0

Fix print preview clipping issues due to scaling.

BUG=79941
TEST=none
Review URL: http://codereview.chromium.org/6879098

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@83657 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
ctguil@chromium.org
2011-04-30 02:24:44 +00:00
parent f1e6bdc4cd
commit 39892b93d2
20 changed files with 82 additions and 70 deletions

2
DEPS

@ -15,7 +15,7 @@ vars = {
"libjingle_revision": "55",
"libvpx_revision": "81610",
"ffmpeg_revision": "83236",
"skia_revision": "1206",
"skia_revision": "1217",
"v8_revision": "7688",
}

@ -185,7 +185,7 @@ class PrintWebViewHelper : public RenderViewObserver ,
int page_number, bool is_preview, WebKit::WebFrame* frame,
scoped_ptr<printing::Metafile>* metafile);
#elif defined(OS_MACOSX)
void RenderPage(const gfx::Size& page_size, const gfx::Point& content_origin,
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);
#elif defined(OS_POSIX)

@ -217,10 +217,11 @@ void PrintWebViewHelper::PrintPageInternal(
margin_left_in_points,
content_height_in_points + margin_top_in_points +
margin_bottom_in_points);
gfx::Point content_origin(margin_left_in_points, margin_top_in_points);
gfx::Rect content_area(margin_left_in_points, margin_top_in_points,
content_width_in_points, content_height_in_points);
skia::PlatformDevice* device = metafile->StartPageForVectorCanvas(
page_size, content_origin, 1.0f);
page_size, content_area, 1.0f);
if (!device)
return;

@ -27,9 +27,9 @@ void PrintWebViewHelper::PrintPageInternal(
int page_number = params.page_number;
// Render page for printing.
gfx::Point origin(0.0f, 0.0f);
RenderPage(params.params.printable_size, origin, scale_factor, page_number,
frame, &metafile);
gfx::Rect content_area(params.params.printable_size);
RenderPage(params.params.printable_size, content_area, scale_factor,
page_number, frame, &metafile);
metafile.FinishDocument();
PrintHostMsg_DidPrintPage_Params page_params;
@ -70,17 +70,19 @@ bool PrintWebViewHelper::CreatePreviewDocument(
return false;
float scale_factor = frame->getPrintPageShrink(0);
gfx::Point origin(printParams.margin_left, printParams.margin_top);
gfx::Rect content_area(printParams.margin_left, printParams.margin_top,
printParams.printable_size.width(),
printParams.printable_size.height());
if (params.pages.empty()) {
for (int i = 0; i < page_count; ++i) {
RenderPage(printParams.page_size, origin, scale_factor, i, frame,
RenderPage(printParams.page_size, content_area, scale_factor, i, frame,
&metafile);
}
} else {
for (size_t i = 0; i < params.pages.size(); ++i) {
if (params.pages[i] >= page_count)
break;
RenderPage(printParams.page_size, origin, scale_factor,
RenderPage(printParams.page_size, content_area, scale_factor,
static_cast<int>(params.pages[i]), frame, &metafile);
}
}
@ -101,10 +103,10 @@ bool PrintWebViewHelper::CreatePreviewDocument(
}
void PrintWebViewHelper::RenderPage(
const gfx::Size& page_size, const gfx::Point& content_origin,
const gfx::Size& page_size, const gfx::Rect& content_area,
const float& scale_factor, int page_number, WebFrame* frame,
printing::Metafile* metafile) {
bool success = metafile->StartPage(page_size, content_origin, scale_factor);
bool success = metafile->StartPage(page_size, content_area, scale_factor);
DCHECK(success);
// printPage can create autoreleased references to |context|. PDF contexts

@ -207,10 +207,12 @@ void PrintWebViewHelper::RenderPage(
}
gfx::Size page_size(width, height);
gfx::Point content_origin(static_cast<int>(margin_left_in_points),
static_cast<int>(margin_top_in_points));
gfx::Rect content_area(static_cast<int>(margin_left_in_points),
static_cast<int>(margin_top_in_points),
static_cast<int>(content_width_in_points),
static_cast<int>(content_height_in_points));
skia::PlatformDevice* device = (*metafile)->StartPageForVectorCanvas(
page_size, content_origin, frame->getPrintPageShrink(page_number));
page_size, content_area, frame->getPrintPageShrink(page_number));
DCHECK(device);
skia::VectorCanvas canvas(device);

@ -301,7 +301,7 @@ bool UtilityThread::RenderPDFToWinMetafile(
break;
// The underlying metafile is of type Emf and ignores the arguments passed
// to StartPage.
metafile.StartPage(gfx::Size(), gfx::Point(), 1);
metafile.StartPage(gfx::Size(), gfx::Rect(), 1);
if (render_proc(&buffer.front(), buffer.size(), page_number,
metafile.context(), render_dpi, render_dpi,
render_area.x(), render_area.y(), render_area.width(),

@ -404,9 +404,9 @@ bool Emf::Record::SafePlayback(const XFORM* base_matrix) const {
}
skia::PlatformDevice* Emf::StartPageForVectorCanvas(
const gfx::Size& page_size, const gfx::Point& content_origin,
const gfx::Size& page_size, const gfx::Rect& content_area,
const float& scale_factor) {
if (!StartPage(page_size, content_origin, scale_factor))
if (!StartPage(page_size, content_area, scale_factor))
return NULL;
return skia::VectorPlatformDeviceEmfFactory::CreateDevice(page_size.width(),
@ -415,7 +415,7 @@ skia::PlatformDevice* Emf::StartPageForVectorCanvas(
}
bool Emf::StartPage(const gfx::Size& /*page_size*/,
const gfx::Point& /*content_origin*/,
const gfx::Rect& /*content_area*/,
const float& /*scale_factor*/) {
DCHECK(hdc_);
if (!hdc_)

@ -46,14 +46,14 @@ class Emf : public Metafile {
virtual bool InitFromData(const void* src_buffer, uint32 src_buffer_size);
virtual skia::PlatformDevice* StartPageForVectorCanvas(
const gfx::Size& page_size, const gfx::Point& content_origin,
const gfx::Size& page_size, const gfx::Rect& content_area,
const float& scale_factor);
// Inserts a custom GDICOMMENT records indicating StartPage/EndPage calls
// (since StartPage and EndPage do not work in a metafile DC). Only valid
// when hdc_ is non-NULL. |page_size|, |content_origin|, and |scale_factor|
// are ignored.
// when hdc_ is non-NULL. |page_size|, |content_area|, and |scale_factor| are
// ignored.
virtual bool StartPage(const gfx::Size& page_size,
const gfx::Point& content_origin,
const gfx::Rect& content_area,
const float& scale_factor);
virtual bool FinishPage();
virtual bool FinishDocument();

@ -136,7 +136,7 @@ TEST_F(EmfPrintingTest, PageBreak) {
EXPECT_TRUE(emf.context() != NULL);
int pages = 3;
while (pages) {
EXPECT_TRUE(emf.StartPage(gfx::Size(), gfx::Point(), 1));
EXPECT_TRUE(emf.StartPage(gfx::Size(), gfx::Rect(), 1));
::Rectangle(emf.context(), 10, 10, 190, 190);
EXPECT_TRUE(emf.FinishPage());
--pages;

@ -57,14 +57,15 @@ class Metafile {
// VectorPlatformDevice implementation bound to the context created by
// StartPage or NULL on error.
virtual skia::PlatformDevice* StartPageForVectorCanvas(
const gfx::Size& page_size, const gfx::Point& content_origin,
const gfx::Size& page_size,
const gfx::Rect& content_area,
const float& scale_factor) = 0;
// Prepares a context for rendering a new page at the specified
// |content_origin| with the given |page_size| and a |scale_factor| to use for
// the drawing. The units are in points (=1/72 in). Returns true on success.
// Prepares a context for rendering a new page with the given |page_size|,
// |content_area| and a |scale_factor| to use for the drawing. The units are
// in points (=1/72 in). Returns true on success.
virtual bool StartPage(const gfx::Size& page_size,
const gfx::Point& content_origin,
const gfx::Rect& content_area,
const float& scale_factor) = 0;
// Closes the current page and destroys the context used in rendering that

@ -119,9 +119,9 @@ bool PdfMetafileCairo::InitFromData(const void* src_buffer,
}
skia::PlatformDevice* PdfMetafileCairo::StartPageForVectorCanvas(
const gfx::Size& page_size, const gfx::Point& content_origin,
const gfx::Size& page_size, const gfx::Rect& content_area,
const float& scale_factor) {
if (!StartPage(page_size, content_origin, scale_factor))
if (!StartPage(page_size, content_area, scale_factor))
return NULL;
return skia::VectorPlatformDeviceCairoFactory::CreateDevice(
@ -129,7 +129,7 @@ skia::PlatformDevice* PdfMetafileCairo::StartPageForVectorCanvas(
}
bool PdfMetafileCairo::StartPage(const gfx::Size& page_size,
const gfx::Point& content_origin,
const gfx::Rect& content_area,
const float& scale_factor) {
DCHECK(IsSurfaceValid(surface_));
DCHECK(IsContextValid(context_));
@ -142,8 +142,8 @@ bool PdfMetafileCairo::StartPage(const gfx::Size& page_size,
// Don't let WebKit draw over the margins.
cairo_surface_set_device_offset(surface_,
content_origin.x(),
content_origin.y());
content_area.x(),
content_area.y());
cairo_pdf_surface_set_size(surface_, page_size.width(), page_size.height());
return context_ != NULL;

@ -37,10 +37,10 @@ class PdfMetafileCairo : public Metafile {
virtual bool InitFromData(const void* src_buffer, uint32 src_buffer_size);
virtual skia::PlatformDevice* StartPageForVectorCanvas(
const gfx::Size& page_size, const gfx::Point& content_origin,
const gfx::Size& page_size, const gfx::Rect& content_area,
const float& scale_factor);
virtual bool StartPage(const gfx::Size& page_size,
const gfx::Point& content_origin,
const gfx::Rect& content_area,
const float& scale_factor);
virtual bool FinishPage();
virtual bool FinishDocument();

@ -13,8 +13,8 @@
#include "base/file_util.h"
#include "base/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
#include "ui/gfx/point.h"
typedef struct _cairo cairo_t;
@ -32,12 +32,12 @@ TEST_F(PdfMetafileCairoTest, Pdf) {
EXPECT_TRUE(pdf.Init());
// Renders page 1.
EXPECT_TRUE(pdf.StartPage(gfx::Size(72, 73), gfx::Point(4, 5), 1));
EXPECT_TRUE(pdf.StartPage(gfx::Size(72, 73), gfx::Rect(4, 5, 64, 63), 1));
// In theory, we should use Cairo to draw something on |context|.
EXPECT_TRUE(pdf.FinishPage());
// Renders page 2.
EXPECT_TRUE(pdf.StartPage(gfx::Size(72, 73), gfx::Point(4, 5), 1));
EXPECT_TRUE(pdf.StartPage(gfx::Size(72, 73), gfx::Rect(4, 5, 64, 63), 1));
// In theory, we should use Cairo to draw something on |context|.
EXPECT_TRUE(pdf.FinishPage());
@ -70,7 +70,7 @@ TEST_F(PdfMetafileCairoTest, Pdf) {
// Test overriding the metafile with raw data.
printing::PdfMetafileCairo pdf3;
EXPECT_TRUE(pdf3.Init());
EXPECT_TRUE(pdf3.StartPage(gfx::Size(72, 73), gfx::Point(4, 5), 1));
EXPECT_TRUE(pdf3.StartPage(gfx::Size(72, 73), gfx::Rect(4, 5, 64, 63), 1));
std::string test_raw_data = "Dummy PDF";
EXPECT_TRUE(pdf3.InitFromData(test_raw_data.c_str(), test_raw_data.size()));
EXPECT_TRUE(pdf3.FinishPage());

@ -64,14 +64,14 @@ bool PdfMetafileCg::InitFromData(const void* src_buffer,
}
skia::PlatformDevice* PdfMetafileCg::StartPageForVectorCanvas(
const gfx::Size& page_size, const gfx::Point& content_origin,
const gfx::Size& page_size, const gfx::Rect& content_area,
const float& scale_factor) {
NOTIMPLEMENTED();
return NULL;
}
bool PdfMetafileCg::StartPage(const gfx::Size& page_size,
const gfx::Point& content_origin,
const gfx::Rect& content_area,
const float& scale_factor) {
DCHECK(context_.get());
DCHECK(!page_is_open_);
@ -88,8 +88,8 @@ bool PdfMetafileCg::StartPage(const gfx::Size& page_size,
CGContextTranslateCTM(context_, 0, height);
CGContextScaleCTM(context_, scale_factor, -scale_factor);
// Move the context to origin.
CGContextTranslateCTM(context_, content_origin.x(), content_origin.y());
// Move to the context origin.
CGContextTranslateCTM(context_, content_area.x(), content_area.y());
return context_.get() != NULL;
}

@ -35,10 +35,10 @@ class PdfMetafileCg : public Metafile {
// Not implemented on mac.
virtual skia::PlatformDevice* StartPageForVectorCanvas(
const gfx::Size& page_size, const gfx::Point& content_origin,
const gfx::Size& page_size, const gfx::Rect& content_area,
const float& scale_factor);
virtual bool StartPage(const gfx::Size& page_size,
const gfx::Point& content_origin,
const gfx::Rect& content_area,
const float& scale_factor);
virtual bool FinishPage();
virtual bool FinishDocument();

@ -20,16 +20,16 @@ TEST(PdfMetafileCgTest, Pdf) {
EXPECT_TRUE(pdf.Init());
EXPECT_TRUE(pdf.context() != NULL);
// Render page 1 at origin (10.0, 10.0).
gfx::Point origin_1(10.0f, 10.0f);
// Render page 1.
gfx::Rect rect_1(10, 10, 520, 700);
gfx::Size size_1(540, 720);
pdf.StartPage(size_1, origin_1, 1.25);
pdf.StartPage(size_1, rect_1, 1.25);
pdf.FinishPage();
// Render page 2 at origin (10.0, 10.0).
gfx::Point origin_2(10.0f, 10.0f);
// Render page 2.
gfx::Rect rect_2(10, 10, 520, 700);
gfx::Size size_2(720, 540);
pdf.StartPage(size_2, origin_2, 2.0);
pdf.StartPage(size_2, rect_2, 2.0);
pdf.FinishPage();
pdf.FinishDocument();

@ -37,26 +37,32 @@ bool PdfMetafileSkia::InitFromData(const void* src_buffer,
}
skia::PlatformDevice* PdfMetafileSkia::StartPageForVectorCanvas(
const gfx::Size& page_size, const gfx::Point& content_origin,
const gfx::Size& page_size, const gfx::Rect& content_area,
const float& scale_factor) {
DCHECK(data_->current_page_.get() == NULL);
// Adjust for the margins and apply the scale factor.
SkMatrix transform;
transform.setTranslate(SkIntToScalar(content_origin.x()),
SkIntToScalar(content_origin.y()));
transform.setTranslate(SkIntToScalar(content_area.x()),
SkIntToScalar(content_area.y()));
transform.preScale(SkFloatToScalar(scale_factor),
SkFloatToScalar(scale_factor));
// TODO(ctguil): Refactor: don't create the PDF device explicitly here.
SkISize pdf_page_size = SkISize::Make(page_size.width(), page_size.height());
SkISize pdf_content_size =
SkISize::Make(content_area.width(), content_area.height());
SkRefPtr<SkPDFDevice> pdf_device =
new SkPDFDevice(pdf_page_size, pdf_content_size, transform);
pdf_device->unref(); // SkRefPtr and new both took a reference.
skia::VectorPlatformDeviceSkia* device =
new skia::VectorPlatformDeviceSkia(page_size.width(), page_size.height(),
transform);
new skia::VectorPlatformDeviceSkia(pdf_device.get());
data_->current_page_ = device->PdfDevice();
return device;
}
bool PdfMetafileSkia::StartPage(const gfx::Size& page_size,
const gfx::Point& content_origin,
const gfx::Rect& content_area,
const float& scale_factor) {
NOTREACHED();
return NULL;

@ -31,10 +31,10 @@ class PdfMetafileSkia : public Metafile {
virtual skia::PlatformDevice* StartPageForVectorCanvas(
const gfx::Size& page_size,
const gfx::Point& content_origin,
const gfx::Rect& content_area,
const float& scale_factor);
virtual bool StartPage(const gfx::Size& page_size,
const gfx::Point& content_origin,
const gfx::Rect& content_area,
const float& scale_factor);
virtual bool FinishPage();
virtual bool FinishDocument();
@ -66,4 +66,4 @@ class PdfMetafileSkia : public Metafile {
} // namespace printing
#endif // PRINTING_PDF_METAFILE_MAC_H_
#endif // PRINTING_PDF_METAFILE_SKIA_H_

@ -25,7 +25,11 @@ SkDevice* VectorPlatformDeviceSkiaFactory::newDevice(SkCanvas* noUsed,
initialTransform.setTranslate(0, height);
initialTransform.preScale(1, -1);
}
return new VectorPlatformDeviceSkia(width, height, initialTransform);
SkISize size = SkISize::Make(width, height);
SkRefPtr<SkPDFDevice> pdf_device =
new SkPDFDevice(size, size, initialTransform);
pdf_device->unref(); // SkRefPtr and new both took a reference.
return new VectorPlatformDeviceSkia(pdf_device.get());
}
static inline SkBitmap makeABitmap(int width, int height) {
@ -34,11 +38,9 @@ static inline SkBitmap makeABitmap(int width, int height) {
return bitmap;
}
VectorPlatformDeviceSkia::VectorPlatformDeviceSkia(
int width, int height, const SkMatrix& initialTransform)
: PlatformDevice(makeABitmap(width, height)),
pdf_device_(new SkPDFDevice(width, height, initialTransform)) {
pdf_device_->unref(); // SkRefPtr and new both took a reference.
VectorPlatformDeviceSkia::VectorPlatformDeviceSkia(SkPDFDevice* pdf_device)
: PlatformDevice(makeABitmap(pdf_device->width(), pdf_device->height())),
pdf_device_(pdf_device) {
}
VectorPlatformDeviceSkia::~VectorPlatformDeviceSkia() {

@ -31,9 +31,7 @@ class VectorPlatformDeviceSkiaFactory : public SkDeviceFactory {
class VectorPlatformDeviceSkia : public PlatformDevice {
public:
SK_API VectorPlatformDeviceSkia(int width,
int height,
const SkMatrix& initialTransform);
SK_API VectorPlatformDeviceSkia(SkPDFDevice* pdf_device);
~VectorPlatformDeviceSkia();
SkPDFDevice* PdfDevice() { return pdf_device_.get(); }