From be44f2f511cd692192b2668d40c4226ab3b60ce7 Mon Sep 17 00:00:00 2001 From: "kmadhusu@chromium.org" Date: Wed, 28 Sep 2011 03:07:34 +0000 Subject: [PATCH] Reland 103021: Printing preview of a PDF on Mac with Skia only previews the last page of the PDF BUG=93145 TEST=Please refer to bug report. Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=103021 Original review URL: codereview.chromium.org/7719014 Please refer to trybot results in the last patch of original review url. Review URL: http://codereview.chromium.org/8059034 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@103082 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/renderer/print_web_view_helper.h | 3 +- .../renderer/print_web_view_helper_linux.cc | 6 +-- chrome/renderer/print_web_view_helper_mac.mm | 13 +++--- chrome/renderer/print_web_view_helper_win.cc | 6 +-- printing/metafile_skia_wrapper.cc | 34 +++----------- printing/metafile_skia_wrapper.h | 8 +--- skia/ext/platform_device.cc | 45 +++++++++++++++++++ skia/ext/platform_device.h | 12 +++++ webkit/plugins/ppapi/ppapi_plugin_instance.cc | 23 ++++++---- webkit/plugins/ppapi/ppapi_plugin_instance.h | 16 +++---- 10 files changed, 101 insertions(+), 65 deletions(-) diff --git a/chrome/renderer/print_web_view_helper.h b/chrome/renderer/print_web_view_helper.h index 7d0a8ea51925..1884f9f95e4b 100644 --- a/chrome/renderer/print_web_view_helper.h +++ b/chrome/renderer/print_web_view_helper.h @@ -234,7 +234,8 @@ class PrintWebViewHelper : public RenderViewObserver, #elif defined(OS_MACOSX) void RenderPage(const gfx::Size& page_size, const gfx::Rect& content_area, const float& scale_factor, int page_number, - WebKit::WebFrame* frame, printing::Metafile* metafile); + WebKit::WebFrame* frame, bool is_preview, + printing::Metafile* metafile); #elif defined(OS_POSIX) bool RenderPages(const PrintMsg_PrintPages_Params& params, WebKit::WebFrame* frame, const WebKit::WebNode& node, diff --git a/chrome/renderer/print_web_view_helper_linux.cc b/chrome/renderer/print_web_view_helper_linux.cc index 7d93a8413844..4d03b35b426e 100644 --- a/chrome/renderer/print_web_view_helper_linux.cc +++ b/chrome/renderer/print_web_view_helper_linux.cc @@ -14,6 +14,7 @@ #include "printing/metafile_impl.h" #include "printing/metafile_skia_wrapper.h" #include "printing/page_size_margins.h" +#include "skia/ext/platform_device.h" #include "skia/ext/vector_canvas.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" @@ -208,9 +209,8 @@ void PrintWebViewHelper::PrintPageInternal( // can't be a stack object. SkRefPtr canvas = new skia::VectorCanvas(device); canvas->unref(); // SkRefPtr and new both took a reference. - printing::MetafileSkiaWrapper::SetMetafileOnCanvas(canvas.get(), metafile); - printing::MetafileSkiaWrapper::SetDraftMode(canvas.get(), - is_print_ready_metafile_sent_); + printing::MetafileSkiaWrapper::SetMetafileOnCanvas(*canvas, metafile); + skia::SetIsDraftMode(*canvas, is_print_ready_metafile_sent_); frame->printPage(params.page_number, canvas.get()); if (params.params.display_header_footer) { diff --git a/chrome/renderer/print_web_view_helper_mac.mm b/chrome/renderer/print_web_view_helper_mac.mm index 0e8c3b24133f..1700f669af18 100644 --- a/chrome/renderer/print_web_view_helper_mac.mm +++ b/chrome/renderer/print_web_view_helper_mac.mm @@ -17,6 +17,7 @@ #if defined(USE_SKIA) #include "printing/metafile_skia_wrapper.h" +#include "skia/ext/platform_device.h" #include "skia/ext/vector_canvas.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebCanvas.h" #endif @@ -37,7 +38,7 @@ // Render page for printing. gfx::Rect content_area(params.params.printable_size); RenderPage(params.params.printable_size, content_area, scale_factor, - page_number, frame, &metafile); + page_number, frame, false, &metafile); metafile.FinishDocument(); PrintHostMsg_DidPrintPage_Params page_params; @@ -96,7 +97,7 @@ base::TimeTicks begin_time = base::TimeTicks::Now(); RenderPage(printParams.page_size, content_area, scale_factor, page_number, - print_preview_context_.frame(), initial_render_metafile); + print_preview_context_.frame(), true, initial_render_metafile); print_preview_context_.RenderedPreviewPage( base::TimeTicks::Now() - begin_time); @@ -144,7 +145,7 @@ void PrintWebViewHelper::RenderPage( const gfx::Size& page_size, const gfx::Rect& content_area, const float& scale_factor, int page_number, WebFrame* frame, - printing::Metafile* metafile) { + bool is_preview, printing::Metafile* metafile) { { #if defined(USE_SKIA) @@ -156,9 +157,9 @@ SkRefPtr canvas = new skia::VectorCanvas(device); canvas->unref(); // SkRefPtr and new both took a reference. WebKit::WebCanvas* canvas_ptr = canvas.get(); - printing::MetafileSkiaWrapper::SetMetafileOnCanvas(canvas.get(), metafile); - printing::MetafileSkiaWrapper::SetDraftMode(canvas.get(), - is_print_ready_metafile_sent_); + printing::MetafileSkiaWrapper::SetMetafileOnCanvas(*canvas, metafile); + skia::SetIsDraftMode(*canvas, is_print_ready_metafile_sent_); + skia::SetIsPreviewMetafile(*canvas, is_preview); #else bool success = metafile->StartPage(page_size, content_area, scale_factor); DCHECK(success); diff --git a/chrome/renderer/print_web_view_helper_win.cc b/chrome/renderer/print_web_view_helper_win.cc index 4ceef0bef28b..fe8e6b6b43ed 100644 --- a/chrome/renderer/print_web_view_helper_win.cc +++ b/chrome/renderer/print_web_view_helper_win.cc @@ -193,9 +193,9 @@ Metafile* PrintWebViewHelper::RenderPage( SkRefPtr canvas = new skia::VectorCanvas(device); canvas->unref(); // SkRefPtr and new both took a reference. if (is_preview) { - printing::MetafileSkiaWrapper::SetMetafileOnCanvas(canvas.get(), metafile); - printing::MetafileSkiaWrapper::SetDraftMode(canvas.get(), - is_print_ready_metafile_sent_); + printing::MetafileSkiaWrapper::SetMetafileOnCanvas(*canvas, metafile); + skia::SetIsDraftMode(*canvas, is_print_ready_metafile_sent_); + skia::SetIsPreviewMetafile(*canvas, is_preview); } float webkit_scale_factor = frame->printPage(page_number, canvas.get()); diff --git a/printing/metafile_skia_wrapper.cc b/printing/metafile_skia_wrapper.cc index cc7fa0880417..ee24a667dba7 100644 --- a/printing/metafile_skia_wrapper.cc +++ b/printing/metafile_skia_wrapper.cc @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/logging.h" #include "printing/metafile_skia_wrapper.h" +#include "skia/ext/platform_device.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkDevice.h" #include "third_party/skia/include/core/SkMetaData.h" @@ -12,34 +12,25 @@ namespace printing { namespace { -const char* kDraftModeKey = "CrDraftMode"; const char* kMetafileKey = "CrMetafile"; -SkMetaData& getMetaData(SkCanvas* canvas) { - DCHECK(canvas != NULL); - - SkDevice* device = canvas->getDevice(); - DCHECK(device != NULL); - return device->getMetaData(); -} - } // namespace // static -void MetafileSkiaWrapper::SetMetafileOnCanvas(SkCanvas* canvas, +void MetafileSkiaWrapper::SetMetafileOnCanvas(const SkCanvas& canvas, Metafile* metafile) { MetafileSkiaWrapper* wrapper = NULL; if (metafile) wrapper = new MetafileSkiaWrapper(metafile); - SkMetaData& meta = getMetaData(canvas); + SkMetaData& meta = skia::getMetaData(canvas); meta.setRefCnt(kMetafileKey, wrapper); SkSafeUnref(wrapper); } // static -Metafile* MetafileSkiaWrapper::GetMetafileFromCanvas(SkCanvas* canvas) { - SkMetaData& meta = getMetaData(canvas); +Metafile* MetafileSkiaWrapper::GetMetafileFromCanvas(const SkCanvas& canvas) { + SkMetaData& meta = skia::getMetaData(canvas); SkRefCnt* value; if (!meta.findRefCnt(kMetafileKey, &value) || !value) return NULL; @@ -47,21 +38,6 @@ Metafile* MetafileSkiaWrapper::GetMetafileFromCanvas(SkCanvas* canvas) { return static_cast(value)->metafile_; } -// static -void MetafileSkiaWrapper::SetDraftMode(SkCanvas* canvas, bool draft_mode) { - SkMetaData& meta = getMetaData(canvas); - meta.setBool(kDraftModeKey, draft_mode); -} - -// static -bool MetafileSkiaWrapper::GetDraftMode(SkCanvas* canvas) { - SkMetaData& meta = getMetaData(canvas); - bool draft_mode; - if (!meta.findBool(kDraftModeKey, &draft_mode)) - draft_mode = false; - return draft_mode; -} - MetafileSkiaWrapper::MetafileSkiaWrapper(Metafile* metafile) : metafile_(metafile) { } diff --git a/printing/metafile_skia_wrapper.h b/printing/metafile_skia_wrapper.h index 40e26e82786d..901044964ffc 100644 --- a/printing/metafile_skia_wrapper.h +++ b/printing/metafile_skia_wrapper.h @@ -20,13 +20,9 @@ class Metafile; // as long as the canvas. class PRINTING_EXPORT MetafileSkiaWrapper : public SkRefCnt { public: - static void SetMetafileOnCanvas(SkCanvas* canvas, Metafile* metafile); + static void SetMetafileOnCanvas(const SkCanvas& canvas, Metafile* metafile); - static Metafile* GetMetafileFromCanvas(SkCanvas* canvas); - - static void SetDraftMode(SkCanvas* canvas, bool draft_mode); - - static bool GetDraftMode(SkCanvas* canvas); + static Metafile* GetMetafileFromCanvas(const SkCanvas& canvas); private: explicit MetafileSkiaWrapper(Metafile* metafile); diff --git a/skia/ext/platform_device.cc b/skia/ext/platform_device.cc index 9e1dde76667d..6292273a8b51 100644 --- a/skia/ext/platform_device.cc +++ b/skia/ext/platform_device.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/logging.h" #include "skia/ext/platform_device.h" #include "third_party/skia/include/core/SkMetaData.h" @@ -9,9 +10,29 @@ namespace skia { namespace { + const char* kDevicePlatformBehaviour = "CrDevicePlatformBehaviour"; +const char* kDraftModeKey = "CrDraftMode"; + +#if defined(OS_MACOSX) || defined(OS_WIN) +const char* kIsPreviewMetafileKey = "CrIsPreviewMetafile"; +#endif + +void SetBoolMetaData(const SkCanvas& canvas, const char* key, bool value) { + SkMetaData& meta = skia::getMetaData(canvas); + meta.setBool(key, value); +} + +bool GetBoolMetaData(const SkCanvas& canvas, const char* key) { + bool value; + SkMetaData& meta = skia::getMetaData(canvas); + if (!meta.findBool(key, &value)) + value = false; + return value; } +} // namespace + void SetPlatformDevice(SkDevice* device, PlatformDevice* platform_behaviour) { SkMetaData& meta_data = device->getMetaData(); meta_data.setPtr(kDevicePlatformBehaviour, platform_behaviour); @@ -27,6 +48,30 @@ PlatformDevice* GetPlatformDevice(SkDevice* device) { return NULL; } +SkMetaData& getMetaData(const SkCanvas& canvas) { + SkDevice* device = canvas.getDevice(); + DCHECK(device != NULL); + return device->getMetaData(); +} + +void SetIsDraftMode(const SkCanvas& canvas, bool draft_mode) { + SetBoolMetaData(canvas, kDraftModeKey, draft_mode); +} + +bool IsDraftMode(const SkCanvas& canvas) { + return GetBoolMetaData(canvas, kDraftModeKey); +} + +#if defined(OS_MACOSX) || defined(OS_WIN) +void SetIsPreviewMetafile(const SkCanvas& canvas, bool is_preview) { + SetBoolMetaData(canvas, kIsPreviewMetafileKey, is_preview); +} + +bool IsPreviewMetafile(const SkCanvas& canvas) { + return GetBoolMetaData(canvas, kIsPreviewMetafileKey); +} +#endif + bool PlatformDevice::IsNativeFontRenderingAllowed() { return true; } diff --git a/skia/ext/platform_device.h b/skia/ext/platform_device.h index 179a8e8bfa33..3973f8a3d72a 100644 --- a/skia/ext/platform_device.h +++ b/skia/ext/platform_device.h @@ -18,6 +18,7 @@ #include "third_party/skia/include/core/SkColor.h" class SkMatrix; +class SkMetaData; class SkPath; class SkRegion; @@ -78,6 +79,17 @@ SK_API void InitializeDC(HDC context); SK_API CGContextRef GetBitmapContext(SkDevice* device); #endif +// Following routines are used in print preview workflow to mark the draft mode +// metafile and preview metafile. +SK_API SkMetaData& getMetaData(const SkCanvas& canvas); +SK_API void SetIsDraftMode(const SkCanvas& canvas, bool draft_mode); +SK_API bool IsDraftMode(const SkCanvas& canvas); + +#if defined(OS_MACOSX) || defined(OS_WIN) +SK_API void SetIsPreviewMetafile(const SkCanvas& canvas, bool is_preview); +SK_API bool IsPreviewMetafile(const SkCanvas& canvas); +#endif + // A SkDevice is basically a wrapper around SkBitmap that provides a surface for // SkCanvas to draw into. PlatformDevice provides a surface Windows can also // write to. It also provides functionality to play well with GDI drawing diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.cc b/webkit/plugins/ppapi/ppapi_plugin_instance.cc index 4ec22da3d447..cee7108aac41 100644 --- a/webkit/plugins/ppapi/ppapi_plugin_instance.cc +++ b/webkit/plugins/ppapi/ppapi_plugin_instance.cc @@ -851,10 +851,10 @@ int PluginInstance::PrintBegin(const gfx::Rect& printable_area, if (!num_pages) return 0; current_print_settings_ = print_settings; -#if defined(OS_LINUX) || defined(OS_WIN) +#if defined(USE_SKIA) canvas_ = NULL; ranges_.clear(); -#endif // OS_LINUX || OS_WIN +#endif // USE_SKIA return num_pages; } @@ -862,14 +862,19 @@ bool PluginInstance::PrintPage(int page_number, WebKit::WebCanvas* canvas) { DCHECK(plugin_print_interface_); PP_PrintPageNumberRange_Dev page_range; page_range.first_page_number = page_range.last_page_number = page_number; -#if defined(OS_LINUX) || defined(OS_WIN) +#if defined(USE_SKIA) // The canvas only has a metafile on it for print preview. - if (printing::MetafileSkiaWrapper::GetMetafileFromCanvas(canvas)) { + bool save_for_later = + (printing::MetafileSkiaWrapper::GetMetafileFromCanvas(*canvas) != NULL); +#if defined(OS_MACOSX) || defined(OS_WIN) + save_for_later = save_for_later && skia::IsPreviewMetafile(*canvas); +#endif + if (save_for_later) { ranges_.push_back(page_range); canvas_ = canvas; return true; } else -#endif // OS_LINUX || OS_WIN +#endif // USE_SKIA { return PrintPageHelper(&page_range, 1, canvas); } @@ -901,12 +906,12 @@ bool PluginInstance::PrintPageHelper(PP_PrintPageNumberRange_Dev* page_ranges, void PluginInstance::PrintEnd() { // Keep a reference on the stack. See NOTE above. scoped_refptr ref(this); -#if defined(OS_LINUX) || defined(OS_WIN) +#if defined(USE_SKIA) if (!ranges_.empty()) PrintPageHelper(&(ranges_.front()), ranges_.size(), canvas_.get()); canvas_ = NULL; ranges_.clear(); -#endif // OS_LINUX || OS_WIN +#endif // USE_SKIA DCHECK(plugin_print_interface_); if (plugin_print_interface_) @@ -1061,7 +1066,7 @@ bool PluginInstance::PrintPDFOutput(PP_Resource print_output, // (NativeMetafile and PreviewMetafile must have compatible formats, // i.e. both PDF for this to work). printing::Metafile* metafile = - printing::MetafileSkiaWrapper::GetMetafileFromCanvas(canvas); + printing::MetafileSkiaWrapper::GetMetafileFromCanvas(*canvas); DCHECK(metafile != NULL); if (metafile) ret = metafile->InitFromData(mapper.data(), mapper.size()); @@ -1086,7 +1091,7 @@ bool PluginInstance::PrintPDFOutput(PP_Resource print_output, } #elif defined(OS_WIN) printing::Metafile* metafile = - printing::MetafileSkiaWrapper::GetMetafileFromCanvas(canvas); + printing::MetafileSkiaWrapper::GetMetafileFromCanvas(*canvas); if (metafile) { // We only have a metafile when doing print preview, so we just want to // pass the PDF off to preview. diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.h b/webkit/plugins/ppapi/ppapi_plugin_instance.h index f46301b1bcdc..fdb3dcea7d87 100644 --- a/webkit/plugins/ppapi/ppapi_plugin_instance.h +++ b/webkit/plugins/ppapi/ppapi_plugin_instance.h @@ -466,14 +466,14 @@ class PluginInstance : public base::RefCounted, // variable to hold on to the pixels. scoped_refptr last_printed_page_; #endif // defined(OS_MACOSX) -#if defined(OS_LINUX) || defined(OS_WIN) - // When printing to PDF (print preview, Linux) the entire document goes into - // one metafile. However, when users print only a subset of all the pages, - // it is impossible to know if a call to PrintPage() is the last call. - // Thus in PrintPage(), just store the page number in |ranges_|. - // The hack is in PrintEnd(), where a valid |canvas_| is preserved in - // PrintWebViewHelper::PrintPages. This makes it possible to generate the - // entire PDF given the variables below: +#if defined(USE_SKIA) + // Always when printing to PDF on Linux and when printing for preview on Mac + // and Win, the entire document goes into one metafile. However, when users + // print only a subset of all the pages, it is impossible to know if a call + // to PrintPage() is the last call. Thus in PrintPage(), just store the page + // number in |ranges_|. The hack is in PrintEnd(), where a valid |canvas_| + // is preserved in PrintWebViewHelper::PrintPages. This makes it possible + // to generate the entire PDF given the variables below: // // The most recently used WebCanvas, guaranteed to be valid. SkRefPtr canvas_;