summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authorsanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-15 20:23:49 +0000
committersanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-15 20:23:49 +0000
commit42a203b4d3c0c1a04b1aa0c6a15a9cd0d98efb61 (patch)
treea5753f394fae951bf191783f2fb9850c8b54fabc /webkit
parent35f39af0f1ff12d950b4175e1d9743724a321f10 (diff)
downloadchromium_src-42a203b4d3c0c1a04b1aa0c6a15a9cd0d98efb61.zip
chromium_src-42a203b4d3c0c1a04b1aa0c6a15a9cd0d98efb61.tar.gz
chromium_src-42a203b4d3c0c1a04b1aa0c6a15a9cd0d98efb61.tar.bz2
Added support for printing of Pepper v2 plugins.
BUG=None TEST=Test printing with Chrome PDF Pepper v2 plugin. Review URL: http://codereview.chromium.org/2819047 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52520 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/glue/plugins/DEPS1
-rw-r--r--webkit/glue/plugins/pepper_buffer.h1
-rw-r--r--webkit/glue/plugins/pepper_plugin_instance.cc375
-rw-r--r--webkit/glue/plugins/pepper_plugin_instance.h50
-rw-r--r--webkit/glue/plugins/pepper_plugin_module.cc5
-rw-r--r--webkit/glue/plugins/pepper_plugin_module.h4
-rw-r--r--webkit/glue/plugins/pepper_webplugin_impl.cc18
-rw-r--r--webkit/glue/plugins/pepper_webplugin_impl.h5
-rw-r--r--webkit/glue/webkit_glue.gypi1
9 files changed, 459 insertions, 1 deletions
diff --git a/webkit/glue/plugins/DEPS b/webkit/glue/plugins/DEPS
index 21f5108..4ac8845 100644
--- a/webkit/glue/plugins/DEPS
+++ b/webkit/glue/plugins/DEPS
@@ -1,3 +1,4 @@
include_rules = [
+ "+printing",
"+third_party/ppapi/c",
]
diff --git a/webkit/glue/plugins/pepper_buffer.h b/webkit/glue/plugins/pepper_buffer.h
index 8b3f031..5d750ec 100644
--- a/webkit/glue/plugins/pepper_buffer.h
+++ b/webkit/glue/plugins/pepper_buffer.h
@@ -20,6 +20,7 @@ class Buffer : public Resource {
virtual ~Buffer();
int size() const { return size_; }
+ unsigned char* mapped_buffer() { return mem_buffer_.get(); }
// Returns true if this buffer is mapped. False means that the buffer is
// either invalid or not mapped.
diff --git a/webkit/glue/plugins/pepper_plugin_instance.cc b/webkit/glue/plugins/pepper_plugin_instance.cc
index 89e8284..35f4cca 100644
--- a/webkit/glue/plugins/pepper_plugin_instance.cc
+++ b/webkit/glue/plugins/pepper_plugin_instance.cc
@@ -5,14 +5,29 @@
#include "webkit/glue/plugins/pepper_plugin_instance.h"
#include "base/logging.h"
+#include "base/histogram.h"
+#if defined(OS_MACOSX)
+#include "base/mac_util.h"
+#include "base/scoped_cftyperef.h"
+#endif
#include "base/scoped_ptr.h"
#include "base/utf_string_conversions.h"
#include "gfx/rect.h"
+#if defined(OS_WIN)
+#include "gfx/codec/jpeg_codec.h"
+#include "gfx/gdi_util.h"
+#endif
+#include "gfx/skia_util.h"
+#include "printing/native_metafile.h"
+#include "printing/units.h"
+#include "skia/ext/vector_platform_device.h"
+#include "skia/ext/platform_canvas.h"
#include "third_party/ppapi/c/pp_instance.h"
#include "third_party/ppapi/c/pp_event.h"
#include "third_party/ppapi/c/pp_rect.h"
#include "third_party/ppapi/c/pp_resource.h"
#include "third_party/ppapi/c/pp_var.h"
+#include "third_party/ppapi/c/ppb_core.h"
#include "third_party/ppapi/c/ppb_find.h"
#include "third_party/ppapi/c/ppb_instance.h"
#include "third_party/ppapi/c/ppp_find.h"
@@ -25,6 +40,7 @@
#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
#include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h"
#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
+#include "webkit/glue/plugins/pepper_buffer.h"
#include "webkit/glue/plugins/pepper_device_context_2d.h"
#include "webkit/glue/plugins/pepper_event_conversion.h"
#include "webkit/glue/plugins/pepper_image_data.h"
@@ -42,6 +58,15 @@ using WebKit::WebPluginContainer;
namespace pepper {
+#if defined(OS_WIN)
+// Exported by pdf.dll
+typedef bool (*RenderPDFPageToDCProc)(
+ const unsigned char* pdf_buffer, int buffer_size, int page_number, HDC dc,
+ int dpi_x, int dpi_y, int bounds_origin_x, int bounds_origin_y,
+ int bounds_width, int bounds_height, bool fit_to_bounds,
+ bool stretch_to_bounds, bool keep_aspect_ratio, bool center_in_bounds);
+#endif // defined(OS_WIN)
+
namespace {
#define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, np_name) \
@@ -202,7 +227,13 @@ PluginInstance::PluginInstance(PluginDelegate* delegate,
full_frame_(false),
find_identifier_(-1),
plugin_find_interface_(NULL),
- plugin_zoom_interface_(NULL) {
+ plugin_zoom_interface_(NULL),
+#if defined (OS_LINUX)
+ num_pages_(0),
+ pdf_output_done_(false),
+#endif // defined (OS_LINUX)
+ plugin_print_interface_(NULL) {
+ memset(&current_print_settings_, 0, sizeof(current_print_settings_));
DCHECK(delegate);
module_->InstanceCreated(this);
delegate_->InstanceCreated(this);
@@ -432,4 +463,346 @@ bool PluginInstance::LoadZoomInterface() {
return !!plugin_zoom_interface_;
}
+bool PluginInstance::GetPreferredPrintOutputFormat(
+ PP_PrintOutputFormat* format) {
+ if (!plugin_print_interface_) {
+ plugin_print_interface_ =
+ reinterpret_cast<const PPP_Printing*>(module_->GetPluginInterface(
+ PPP_PRINTING_INTERFACE));
+ }
+ if (!plugin_print_interface_)
+ return false;
+ uint32_t format_count = 0;
+ PP_PrintOutputFormat* supported_formats =
+ plugin_print_interface_->QuerySupportedFormats(GetPPInstance(),
+ &format_count);
+ if (!supported_formats)
+ return false;
+
+ bool found_supported_format = false;
+ for (uint32_t index = 0; index < format_count; index++) {
+ if (supported_formats[index] == PP_PRINTOUTPUTFORMAT_PDF) {
+ // If we found PDF, we are done.
+ found_supported_format = true;
+ *format = PP_PRINTOUTPUTFORMAT_PDF;
+ break;
+ } else if (supported_formats[index] == PP_PRINTOUTPUTFORMAT_RASTER) {
+ // We found raster. Keep looking.
+ found_supported_format = true;
+ *format = PP_PRINTOUTPUTFORMAT_RASTER;
+ }
+ }
+ PluginModule::GetCore()->MemFree(supported_formats);
+ return found_supported_format;
+}
+
+bool PluginInstance::SupportsPrintInterface() {
+ PP_PrintOutputFormat format;
+ return GetPreferredPrintOutputFormat(&format);
+}
+
+int PluginInstance::PrintBegin(const gfx::Rect& printable_area,
+ int printer_dpi) {
+ PP_PrintOutputFormat format;
+ if (!GetPreferredPrintOutputFormat(&format)) {
+ // PrintBegin should not have been called since SupportsPrintInterface
+ // would have returned false;
+ NOTREACHED();
+ return 0;
+ }
+
+ PP_PrintSettings print_settings;
+ RectToPPRect(printable_area, &print_settings.printable_area);
+ print_settings.dpi = printer_dpi;
+ print_settings.orientation = PP_PRINTORIENTATION_NORMAL;
+ print_settings.grayscale = false;
+ print_settings.format = format;
+ int num_pages = plugin_print_interface_->Begin(GetPPInstance(),
+ &print_settings);
+ if (!num_pages)
+ return 0;
+ current_print_settings_ = print_settings;
+#if defined (OS_LINUX)
+ num_pages_ = num_pages;
+ pdf_output_done_ = false;
+#endif // (OS_LINUX)
+ return num_pages;
+}
+
+bool PluginInstance::PrintPage(int page_number, WebKit::WebCanvas* canvas) {
+ DCHECK(plugin_print_interface_);
+ PP_PrintPageNumberRange page_range;
+#if defined(OS_LINUX)
+ if (current_print_settings_.format == PP_PRINTOUTPUTFORMAT_PDF) {
+ // 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.first_page_number = 0;
+ page_range.last_page_number = num_pages_ - 1;
+ }
+#else // defined(OS_LINUX)
+ page_range.first_page_number = page_range.last_page_number = page_number;
+#endif // defined(OS_LINUX)
+
+ PP_Resource print_output =
+ plugin_print_interface_->PrintPages(GetPPInstance(), &page_range, 1);
+
+ if (!print_output)
+ return false;
+
+ bool ret = false;
+
+ if (current_print_settings_.format == PP_PRINTOUTPUTFORMAT_PDF)
+ ret = PrintPDFOutput(print_output, canvas);
+ else if (current_print_settings_.format == PP_PRINTOUTPUTFORMAT_RASTER)
+ ret = PrintRasterOutput(print_output, canvas);
+
+ // Now we need to release the print output resource.
+ PluginModule::GetCore()->ReleaseResource(print_output);
+
+ return ret;
+}
+
+void PluginInstance::PrintEnd() {
+ DCHECK(plugin_print_interface_);
+ if (plugin_print_interface_)
+ plugin_print_interface_->End(GetPPInstance());
+ memset(&current_print_settings_, 0, sizeof(current_print_settings_));
+#if defined(OS_MACOSX)
+ last_printed_page_ = SkBitmap();
+#elif defined(OS_LINUX)
+ num_pages_ = 0;
+ pdf_output_done_ = false;
+#endif // defined(OS_LINUX)
+}
+
+bool PluginInstance::PrintPDFOutput(PP_Resource print_output,
+ WebKit::WebCanvas* canvas) {
+ scoped_refptr<Buffer> buffer(Resource::GetAs<Buffer>(print_output));
+ if (!buffer.get() || !buffer->is_mapped() || !buffer->size()) {
+ NOTREACHED();
+ return false;
+ }
+#if defined(OS_WIN)
+ // For Windows, we need the PDF DLL to render the output PDF to a DC.
+ HMODULE pdf_module = GetModuleHandle(L"pdf.dll");
+ if (!pdf_module)
+ return false;
+ RenderPDFPageToDCProc render_proc =
+ reinterpret_cast<RenderPDFPageToDCProc>(
+ GetProcAddress(pdf_module, "RenderPDFPageToDC"));
+ if (!render_proc)
+ return false;
+#endif // defined(OS_WIN)
+
+ bool ret = false;
+#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(buffer->mapped_buffer(), buffer->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(buffer->mapped_buffer(), buffer->size())) {
+ // Flip the transform.
+ CGContextSaveGState(canvas);
+ CGContextTranslateCTM(canvas, 0,
+ current_print_settings_.printable_area.size.height);
+ CGContextScaleCTM(canvas, 1.0, -1.0);
+ CGRect page_rect;
+ page_rect.origin.x = current_print_settings_.printable_area.point.x;
+ page_rect.origin.y = current_print_settings_.printable_area.point.y;
+ page_rect.size.width = current_print_settings_.printable_area.size.width;
+ page_rect.size.height = current_print_settings_.printable_area.size.height;
+
+ ret = metafile.RenderPage(1, canvas, page_rect, true, false, true, true);
+ CGContextRestoreGState(canvas);
+ }
+#elif defined(OS_WIN)
+ // On Windows, we now need to render the PDF to the DC that backs the
+ // supplied canvas.
+ skia::VectorPlatformDevice& device =
+ static_cast<skia::VectorPlatformDevice&>(
+ canvas->getTopPlatformDevice());
+ HDC dc = device.getBitmapDC();
+ gfx::Size size_in_pixels;
+ size_in_pixels.set_width(
+ printing::ConvertUnit(current_print_settings_.printable_area.size.width,
+ static_cast<int>(printing::kPointsPerInch),
+ current_print_settings_.dpi));
+ size_in_pixels.set_height(
+ printing::ConvertUnit(current_print_settings_.printable_area.size.height,
+ static_cast<int>(printing::kPointsPerInch),
+ current_print_settings_.dpi));
+ // We need to render using the actual printer DPI (rendering to a smaller
+ // set of pixels leads to a blurry output). However, we need to counter the
+ // scaling up that will happen in the browser.
+ XFORM xform = {0};
+ xform.eM11 = xform.eM22 = static_cast<float>(printing::kPointsPerInch) /
+ static_cast<float>(current_print_settings_.dpi);
+ ModifyWorldTransform(dc, &xform, MWT_LEFTMULTIPLY);
+
+ ret = render_proc(buffer->mapped_buffer(), buffer->size(), 0, dc,
+ current_print_settings_.dpi, current_print_settings_.dpi,
+ 0, 0, size_in_pixels.width(),
+ size_in_pixels.height(), true, false, true, true);
+#endif // defined(OS_WIN)
+
+ return ret;
+}
+
+bool PluginInstance::PrintRasterOutput(PP_Resource print_output,
+ WebKit::WebCanvas* canvas) {
+ scoped_refptr<ImageData> image(Resource::GetAs<ImageData>(print_output));
+ if (!image.get() || !image->is_mapped())
+ return false;
+
+ const SkBitmap* bitmap = image->GetMappedBitmap();
+ if (!bitmap)
+ return false;
+
+ // Draw the printed image into the supplied canvas.
+ SkIRect src_rect;
+ src_rect.set(0, 0, bitmap->width(), bitmap->height());
+ SkRect dest_rect;
+ dest_rect.set(
+ SkIntToScalar(current_print_settings_.printable_area.point.x),
+ SkIntToScalar(current_print_settings_.printable_area.point.y),
+ SkIntToScalar(current_print_settings_.printable_area.point.x +
+ current_print_settings_.printable_area.size.width),
+ SkIntToScalar(current_print_settings_.printable_area.point.y +
+ current_print_settings_.printable_area.size.height));
+ bool draw_to_canvas = true;
+ gfx::Rect dest_rect_gfx;
+ dest_rect_gfx.set_x(current_print_settings_.printable_area.point.x);
+ dest_rect_gfx.set_y(current_print_settings_.printable_area.point.y);
+ dest_rect_gfx.set_width(current_print_settings_.printable_area.size.width);
+ dest_rect_gfx.set_height(current_print_settings_.printable_area.size.height);
+
+#if defined(OS_WIN)
+ // Since this is a raster output, the size of the bitmap can be
+ // huge (especially at high printer DPIs). On Windows, this can
+ // result in a HUGE EMF (on Mac and Linux the output goes to PDF
+ // which appears to Flate compress the bitmap). So, if this bitmap
+ // is larger than 20 MB, we save the bitmap as a JPEG into the EMF
+ // DC. Note: We chose JPEG over PNG because JPEG compression seems
+ // way faster (about 4 times faster).
+ static const int kCompressionThreshold = 20 * 1024 * 1024;
+ if (bitmap->getSize() > kCompressionThreshold) {
+ DrawJPEGToPlatformDC(*bitmap, dest_rect_gfx, canvas);
+ draw_to_canvas = false;
+ }
+#endif // defined(OS_WIN)
+#if defined(OS_MACOSX)
+ draw_to_canvas = false;
+ DrawSkBitmapToCanvas(*bitmap, canvas, dest_rect_gfx,
+ current_print_settings_.printable_area.size.height);
+ // See comments in the header file.
+ last_printed_page_ = *bitmap;
+#else // defined(OS_MACOSX)
+ if (draw_to_canvas)
+ canvas->drawBitmapRect(*bitmap, &src_rect, dest_rect);
+#endif // defined(OS_MACOSX)
+ return true;
+}
+
+#if defined(OS_WIN)
+bool PluginInstance::DrawJPEGToPlatformDC(
+ const SkBitmap& bitmap,
+ const gfx::Rect& printable_area,
+ WebKit::WebCanvas* canvas) {
+ skia::VectorPlatformDevice& device =
+ static_cast<skia::VectorPlatformDevice&>(
+ canvas->getTopPlatformDevice());
+ HDC dc = device.getBitmapDC();
+ // TODO(sanjeevr): This is a temporary hack. If we output a JPEG
+ // to the EMF, the EnumEnhMetaFile call fails in the browser
+ // process. The failure also happens if we output nothing here.
+ // We need to investigate the reason for this failure and fix it.
+ // In the meantime this temporary hack of drawing an empty
+ // rectangle in the DC gets us by.
+ Rectangle(dc, 0, 0, 0, 0);
+
+ // Ideally we should add JPEG compression to the VectorPlatformDevice class
+ // However, Skia currently has no JPEG compression code and we cannot
+ // depend on gfx/jpeg_codec.h in Skia. So we do the compression here.
+ SkAutoLockPixels lock(bitmap);
+ DCHECK(bitmap.getConfig() == SkBitmap::kARGB_8888_Config);
+ const uint32_t* pixels =
+ static_cast<const uint32_t*>(bitmap.getPixels());
+ std::vector<unsigned char> compressed_image;
+ base::TimeTicks start_time = base::TimeTicks::Now();
+ bool encoded = gfx::JPEGCodec::Encode(
+ reinterpret_cast<const unsigned char*>(pixels),
+ gfx::JPEGCodec::FORMAT_BGRA, bitmap.width(), bitmap.height(),
+ static_cast<int>(bitmap.rowBytes()), 100, &compressed_image);
+ UMA_HISTOGRAM_TIMES("PepperPluginPrint.RasterBitmapCompressTime",
+ base::TimeTicks::Now() - start_time);
+ if (!encoded) {
+ NOTREACHED();
+ return false;
+ }
+ BITMAPINFOHEADER bmi = {0};
+ gfx::CreateBitmapHeader(bitmap.width(), bitmap.height(), &bmi);
+ bmi.biCompression = BI_JPEG;
+ bmi.biSizeImage = compressed_image.size();
+ bmi.biHeight = -bmi.biHeight;
+ StretchDIBits(dc, printable_area.x(), printable_area.y(),
+ printable_area.width(), printable_area.height(),
+ 0, 0, bitmap.width(), bitmap.height(),
+ &compressed_image.front(),
+ reinterpret_cast<const BITMAPINFO*>(&bmi),
+ DIB_RGB_COLORS, SRCCOPY);
+ return true;
+}
+#endif // OS_WIN
+
+#if defined(OS_MACOSX)
+void PluginInstance::DrawSkBitmapToCanvas(
+ const SkBitmap& bitmap, WebKit::WebCanvas* canvas,
+ const gfx::Rect& dest_rect,
+ int canvas_height) {
+ SkAutoLockPixels lock(bitmap);
+ DCHECK(bitmap.getConfig() == SkBitmap::kARGB_8888_Config);
+ scoped_cftyperef<CGDataProviderRef> data_provider(
+ CGDataProviderCreateWithData(
+ NULL, bitmap.getAddr32(0, 0),
+ bitmap.rowBytes() * bitmap.height(), NULL));
+ scoped_cftyperef<CGImageRef> image(
+ CGImageCreate(
+ bitmap.width(), bitmap.height(),
+ 8, 32, bitmap.rowBytes(),
+ mac_util::GetSystemColorSpace(),
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
+ data_provider, NULL, false, kCGRenderingIntentDefault));
+
+ // Flip the transform
+ CGContextSaveGState(canvas);
+ CGContextTranslateCTM(canvas, 0, canvas_height);
+ CGContextScaleCTM(canvas, 1.0, -1.0);
+
+ CGRect bounds;
+ bounds.origin.x = dest_rect.x();
+ bounds.origin.y = canvas_height - dest_rect.y() - dest_rect.height();
+ bounds.size.width = dest_rect.width();
+ bounds.size.height = dest_rect.height();
+
+ CGContextDrawImage(canvas, bounds, image);
+ CGContextRestoreGState(canvas);
+}
+#endif // defined(OS_MACOSX)
+
+
} // namespace pepper
diff --git a/webkit/glue/plugins/pepper_plugin_instance.h b/webkit/glue/plugins/pepper_plugin_instance.h
index 0ed2603..4528a99 100644
--- a/webkit/glue/plugins/pepper_plugin_instance.h
+++ b/webkit/glue/plugins/pepper_plugin_instance.h
@@ -16,6 +16,8 @@
#include "third_party/ppapi/c/pp_cursor_type.h"
#include "third_party/ppapi/c/pp_instance.h"
#include "third_party/ppapi/c/pp_resource.h"
+#include "third_party/ppapi/c/ppp_printing.h"
+#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/WebKit/WebKit/chromium/public/WebCanvas.h"
typedef struct _pp_Var PP_Var;
@@ -25,6 +27,8 @@ typedef struct _ppp_Find PPP_Find;
typedef struct _ppp_Instance PPP_Instance;
typedef struct _ppp_Zoom PPP_Zoom;
+class SkBitmap;
+
namespace gfx {
class Rect;
}
@@ -114,10 +118,32 @@ class PluginInstance : public base::RefCounted<PluginInstance> {
void SelectFindResult(bool forward);
void StopFind();
+ bool SupportsPrintInterface();
+ int PrintBegin(const gfx::Rect& printable_area, int printer_dpi);
+ bool PrintPage(int page_number, WebKit::WebCanvas* canvas);
+ void PrintEnd();
+
private:
bool LoadFindInterface();
bool LoadZoomInterface();
+ // Queries the plugin for supported print formats and sets |format| to the
+ // best format to use. Returns false if the plugin does not support any
+ // print format that we can handle (we can handle raster and PDF).
+ bool GetPreferredPrintOutputFormat(PP_PrintOutputFormat* format);
+ bool PrintPDFOutput(PP_Resource print_output, WebKit::WebCanvas* canvas);
+ bool PrintRasterOutput(PP_Resource print_output, WebKit::WebCanvas* canvas);
+#if defined(OS_WIN)
+ bool DrawJPEGToPlatformDC(const SkBitmap& bitmap,
+ const gfx::Rect& printable_area,
+ WebKit::WebCanvas* canvas);
+#elif defined(OS_MACOSX)
+ // Draws the given kARGB_8888_Config bitmap to the specified canvas starting
+ // at the specified destination rect.
+ void DrawSkBitmapToCanvas(const SkBitmap& bitmap, WebKit::WebCanvas* canvas,
+ const gfx::Rect& dest_rect, int canvas_height);
+#endif // OS_MACOSX
+
PluginDelegate* delegate_;
scoped_refptr<PluginModule> module_;
const PPP_Instance* instance_interface_;
@@ -149,6 +175,30 @@ class PluginInstance : public base::RefCounted<PluginInstance> {
const PPP_Find* plugin_find_interface_;
const PPP_Zoom* plugin_zoom_interface_;
+ // This is only valid between a successful PrintBegin call and a PrintEnd
+ // call.
+ PP_PrintSettings current_print_settings_;
+#if defined(OS_MACOSX)
+ // On the Mac, when we draw the bitmap to the PDFContext, it seems necessary
+ // to keep the pixels valid until CGContextEndPage is called. We use this
+ // variable to hold on to the pixels.
+ SkBitmap last_printed_page_;
+#elif 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)
+
+ // The plugin print interface.
+ const PPP_Printing* plugin_print_interface_;
+
// Containes the cursor if it's set by the plugin.
scoped_ptr<WebKit::WebCursorInfo> cursor_;
diff --git a/webkit/glue/plugins/pepper_plugin_module.cc b/webkit/glue/plugins/pepper_plugin_module.cc
index 22b9e98..ff73f89 100644
--- a/webkit/glue/plugins/pepper_plugin_module.cc
+++ b/webkit/glue/plugins/pepper_plugin_module.cc
@@ -251,6 +251,11 @@ PluginModule* PluginModule::FromPPModule(PP_Module module) {
return lib;
}
+// static
+const PPB_Core* PluginModule::GetCore() {
+ return &core_interface;
+}
+
bool PluginModule::InitFromEntryPoints(const EntryPoints& entry_points) {
if (initialized_)
return true;
diff --git a/webkit/glue/plugins/pepper_plugin_module.h b/webkit/glue/plugins/pepper_plugin_module.h
index 1b2d9fb..6bfeccf 100644
--- a/webkit/glue/plugins/pepper_plugin_module.h
+++ b/webkit/glue/plugins/pepper_plugin_module.h
@@ -14,6 +14,8 @@
#include "third_party/ppapi/c/pp_module.h"
#include "third_party/ppapi/c/ppb.h"
+typedef struct _ppb_Core PPB_Core;
+
namespace pepper {
class PluginDelegate;
@@ -47,6 +49,8 @@ class PluginModule : public base::RefCounted<PluginModule> {
// if the module is invalid.
static PluginModule* FromPPModule(PP_Module module);
+ static const PPB_Core* GetCore();
+
PP_Module GetPPModule() const;
PluginInstance* CreateInstance(PluginDelegate* delegate);
diff --git a/webkit/glue/plugins/pepper_webplugin_impl.cc b/webkit/glue/plugins/pepper_webplugin_impl.cc
index 6be3997..df8aae0 100644
--- a/webkit/glue/plugins/pepper_webplugin_impl.cc
+++ b/webkit/glue/plugins/pepper_webplugin_impl.cc
@@ -175,4 +175,22 @@ void WebPluginImpl::stopFind() {
instance_->StopFind();
}
+bool WebPluginImpl::supportsPaginatedPrint() {
+ return instance_->SupportsPrintInterface();
+}
+
+int WebPluginImpl::printBegin(const WebKit::WebRect& printable_area,
+ int printer_dpi) {
+ return instance_->PrintBegin(printable_area, printer_dpi);
+}
+
+bool WebPluginImpl::printPage(int page_number,
+ WebKit::WebCanvas* canvas) {
+ return instance_->PrintPage(page_number, canvas);
+}
+
+void WebPluginImpl::printEnd() {
+ return instance_->PrintEnd();
+}
+
} // namespace pepper
diff --git a/webkit/glue/plugins/pepper_webplugin_impl.h b/webkit/glue/plugins/pepper_webplugin_impl.h
index 8d950c9..9d2f313 100644
--- a/webkit/glue/plugins/pepper_webplugin_impl.h
+++ b/webkit/glue/plugins/pepper_webplugin_impl.h
@@ -69,6 +69,11 @@ class WebPluginImpl : public WebKit::WebPlugin {
int identifier);
virtual void selectFindResult(bool forward);
virtual void stopFind();
+ virtual bool supportsPaginatedPrint();
+ virtual int printBegin(const WebKit::WebRect& printable_area,
+ int printer_dpi);
+ virtual bool printPage(int page_number, WebKit::WebCanvas* canvas);
+ virtual void printEnd();
struct InitData {
scoped_refptr<PluginModule> module;
diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi
index 75631bf..c1a467a 100644
--- a/webkit/glue/webkit_glue.gypi
+++ b/webkit/glue/webkit_glue.gypi
@@ -112,6 +112,7 @@
'<(DEPTH)/app/app.gyp:app_base',
'<(DEPTH)/base/base.gyp:base_i18n',
'<(DEPTH)/net/net.gyp:net',
+ '<(DEPTH)/printing/printing.gyp:printing',
'<(DEPTH)/skia/skia.gyp:skia',
'<(DEPTH)/third_party/icu/icu.gyp:icui18n',
'<(DEPTH)/third_party/icu/icu.gyp:icuuc',