1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "printing/printed_document.h"
7 #include "base/logging.h"
8 #include "base/string_util.h"
9 #include "base/utf_string_conversions.h"
10 #include "printing/page_number.h"
11 #include "printing/page_overlays.h"
12 #include "printing/printed_pages_source.h"
13 #include "printing/printed_page.h"
14 #include "printing/units.h"
15 #include "skia/ext/platform_device.h"
16 #include "ui/gfx/font.h"
20 void SimpleModifyWorldTransform(HDC context
,
23 double shrink_factor
) {
25 xform
.eDx
= static_cast<float>(offset_x
);
26 xform
.eDy
= static_cast<float>(offset_y
);
27 xform
.eM11
= xform
.eM22
= static_cast<float>(1. / shrink_factor
);
28 BOOL res
= ModifyWorldTransform(context
, &xform
, MWT_LEFTMULTIPLY
);
32 void DrawRect(HDC context
, gfx::Rect rect
) {
33 Rectangle(context
, rect
.x(), rect
.y(), rect
.right(), rect
.bottom());
36 // Creates a string interpretation of the time of day represented by the given
37 // SYSTEMTIME that's appropriate for the user's default locale.
38 // Format can be an empty string (for the default format), or a "format picture"
39 // as specified in the Windows documentation for GetTimeFormat().
40 string16
FormatSystemTime(const SYSTEMTIME
& time
, const string16
& format
) {
41 // If the format string is empty, just use the default format.
42 LPCTSTR format_ptr
= NULL
;
44 format_ptr
= format
.c_str();
46 int buffer_size
= GetTimeFormat(LOCALE_USER_DEFAULT
, NULL
, &time
, format_ptr
,
50 GetTimeFormat(LOCALE_USER_DEFAULT
, NULL
, &time
, format_ptr
,
51 WriteInto(&output
, buffer_size
), buffer_size
);
56 // Creates a string interpretation of the date represented by the given
57 // SYSTEMTIME that's appropriate for the user's default locale.
58 // Format can be an empty string (for the default format), or a "format picture"
59 // as specified in the Windows documentation for GetDateFormat().
60 string16
FormatSystemDate(const SYSTEMTIME
& date
, const string16
& format
) {
61 // If the format string is empty, just use the default format.
62 LPCTSTR format_ptr
= NULL
;
64 format_ptr
= format
.c_str();
66 int buffer_size
= GetDateFormat(LOCALE_USER_DEFAULT
, NULL
, &date
, format_ptr
,
70 GetDateFormat(LOCALE_USER_DEFAULT
, NULL
, &date
, format_ptr
,
71 WriteInto(&output
, buffer_size
), buffer_size
);
80 void PrintedDocument::RenderPrintedPage(
81 const PrintedPage
& page
, gfx::NativeDrawingContext context
) const {
84 // Make sure the page is from our list.
85 base::AutoLock
lock(lock_
);
86 DCHECK(&page
== mutable_
.pages_
.find(page
.page_number() - 1)->second
.get());
92 const printing::PageSetup
& page_setup(
93 immutable_
.settings_
.page_setup_device_units());
94 gfx::Rect content_area
;
95 page
.GetCenteredPageContentRect(page_setup
.physical_size(), &content_area
);
97 // Save the state to make sure the context this function call does not modify
98 // the device context.
99 int saved_state
= SaveDC(context
);
100 DCHECK_NE(saved_state
, 0);
101 skia::InitializeDC(context
);
103 // Save the state (again) to apply the necessary world transformation.
104 int saved_state
= SaveDC(context
);
105 DCHECK_NE(saved_state
, 0);
107 // Setup the matrix to translate and scale to the right place. Take in
108 // account the actual shrinking factor.
109 // Note that the printing output is relative to printable area of the page.
110 // That is 0,0 is offset by PHYSICALOFFSETX/Y from the page.
111 SimpleModifyWorldTransform(
113 content_area
.x() - page_setup
.printable_area().x(),
114 content_area
.y() - page_setup
.printable_area().y(),
115 mutable_
.shrink_factor
);
117 if (!page
.metafile()->SafePlayback(context
)) {
121 BOOL res
= RestoreDC(context
, saved_state
);
125 // Print the header and footer. Offset by printable area offset (see comment
127 SimpleModifyWorldTransform(
129 -page_setup
.printable_area().x(),
130 -page_setup
.printable_area().y(),
132 int base_font_size
= gfx::Font().GetHeight();
133 int new_font_size
= ConvertUnit(10,
134 immutable_
.settings_
.desired_dpi
,
135 immutable_
.settings_
.device_units_per_inch());
136 DCHECK_GT(new_font_size
, base_font_size
);
137 gfx::Font
font(gfx::Font().DeriveFont(new_font_size
- base_font_size
));
138 HGDIOBJ old_font
= SelectObject(context
, font
.GetNativeFont());
139 DCHECK(old_font
!= NULL
);
140 // We don't want a white square around the text ever if overflowing.
141 SetBkMode(context
, TRANSPARENT
);
142 // Disabling printing the header/footer on Windows for now to make the
143 // behavior consistent with Mac/Linux.
144 // TODO(thestig) re-enable this for print preview.
146 PrintHeaderFooter(context
, page
, PageOverlays::LEFT
, PageOverlays::TOP
,
148 PrintHeaderFooter(context
, page
, PageOverlays::CENTER
, PageOverlays::TOP
,
150 PrintHeaderFooter(context
, page
, PageOverlays::RIGHT
, PageOverlays::TOP
,
152 PrintHeaderFooter(context
, page
, PageOverlays::LEFT
, PageOverlays::BOTTOM
,
154 PrintHeaderFooter(context
, page
, PageOverlays::CENTER
, PageOverlays::BOTTOM
,
156 PrintHeaderFooter(context
, page
, PageOverlays::RIGHT
, PageOverlays::BOTTOM
,
159 int res
= RestoreDC(context
, saved_state
);
163 void PrintedDocument::Immutable::SetDocumentDate() {
164 // Use the native time formatting for printing on Windows.
165 SYSTEMTIME systemtime
;
166 GetLocalTime(&systemtime
);
168 WideToUTF16Hack(FormatSystemDate(systemtime
, std::wstring()));
170 WideToUTF16Hack(FormatSystemTime(systemtime
, std::wstring()));
173 void PrintedDocument::DrawHeaderFooter(gfx::NativeDrawingContext context
,
175 gfx::Rect bounds
) const {
176 // Save the state for the clipping region.
177 int saved_state
= SaveDC(context
);
178 DCHECK_NE(saved_state
, 0);
180 int result
= IntersectClipRect(context
, bounds
.x(), bounds
.y(),
181 bounds
.right() + 1, bounds
.bottom() + 1);
182 DCHECK(result
== SIMPLEREGION
|| result
== COMPLEXREGION
);
184 bounds
.x(), bounds
.y(),
186 static_cast<int>(text
.size()));
187 int res
= RestoreDC(context
, saved_state
);
191 } // namespace printing