summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/renderer/webplugin_delegate_pepper.cc50
-rw-r--r--chrome/renderer/webplugin_delegate_pepper.h14
-rw-r--r--printing/pdf_ps_metafile_cairo.cc36
-rw-r--r--printing/pdf_ps_metafile_cairo.h12
-rw-r--r--printing/pdf_ps_metafile_cairo_unittest.cc18
-rw-r--r--third_party/npapi/bindings/npapi_extensions.h19
6 files changed, 135 insertions, 14 deletions
diff --git a/chrome/renderer/webplugin_delegate_pepper.cc b/chrome/renderer/webplugin_delegate_pepper.cc
index d388f1c..3bb4ee2 100644
--- a/chrome/renderer/webplugin_delegate_pepper.cc
+++ b/chrome/renderer/webplugin_delegate_pepper.cc
@@ -1161,15 +1161,15 @@ int WebPluginDelegatePepper::PrintBegin(const gfx::Rect& printable_area,
current_printer_dpi_ = printer_dpi;
}
}
+#if defined (OS_LINUX)
+ num_pages_ = num_pages;
+ pdf_output_done_ = false;
+#endif // (OS_LINUX)
return num_pages;
}
bool WebPluginDelegatePepper::VectorPrintPage(int page_number,
WebKit::WebCanvas* canvas) {
-#if !defined(OS_WIN) && !defined(OS_MACOSX)
- // TODO(sanjeevr): Add vector print support for Linux.
- return false;
-#endif // !defined(OS_WIN) && !defined(OS_MACOSX)
NPPPrintExtensions* print_extensions = GetPrintExtensions();
if (!print_extensions)
return false;
@@ -1189,13 +1189,40 @@ bool WebPluginDelegatePepper::VectorPrintPage(int page_number,
unsigned char* pdf_output = NULL;
int32 output_size = 0;
- NPError err = print_extensions->printPageAsPDF(instance()->npp(), page_number,
- &pdf_output, &output_size);
+ NPPrintPageNumberRange page_range;
+#if defined(OS_LINUX)
+ // On Linux we will try and output all pages as PDF in the first call to
+ // PrintPage. This is a temporary hack.
+ // TODO(sanjeevr): Remove this hack and fix this by changing the print
+ // interfaces for WebFrame and WebPlugin.
+ if (page_number != 0)
+ return pdf_output_done_;
+ page_range.firstPageNumber = 0;
+ page_range.lastPageNumber = num_pages_ - 1;
+#else // defined(OS_LINUX)
+ page_range.firstPageNumber = page_range.lastPageNumber = page_number;
+#endif // defined(OS_LINUX)
+ NPError err = print_extensions->printPagesAsPDF(instance()->npp(),
+ &page_range, 1,
+ &pdf_output, &output_size);
if (err != NPERR_NO_ERROR)
return false;
bool ret = false;
-#if defined(OS_MACOSX)
+#if defined(OS_LINUX)
+ // On Linux we need to get the backing PdfPsMetafile and write the bits
+ // directly.
+ cairo_t* context = canvas->beginPlatformPaint();
+ printing::NativeMetafile* metafile =
+ printing::NativeMetafile::FromCairoContext(context);
+ DCHECK(metafile);
+ if (metafile) {
+ ret = metafile->SetRawData(pdf_output, output_size);
+ if (ret)
+ pdf_output_done_ = true;
+ }
+ canvas->endPlatformPaint();
+#elif defined(OS_MACOSX)
printing::NativeMetafile metafile;
// Create a PDF metafile and render from there into the passed in context.
if (metafile.Init(pdf_output, output_size)) {
@@ -1335,7 +1362,10 @@ void WebPluginDelegatePepper::PrintEnd() {
current_printer_dpi_ = -1;
#if defined(OS_MACOSX)
last_printed_page_ = SkBitmap();
-#endif // defined(OS_MACOSX)
+#elif defined(OS_LINUX)
+ num_pages_ = 0;
+ pdf_output_done_ = false;
+#endif // defined(OS_LINUX)
}
bool WebPluginDelegatePepper::SupportsFind() {
@@ -1351,6 +1381,10 @@ WebPluginDelegatePepper::WebPluginDelegatePepper(
instance_(instance),
nested_delegate_(NULL),
current_printer_dpi_(-1),
+#if defined (OS_LINUX)
+ num_pages_(0),
+ pdf_output_done_(false),
+#endif // (OS_LINUX)
#if defined(ENABLE_GPU)
command_buffer_(NULL),
#endif
diff --git a/chrome/renderer/webplugin_delegate_pepper.h b/chrome/renderer/webplugin_delegate_pepper.h
index 3524112..e812cd9 100644
--- a/chrome/renderer/webplugin_delegate_pepper.h
+++ b/chrome/renderer/webplugin_delegate_pepper.h
@@ -301,10 +301,22 @@ class WebPluginDelegatePepper : public webkit_glue::WebPluginDelegate,
int current_printer_dpi_;
#if defined(OS_MACOSX)
// On the Mac, when we draw the bitmap to the PDFContext, it seems necessary
- // to keep the pixels valis until CGContextEndPage is called. We use this
+ // to keep the pixels valid until CGContextEndPage is called. We use this
// variable to hold on to the pixels.
SkBitmap last_printed_page_;
#endif // defined(OS_MACOSX)
+#if defined (OS_LINUX)
+ // On Linux, we always send all pages from the renderer to the browser.
+ // So, if the plugin supports printPagesAsPDF we print the entire output
+ // in one shot in the first call to PrintPage.
+ // (This is a temporary hack until we change the WebFrame and WebPlugin print
+ // interfaces).
+ // Specifies the total number of pages to be printed. It it set in PrintBegin.
+ int32 num_pages_;
+ // Specifies whether we have already output all pages. This is used to ignore
+ // subsequent PrintPage requests.
+ bool pdf_output_done_;
+#endif // defined(OS_LINUX)
#if defined(ENABLE_GPU)
// The command buffer used to issue commands to the nested GPU plugin.
diff --git a/printing/pdf_ps_metafile_cairo.cc b/printing/pdf_ps_metafile_cairo.cc
index a4b10b2..47f4c14 100644
--- a/printing/pdf_ps_metafile_cairo.cc
+++ b/printing/pdf_ps_metafile_cairo.cc
@@ -19,6 +19,8 @@
namespace {
+const cairo_user_data_key_t kPdfMetafileKey = {0};
+
// Tests if |surface| is valid.
bool IsSurfaceValid(cairo_surface_t* surface) {
return cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS;
@@ -60,6 +62,10 @@ cairo_status_t WriteCairoStream(void* dst_buffer,
return CAIRO_STATUS_SUCCESS;
}
+void DestroyContextData(void* data) {
+ // Nothing to be done here.
+}
+
} // namespace
namespace printing {
@@ -115,6 +121,8 @@ bool PdfPsMetafile::Init() {
return false;
}
+ cairo_set_user_data(context_, &kPdfMetafileKey, this, DestroyContextData);
+
return true;
}
@@ -133,6 +141,23 @@ bool PdfPsMetafile::Init(const void* src_buffer, uint32 src_buffer_size) {
return true;
}
+bool PdfPsMetafile::SetRawData(const void* src_buffer,
+ uint32 src_buffer_size) {
+ if (!context_) {
+ // If Init has not already been called, just call Init()
+ return Init(src_buffer, src_buffer_size);
+ }
+ // If a context has already been created, remember this data in
+ // raw_override_data_
+ if (src_buffer == NULL || src_buffer_size == 0)
+ return false;
+
+ raw_override_data_ = std::string(reinterpret_cast<const char*>(src_buffer),
+ src_buffer_size);
+
+ return true;
+}
+
cairo_t* PdfPsMetafile::StartPage(double width_in_points,
double height_in_points,
double margin_top_in_points,
@@ -191,6 +216,12 @@ void PdfPsMetafile::Close() {
DCHECK(IsContextValid(context_));
cairo_surface_finish(surface_);
+
+ // If we have raw PDF/PS data set use that instead of what was drawn.
+ if (!raw_override_data_.empty()) {
+ data_ = raw_override_data_;
+ raw_override_data_.clear();
+ }
DCHECK(!data_.empty()); // Make sure we did get something.
CleanUpContext(&context_);
@@ -242,6 +273,11 @@ bool PdfPsMetafile::SaveTo(const base::FileDescriptor& fd) const {
return success;
}
+PdfPsMetafile* PdfPsMetafile::FromCairoContext(cairo_t* context) {
+ return reinterpret_cast<PdfPsMetafile*>(
+ cairo_get_user_data(context, &kPdfMetafileKey));
+}
+
void PdfPsMetafile::CleanUpAll() {
CleanUpContext(&context_);
CleanUpSurface(&surface_);
diff --git a/printing/pdf_ps_metafile_cairo.h b/printing/pdf_ps_metafile_cairo.h
index 24b5d36..7a7b470 100644
--- a/printing/pdf_ps_metafile_cairo.h
+++ b/printing/pdf_ps_metafile_cairo.h
@@ -48,6 +48,12 @@ class PdfPsMetafile {
// Note: Only call in the browser to initialize |data_|.
bool Init(const void* src_buffer, uint32 src_buffer_size);
+ // Sets raw PS/PDF data for the document. This is used when a cairo drawing
+ // surface has already been created. This method will cause all subsequent
+ // drawing on the surface to be discarded (in Close()). If Init() has not yet
+ // been called this method simply calls the second version of Init.
+ bool SetRawData(const void* src_buffer, uint32 src_buffer_size);
+
FileFormat GetFileFormat() const { return format_; }
// Prepares a new cairo surface/context for rendering a new page.
@@ -89,6 +95,10 @@ class PdfPsMetafile {
static const double kBottomMarginInInch;
static const double kLeftMarginInInch;
+ // Returns the PdfPsMetafile object that owns the given context. Returns NULL
+ // if the context was not created by a PdfPdMetafile object.
+ static PdfPsMetafile* FromCairoContext(cairo_t* context);
+
private:
// Cleans up all resources.
void CleanUpAll();
@@ -101,6 +111,8 @@ class PdfPsMetafile {
// Buffer stores PDF/PS contents for entire PDF/PS file.
std::string data_;
+ // Buffer stores raw PDF/PS contents set by SetRawPageData.
+ std::string raw_override_data_;
DISALLOW_COPY_AND_ASSIGN(PdfPsMetafile);
};
diff --git a/printing/pdf_ps_metafile_cairo_unittest.cc b/printing/pdf_ps_metafile_cairo_unittest.cc
index e1b84d0..9273066 100644
--- a/printing/pdf_ps_metafile_cairo_unittest.cc
+++ b/printing/pdf_ps_metafile_cairo_unittest.cc
@@ -10,6 +10,7 @@
#include "base/file_descriptor_posix.h"
#include "base/file_util.h"
+#include "base/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"
typedef struct _cairo cairo_t;
@@ -29,6 +30,7 @@ TEST_F(PdfPsTest, Pdf) {
// Renders page 1.
cairo_t* context = pdf.StartPage(72, 72, 1, 2, 3, 4);
EXPECT_TRUE(context != NULL);
+ EXPECT_EQ(printing::PdfPsMetafile::FromCairoContext(context), &pdf);
// In theory, we should use Cairo to draw something on |context|.
EXPECT_TRUE(pdf.FinishPage());
@@ -63,6 +65,21 @@ TEST_F(PdfPsTest, Pdf) {
// Tests if we can save data.
EXPECT_TRUE(pdf.SaveTo(DevNullFD()));
+
+ // Test overriding the metafile with raw data.
+ printing::PdfPsMetafile pdf3(printing::PdfPsMetafile::PDF);
+ EXPECT_TRUE(pdf3.Init());
+ context = pdf3.StartPage(72, 72, 1, 2, 3, 4);
+ EXPECT_TRUE(context != NULL);
+ std::string test_raw_data = "Dummy PDF";
+ EXPECT_TRUE(pdf3.SetRawData(test_raw_data.c_str(), test_raw_data.size()));
+ EXPECT_TRUE(pdf3.FinishPage());
+ pdf3.Close();
+ size = pdf3.GetDataSize();
+ EXPECT_EQ(test_raw_data.size(), size);
+ std::string output;
+ pdf3.GetData(WriteInto(&output, size + 1), size);
+ EXPECT_EQ(test_raw_data, output);
}
TEST_F(PdfPsTest, Ps) {
@@ -73,6 +90,7 @@ TEST_F(PdfPsTest, Ps) {
// Renders page 1.
cairo_t* context = ps.StartPage(72, 72, 1, 2, 3, 4);
EXPECT_TRUE(context != NULL);
+ EXPECT_EQ(printing::PdfPsMetafile::FromCairoContext(context), &ps);
// In theory, we should use Cairo to draw something on |context|.
EXPECT_TRUE(ps.FinishPage());
diff --git a/third_party/npapi/bindings/npapi_extensions.h b/third_party/npapi/bindings/npapi_extensions.h
index ec0eaf9..0ce4360 100644
--- a/third_party/npapi/bindings/npapi_extensions.h
+++ b/third_party/npapi/bindings/npapi_extensions.h
@@ -952,6 +952,13 @@ struct _NPDeviceContextAudio {
/* Printing related APIs ---------------------------------------------------*/
+/* Defines a contiguous range of pages to be printed. Page numbers use a
+ * zero-based index. */
+typedef struct _NPPrintPageNumberRange {
+ int32_t firstPageNumber;
+ int32_t lastPageNumber;
+} NPPrintPageNumberRange;
+
/* Being a print operation. Returns the total number of pages to print at the
* given printableArea size and DPI. printableArea is in points (a point is 1/72
* of an inch). The plugin is expected to remember the values of printableArea
@@ -975,12 +982,14 @@ typedef NPError (*NPPPrintPageRasterPtr) (
NPDeviceContext2D* printSurface);
/* Ends the print operation */
typedef NPError (*NPPPrintEndPtr) (NPP instance);
-/* Prints the specified page as PDF. The plugin allocates the output buffer
+/* Prints the specified pages as PDF. The plugin allocates the output buffer
* pointed to by pdf_output using the browser-supplied NPN_MemAlloc function.
* The caller is expected to free the output buffer upon success.*/
-typedef NPError (*NPPrintPageAsPDFPtr)(NPP instance, int32_t page_number,
- unsigned char** pdf_output,
- int32_t* output_size);
+typedef NPError (*NPPrintPagesAsPDFPtr)(NPP instance,
+ NPPrintPageNumberRange* page_ranges,
+ int32_t page_range_count,
+ unsigned char** pdf_output,
+ int32_t* output_size);
/* TODO(sanjeevr) : Provide a vector interface for printing. We need to decide
@@ -992,7 +1001,7 @@ typedef struct _NPPPrintExtensions {
NPPGetRasterDimensionsPtr getRasterDimensions;
NPPPrintPageRasterPtr printPageRaster;
NPPPrintEndPtr printEnd;
- NPPrintPageAsPDFPtr printPageAsPDF;
+ NPPrintPagesAsPDFPtr printPagesAsPDF;
} NPPPrintExtensions;
/* Returns NULL if the plugin does not support print extensions */