From be3b19a50ec04d881b3d11ae3c7aac4e7cab4261 Mon Sep 17 00:00:00 2001 From: "sverrir@chromium.org" Date: Mon, 13 Jul 2009 14:58:18 +0000 Subject: Fix print margins. This fixes multiple issues that caused incorrect offsets on printers that had a non-printable area (like most physical printers do). Two basic problems fixed. Firstly the margins where incorrectly calculated and secondly there was missing an offset int the rendering code (PHYSICALOFFSETX/Y is 0,0 when printing). To track this down I added code to print out all relevant margins for visual inspection (turned off by default). Chrome now prints using correctly calculated margins and is perfectly aligned on the page! BUG=http://crbug.com/947, http://crbug.com/1566 TEST=Printing on various printers. Review URL: http://codereview.chromium.org/155382 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20482 0039d316-1c4b-4281-b951-d872f2087c98 --- printing/page_setup.h | 1 + printing/print_settings.cc | 17 ++++++---- printing/printed_document.cc | 76 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 74 insertions(+), 20 deletions(-) (limited to 'printing') diff --git a/printing/page_setup.h b/printing/page_setup.h index 101b128..2ae984b 100644 --- a/printing/page_setup.h +++ b/printing/page_setup.h @@ -49,6 +49,7 @@ class PageSetup { const gfx::Size& physical_size() const { return physical_size_; } const gfx::Rect& overlay_area() const { return overlay_area_; } const gfx::Rect& content_area() const { return content_area_; } + const gfx::Rect& printable_area() const { return printable_area_; } const PageMargins& effective_margins() const { return effective_margins_; } diff --git a/printing/print_settings.cc b/printing/print_settings.cc index b76821b..4df0483 100644 --- a/printing/print_settings.cc +++ b/printing/print_settings.cc @@ -74,18 +74,23 @@ void PrintSettings::SetPrinterPrintableArea( gfx::Size const& physical_size_pixels, gfx::Rect const& printable_area_pixels) { - int margin_printer_units = ConvertUnit(500, kHundrethsMMPerInch, dpi_); + // Hard-code text_height = 0.5cm = ~1/5 of inch. + int header_footer_text_height = ConvertUnit(500, kHundrethsMMPerInch, dpi_); // Start by setting the user configuration - // Hard-code text_height = 0.5cm = ~1/5 of inch page_setup_pixels_.Init(physical_size_pixels, printable_area_pixels, - margin_printer_units); + header_footer_text_height); - // Now apply user configured settings. + // Default margins 1.0cm = ~2/5 of an inch. + int margin_printer_units = ConvertUnit(1000, kHundrethsMMPerInch, dpi_); + + // Apply default margins (not user configurable just yet). + // Since the font height is half the margin we put the header and footers at + // the font height from the margins. PageMargins margins; - margins.header = margin_printer_units; - margins.footer = margin_printer_units; + margins.header = header_footer_text_height; + margins.footer = header_footer_text_height; margins.left = margin_printer_units; margins.top = margin_printer_units; margins.right = margin_printer_units; diff --git a/printing/printed_document.cc b/printing/printed_document.cc index 517548b..b1d2332 100644 --- a/printing/printed_document.cc +++ b/printing/printed_document.cc @@ -36,6 +36,22 @@ struct PrintDebugDumpPath { Singleton g_debug_dump_info; +void SimpleModifyWorldTransform(HDC context, + int offset_x, + int offset_y, + double shrink_factor) { + XFORM xform = { 0 }; + xform.eDx = static_cast(offset_x); + xform.eDy = static_cast(offset_y); + xform.eM11 = xform.eM22 = static_cast(1. / shrink_factor); + BOOL res = ModifyWorldTransform(context, &xform, MWT_LEFTMULTIPLY); + DCHECK_NE(res, 0); +} + +void DrawRect(HDC context, gfx::Rect rect) { + Rectangle(context, rect.x(), rect.y(), rect.right(), rect.bottom()); +} + } // namespace namespace printing { @@ -102,6 +118,9 @@ void PrintedDocument::RenderPrintedPage(const PrintedPage& page, } #endif + const printing::PageSetup& page_setup( + immutable_.settings_.page_setup_pixels()); + // Save the state to make sure the context this function call does not modify // the device context. int saved_state = SaveDC(context); @@ -112,27 +131,57 @@ void PrintedDocument::RenderPrintedPage(const PrintedPage& page, int saved_state = SaveDC(context); DCHECK_NE(saved_state, 0); +#if 0 + // Debug code to visually verify margins (leaks GDI handles). + XFORM debug_xform = { 0 }; + ModifyWorldTransform(context, &debug_xform, MWT_IDENTITY); + // Printable area: + SelectObject(context, CreatePen(PS_SOLID, 1, RGB(0, 0, 0))); + SelectObject(context, CreateSolidBrush(RGB(0x90, 0x90, 0x90))); + Rectangle(context, + 0, + 0, + page_setup.printable_area().width(), + page_setup.printable_area().height()); + // Overlay area: + gfx::Rect debug_overlay_area(page_setup.overlay_area()); + debug_overlay_area.Offset(-page_setup.printable_area().x(), + -page_setup.printable_area().y()); + SelectObject(context, CreateSolidBrush(RGB(0xb0, 0xb0, 0xb0))); + DrawRect(context, debug_overlay_area); + // Content area: + gfx::Rect debug_content_area(page_setup.content_area()); + debug_content_area.Offset(-page_setup.printable_area().x(), + -page_setup.printable_area().y()); + SelectObject(context, CreateSolidBrush(RGB(0xd0, 0xd0, 0xd0))); + DrawRect(context, debug_content_area); +#endif + // Setup the matrix to translate and scale to the right place. Take in // account the actual shrinking factor. - XFORM xform = { 0 }; - xform.eDx = static_cast( - immutable_.settings_.page_setup_pixels().content_area().x()); - xform.eDy = static_cast( - immutable_.settings_.page_setup_pixels().content_area().y()); - xform.eM11 = static_cast(1. / mutable_.shrink_factor); - xform.eM22 = static_cast(1. / mutable_.shrink_factor); - BOOL res = ModifyWorldTransform(context, &xform, MWT_LEFTMULTIPLY); - DCHECK_NE(res, 0); + // Note that the printing output is relative to printable area of the page. + // That is 0,0 is offset by PHYSICALOFFSETX/Y from the page. + SimpleModifyWorldTransform( + context, + page_setup.content_area().x() - page_setup.printable_area().x(), + page_setup.content_area().y() - page_setup.printable_area().y(), + mutable_.shrink_factor); if (!page.native_metafile()->SafePlayback(context)) { NOTREACHED(); } - res = RestoreDC(context, saved_state); + BOOL res = RestoreDC(context, saved_state); DCHECK_NE(res, 0); } - // Print the header and footer. + // Print the header and footer. Offset by printable area offset (see comment + // above). + SimpleModifyWorldTransform( + context, + -page_setup.printable_area().x(), + -page_setup.printable_area().y(), + 1); int base_font_size = gfx::Font().height(); int new_font_size = ConvertUnit(10, immutable_.settings_.desired_dpi, @@ -243,7 +292,7 @@ void PrintedDocument::PrintHeaderFooter(HDC context, } std::wstring output(PageOverlays::ReplaceVariables(line, *this, page)); if (output.empty()) { - // May happens if document name or url is empty. + // May happen if document name or url is empty. return; } const gfx::Size string_size(font.GetStringWidth(output), font.height()); @@ -305,8 +354,7 @@ void PrintedDocument::PrintHeaderFooter(HDC context, DCHECK_NE(res, 0); } -void PrintedDocument::DebugDump(const PrintedPage& page) -{ +void PrintedDocument::DebugDump(const PrintedPage& page) { if (!g_debug_dump_info->enabled) return; -- cgit v1.1