Skip to content

Commit

Permalink
Reland 103021: Printing preview of a PDF on Mac with Skia only previe…
Browse files Browse the repository at this point in the history
…ws 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
  • Loading branch information
kmadhusu@chromium.org committed Sep 28, 2011
1 parent 8a99325 commit be44f2f
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 65 deletions.
3 changes: 2 additions & 1 deletion chrome/renderer/print_web_view_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 3 additions & 3 deletions chrome/renderer/print_web_view_helper_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -208,9 +209,8 @@ void PrintWebViewHelper::PrintPageInternal(
// can't be a stack object.
SkRefPtr<skia::VectorCanvas> 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) {
Expand Down
13 changes: 7 additions & 6 deletions chrome/renderer/print_web_view_helper_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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)
Expand All @@ -156,9 +157,9 @@
SkRefPtr<skia::VectorCanvas> 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);
Expand Down
6 changes: 3 additions & 3 deletions chrome/renderer/print_web_view_helper_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,9 @@ Metafile* PrintWebViewHelper::RenderPage(
SkRefPtr<skia::VectorCanvas> 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());
Expand Down
34 changes: 5 additions & 29 deletions printing/metafile_skia_wrapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -12,56 +12,32 @@ 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;

return static_cast<MetafileSkiaWrapper*>(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) {
}
Expand Down
8 changes: 2 additions & 6 deletions printing/metafile_skia_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
45 changes: 45 additions & 0 deletions skia/ext/platform_device.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,37 @@
// 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"

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);
Expand All @@ -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;
}
Expand Down
12 changes: 12 additions & 0 deletions skia/ext/platform_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "third_party/skia/include/core/SkColor.h"

class SkMatrix;
class SkMetaData;
class SkPath;
class SkRegion;

Expand Down Expand Up @@ -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
Expand Down
23 changes: 14 additions & 9 deletions webkit/plugins/ppapi/ppapi_plugin_instance.cc
Original file line number Diff line number Diff line change
Expand Up @@ -851,25 +851,30 @@ 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;
}

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);
}
Expand Down Expand Up @@ -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<PluginInstance> 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_)
Expand Down Expand Up @@ -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());
Expand All @@ -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.
Expand Down
16 changes: 8 additions & 8 deletions webkit/plugins/ppapi/ppapi_plugin_instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -466,14 +466,14 @@ class PluginInstance : public base::RefCounted<PluginInstance>,
// variable to hold on to the pixels.
scoped_refptr<PPB_ImageData_Impl> 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<WebKit::WebCanvas> canvas_;
Expand Down

0 comments on commit be44f2f

Please sign in to comment.