OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "printing/printed_document.h" | 5 #include "printing/printed_document.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "app/gfx/font.h" | 9 #include "app/gfx/font.h" |
10 #include "app/gfx/text_elider.h" | 10 #include "app/gfx/text_elider.h" |
(...skipping 23 matching lines...) Expand all Loading... |
34 PrintDebugDumpPath() | 34 PrintDebugDumpPath() |
35 : enabled(false) { | 35 : enabled(false) { |
36 } | 36 } |
37 | 37 |
38 bool enabled; | 38 bool enabled; |
39 std::wstring debug_dump_path; | 39 std::wstring debug_dump_path; |
40 }; | 40 }; |
41 | 41 |
42 Singleton<PrintDebugDumpPath> g_debug_dump_info; | 42 Singleton<PrintDebugDumpPath> g_debug_dump_info; |
43 | 43 |
44 #if defined(OS_WIN) | |
45 void SimpleModifyWorldTransform(HDC context, | |
46 int offset_x, | |
47 int offset_y, | |
48 double shrink_factor) { | |
49 XFORM xform = { 0 }; | |
50 xform.eDx = static_cast<float>(offset_x); | |
51 xform.eDy = static_cast<float>(offset_y); | |
52 xform.eM11 = xform.eM22 = static_cast<float>(1. / shrink_factor); | |
53 BOOL res = ModifyWorldTransform(context, &xform, MWT_LEFTMULTIPLY); | |
54 DCHECK_NE(res, 0); | |
55 } | |
56 | |
57 void DrawRect(HDC context, gfx::Rect rect) { | |
58 Rectangle(context, rect.x(), rect.y(), rect.right(), rect.bottom()); | |
59 } | |
60 #endif // OS_WIN | |
61 | |
62 } // namespace | 44 } // namespace |
63 | 45 |
64 namespace printing { | 46 namespace printing { |
65 | 47 |
66 PrintedDocument::PrintedDocument(const PrintSettings& settings, | 48 PrintedDocument::PrintedDocument(const PrintSettings& settings, |
67 PrintedPagesSource* source, | 49 PrintedPagesSource* source, |
68 int cookie) | 50 int cookie) |
69 : mutable_(source), | 51 : mutable_(source), |
70 immutable_(settings, source, cookie) { | 52 immutable_(settings, source, cookie) { |
71 | 53 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 PrintedPages::const_iterator itr = mutable_.pages_.find(page_number); | 90 PrintedPages::const_iterator itr = mutable_.pages_.find(page_number); |
109 if (itr != mutable_.pages_.end()) { | 91 if (itr != mutable_.pages_.end()) { |
110 if (itr->second.get()) { | 92 if (itr->second.get()) { |
111 *page = itr->second; | 93 *page = itr->second; |
112 return true; | 94 return true; |
113 } | 95 } |
114 } | 96 } |
115 return false; | 97 return false; |
116 } | 98 } |
117 | 99 |
118 void PrintedDocument::RenderPrintedPage(const PrintedPage& page, | 100 bool PrintedDocument::RenderPrintedPageNumber( |
119 HDC context) const { | 101 int page_number, gfx::NativeDrawingContext context) { |
120 #ifndef NDEBUG | |
121 { | |
122 // Make sure the page is from our list. | |
123 AutoLock lock(lock_); | |
124 DCHECK(&page == mutable_.pages_.find(page.page_number() - 1)->second.get()); | |
125 } | |
126 #endif | |
127 | |
128 #if defined(OS_WIN) | |
129 const printing::PageSetup& page_setup( | |
130 immutable_.settings_.page_setup_pixels()); | |
131 | |
132 // Save the state to make sure the context this function call does not modify | |
133 // the device context. | |
134 int saved_state = SaveDC(context); | |
135 DCHECK_NE(saved_state, 0); | |
136 skia::PlatformDevice::InitializeDC(context); | |
137 { | |
138 // Save the state (again) to apply the necessary world transformation. | |
139 int saved_state = SaveDC(context); | |
140 DCHECK_NE(saved_state, 0); | |
141 | |
142 #if 0 | |
143 // Debug code to visually verify margins (leaks GDI handles). | |
144 XFORM debug_xform = { 0 }; | |
145 ModifyWorldTransform(context, &debug_xform, MWT_IDENTITY); | |
146 // Printable area: | |
147 SelectObject(context, CreatePen(PS_SOLID, 1, RGB(0, 0, 0))); | |
148 SelectObject(context, CreateSolidBrush(RGB(0x90, 0x90, 0x90))); | |
149 Rectangle(context, | |
150 0, | |
151 0, | |
152 page_setup.printable_area().width(), | |
153 page_setup.printable_area().height()); | |
154 // Overlay area: | |
155 gfx::Rect debug_overlay_area(page_setup.overlay_area()); | |
156 debug_overlay_area.Offset(-page_setup.printable_area().x(), | |
157 -page_setup.printable_area().y()); | |
158 SelectObject(context, CreateSolidBrush(RGB(0xb0, 0xb0, 0xb0))); | |
159 DrawRect(context, debug_overlay_area); | |
160 // Content area: | |
161 gfx::Rect debug_content_area(page_setup.content_area()); | |
162 debug_content_area.Offset(-page_setup.printable_area().x(), | |
163 -page_setup.printable_area().y()); | |
164 SelectObject(context, CreateSolidBrush(RGB(0xd0, 0xd0, 0xd0))); | |
165 DrawRect(context, debug_content_area); | |
166 #endif | |
167 | |
168 // Setup the matrix to translate and scale to the right place. Take in | |
169 // account the actual shrinking factor. | |
170 // Note that the printing output is relative to printable area of the page. | |
171 // That is 0,0 is offset by PHYSICALOFFSETX/Y from the page. | |
172 SimpleModifyWorldTransform( | |
173 context, | |
174 page_setup.content_area().x() - page_setup.printable_area().x(), | |
175 page_setup.content_area().y() - page_setup.printable_area().y(), | |
176 mutable_.shrink_factor); | |
177 | |
178 if (!page.native_metafile()->SafePlayback(context)) { | |
179 NOTREACHED(); | |
180 } | |
181 | |
182 BOOL res = RestoreDC(context, saved_state); | |
183 DCHECK_NE(res, 0); | |
184 } | |
185 | |
186 // Print the header and footer. Offset by printable area offset (see comment | |
187 // above). | |
188 SimpleModifyWorldTransform( | |
189 context, | |
190 -page_setup.printable_area().x(), | |
191 -page_setup.printable_area().y(), | |
192 1); | |
193 int base_font_size = gfx::Font().height(); | |
194 int new_font_size = ConvertUnit(10, | |
195 immutable_.settings_.desired_dpi, | |
196 immutable_.settings_.dpi()); | |
197 DCHECK_GT(new_font_size, base_font_size); | |
198 gfx::Font font(gfx::Font().DeriveFont(new_font_size - base_font_size)); | |
199 HGDIOBJ old_font = SelectObject(context, font.hfont()); | |
200 DCHECK(old_font != NULL); | |
201 // We don't want a white square around the text ever if overflowing. | |
202 SetBkMode(context, TRANSPARENT); | |
203 PrintHeaderFooter(context, page, PageOverlays::LEFT, PageOverlays::TOP, | |
204 font); | |
205 PrintHeaderFooter(context, page, PageOverlays::CENTER, PageOverlays::TOP, | |
206 font); | |
207 PrintHeaderFooter(context, page, PageOverlays::RIGHT, PageOverlays::TOP, | |
208 font); | |
209 PrintHeaderFooter(context, page, PageOverlays::LEFT, PageOverlays::BOTTOM, | |
210 font); | |
211 PrintHeaderFooter(context, page, PageOverlays::CENTER, PageOverlays::BOTTOM, | |
212 font); | |
213 PrintHeaderFooter(context, page, PageOverlays::RIGHT, PageOverlays::BOTTOM, | |
214 font); | |
215 int res = RestoreDC(context, saved_state); | |
216 DCHECK_NE(res, 0); | |
217 #else // OS_WIN | |
218 NOTIMPLEMENTED(); | |
219 #endif // OS_WIN | |
220 } | |
221 | |
222 bool PrintedDocument::RenderPrintedPageNumber(int page_number, HDC context) { | |
223 scoped_refptr<PrintedPage> page; | 102 scoped_refptr<PrintedPage> page; |
224 if (!GetPage(page_number, &page)) | 103 if (!GetPage(page_number, &page)) |
225 return false; | 104 return false; |
226 RenderPrintedPage(*page.get(), context); | 105 RenderPrintedPage(*page.get(), context); |
227 return true; | 106 return true; |
228 } | 107 } |
229 | 108 |
230 bool PrintedDocument::IsComplete() const { | 109 bool PrintedDocument::IsComplete() const { |
231 AutoLock lock(lock_); | 110 AutoLock lock(lock_); |
232 if (!mutable_.page_count_) | 111 if (!mutable_.page_count_) |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 int PrintedDocument::page_count() const { | 163 int PrintedDocument::page_count() const { |
285 AutoLock lock(lock_); | 164 AutoLock lock(lock_); |
286 return mutable_.page_count_; | 165 return mutable_.page_count_; |
287 } | 166 } |
288 | 167 |
289 int PrintedDocument::expected_page_count() const { | 168 int PrintedDocument::expected_page_count() const { |
290 AutoLock lock(lock_); | 169 AutoLock lock(lock_); |
291 return mutable_.expected_page_count_; | 170 return mutable_.expected_page_count_; |
292 } | 171 } |
293 | 172 |
294 void PrintedDocument::PrintHeaderFooter(HDC context, | 173 void PrintedDocument::PrintHeaderFooter(gfx::NativeDrawingContext context, |
295 const PrintedPage& page, | 174 const PrintedPage& page, |
296 PageOverlays::HorizontalPosition x, | 175 PageOverlays::HorizontalPosition x, |
297 PageOverlays::VerticalPosition y, | 176 PageOverlays::VerticalPosition y, |
298 const gfx::Font& font) const { | 177 const gfx::Font& font) const { |
299 const PrintSettings& settings = immutable_.settings_; | 178 const PrintSettings& settings = immutable_.settings_; |
300 const std::wstring& line = settings.overlays.GetOverlay(x, y); | 179 const std::wstring& line = settings.overlays.GetOverlay(x, y); |
301 if (line.empty()) { | 180 if (line.empty()) { |
302 return; | 181 return; |
303 } | 182 } |
304 std::wstring output(PageOverlays::ReplaceVariables(line, *this, page)); | 183 std::wstring output(PageOverlays::ReplaceVariables(line, *this, page)); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 } | 222 } |
344 | 223 |
345 if (string_size.width() > bounding.width()) { | 224 if (string_size.width() > bounding.width()) { |
346 if (line == PageOverlays::kUrl) { | 225 if (line == PageOverlays::kUrl) { |
347 output = gfx::ElideUrl(url(), font, bounding.width(), std::wstring()); | 226 output = gfx::ElideUrl(url(), font, bounding.width(), std::wstring()); |
348 } else { | 227 } else { |
349 output = gfx::ElideText(output, font, bounding.width()); | 228 output = gfx::ElideText(output, font, bounding.width()); |
350 } | 229 } |
351 } | 230 } |
352 | 231 |
| 232 // TODO(stuartmorgan): Factor out this platform-specific part into another |
| 233 // method that can be moved into the platform files. |
353 #if defined(OS_WIN) | 234 #if defined(OS_WIN) |
354 // Save the state (again) for the clipping region. | 235 // Save the state (again) for the clipping region. |
355 int saved_state = SaveDC(context); | 236 int saved_state = SaveDC(context); |
356 DCHECK_NE(saved_state, 0); | 237 DCHECK_NE(saved_state, 0); |
357 | 238 |
358 int result = IntersectClipRect(context, bounding.x(), bounding.y(), | 239 int result = IntersectClipRect(context, bounding.x(), bounding.y(), |
359 bounding.right() + 1, bounding.bottom() + 1); | 240 bounding.right() + 1, bounding.bottom() + 1); |
360 DCHECK(result == SIMPLEREGION || result == COMPLEXREGION); | 241 DCHECK(result == SIMPLEREGION || result == COMPLEXREGION); |
361 TextOut(context, | 242 TextOut(context, |
362 bounding.x(), bounding.y(), | 243 bounding.x(), bounding.y(), |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 date_ = win_util::FormatSystemDate(systemtime, std::wstring()); | 305 date_ = win_util::FormatSystemDate(systemtime, std::wstring()); |
425 time_ = win_util::FormatSystemTime(systemtime, std::wstring()); | 306 time_ = win_util::FormatSystemTime(systemtime, std::wstring()); |
426 #else // OS_WIN | 307 #else // OS_WIN |
427 Time now = Time::Now(); | 308 Time now = Time::Now(); |
428 date_ = base::TimeFormatShortDateNumeric(now); | 309 date_ = base::TimeFormatShortDateNumeric(now); |
429 time_ = base::TimeFormatTimeOfDay(now); | 310 time_ = base::TimeFormatTimeOfDay(now); |
430 #endif // OS_WIN | 311 #endif // OS_WIN |
431 } | 312 } |
432 | 313 |
433 } // namespace printing | 314 } // namespace printing |
OLD | NEW |