PrintPreview: 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. Review URL: http://codereview.chromium.org/7719014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@103021 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
@ -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,
|
||||
|
@ -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<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) {
|
||||
|
@ -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 @@ void PrintWebViewHelper::PrintPageInternal(
|
||||
// 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 @@ bool PrintWebViewHelper::RenderPreviewPage(int page_number) {
|
||||
|
||||
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 @@ bool PrintWebViewHelper::RenderPreviewPage(int page_number) {
|
||||
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 @@ void PrintWebViewHelper::RenderPage(
|
||||
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);
|
||||
|
@ -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());
|
||||
|
@ -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<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) {
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
SkMetaData& getMetaData(const SkCanvas& canvas);
|
||||
void SetIsDraftMode(const SkCanvas& canvas, bool draft_mode);
|
||||
bool IsDraftMode(const SkCanvas& canvas);
|
||||
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN)
|
||||
void SetIsPreviewMetafile(const SkCanvas& canvas, bool is_preview);
|
||||
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
|
||||
|
@ -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<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_)
|
||||
@ -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.
|
||||
|
@ -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_;
|
||||
|
Reference in New Issue
Block a user