OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/emf_win.h" | 5 #include "printing/emf_win.h" |
6 | 6 |
7 #include "base/files/file.h" | 7 #include "base/files/file.h" |
8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
11 #include "base/win/scoped_gdi_object.h" | 11 #include "base/win/scoped_gdi_object.h" |
12 #include "base/win/scoped_hdc.h" | 12 #include "base/win/scoped_hdc.h" |
13 #include "base/win/scoped_select_object.h" | 13 #include "base/win/scoped_select_object.h" |
14 #include "skia/ext/vector_platform_device_emf_win.h" | 14 #include "skia/ext/vector_platform_device_emf_win.h" |
15 #include "third_party/skia/include/core/SkBitmap.h" | 15 #include "third_party/skia/include/core/SkBitmap.h" |
16 #include "ui/gfx/codec/jpeg_codec.h" | 16 #include "ui/gfx/codec/jpeg_codec.h" |
17 #include "ui/gfx/codec/png_codec.h" | 17 #include "ui/gfx/codec/png_codec.h" |
18 #include "ui/gfx/gdi_util.h" | 18 #include "ui/gfx/gdi_util.h" |
19 #include "ui/gfx/rect.h" | 19 #include "ui/gfx/rect.h" |
20 #include "ui/gfx/size.h" | 20 #include "ui/gfx/size.h" |
21 | 21 |
22 namespace { | 22 namespace { |
23 | 23 |
24 const int kCustomGdiCommentSignature = 0xdeadbabe; | |
25 struct PageBreakRecord { | |
26 int signature; | |
27 enum PageBreakType { | |
28 START_PAGE, | |
29 END_PAGE, | |
30 } type; | |
31 explicit PageBreakRecord(PageBreakType type_in) | |
32 : signature(kCustomGdiCommentSignature), type(type_in) { | |
33 } | |
34 bool IsValid() const { | |
35 return (signature == kCustomGdiCommentSignature) && | |
36 (type >= START_PAGE) && (type <= END_PAGE); | |
37 } | |
38 }; | |
39 | |
40 int CALLBACK IsAlphaBlendUsedEnumProc(HDC, | 24 int CALLBACK IsAlphaBlendUsedEnumProc(HDC, |
41 HANDLETABLE*, | 25 HANDLETABLE*, |
42 const ENHMETARECORD *record, | 26 const ENHMETARECORD *record, |
43 int, | 27 int, |
44 LPARAM data) { | 28 LPARAM data) { |
45 bool* result = reinterpret_cast<bool*>(data); | 29 bool* result = reinterpret_cast<bool*>(data); |
46 if (!result) | 30 if (!result) |
47 return 0; | 31 return 0; |
48 switch (record->iType) { | 32 switch (record->iType) { |
49 case EMR_ALPHABLEND: { | 33 case EMR_ALPHABLEND: { |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 int size) { | 143 int size) { |
160 BOOL supported = FALSE; | 144 BOOL supported = FALSE; |
161 if (ExtEscape(dc, QUERYESCSUPPORT, sizeof(escape), | 145 if (ExtEscape(dc, QUERYESCSUPPORT, sizeof(escape), |
162 reinterpret_cast<LPCSTR>(&escape), 0, 0) > 0) { | 146 reinterpret_cast<LPCSTR>(&escape), 0, 0) > 0) { |
163 ExtEscape(dc, escape, size, reinterpret_cast<LPCSTR>(bits), | 147 ExtEscape(dc, escape, size, reinterpret_cast<LPCSTR>(bits), |
164 sizeof(supported), reinterpret_cast<LPSTR>(&supported)); | 148 sizeof(supported), reinterpret_cast<LPSTR>(&supported)); |
165 } | 149 } |
166 return !!supported; | 150 return !!supported; |
167 } | 151 } |
168 | 152 |
169 Emf::Emf() : emf_(NULL), hdc_(NULL), page_count_(0) { | 153 Emf::Emf() : emf_(NULL), hdc_(NULL) { |
170 } | 154 } |
171 | 155 |
172 Emf::~Emf() { | 156 Emf::~Emf() { |
173 Close(); | 157 Close(); |
174 } | 158 } |
175 | 159 |
176 void Emf::Close() { | 160 void Emf::Close() { |
177 DCHECK(!hdc_); | 161 DCHECK(!hdc_); |
178 if (emf_) | 162 if (emf_) |
179 DeleteEnhMetaFile(emf_); | 163 DeleteEnhMetaFile(emf_); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 | 213 |
230 bool Emf::SafePlayback(HDC context) const { | 214 bool Emf::SafePlayback(HDC context) const { |
231 DCHECK(emf_ && !hdc_); | 215 DCHECK(emf_ && !hdc_); |
232 XFORM base_matrix; | 216 XFORM base_matrix; |
233 if (!GetWorldTransform(context, &base_matrix)) { | 217 if (!GetWorldTransform(context, &base_matrix)) { |
234 NOTREACHED(); | 218 NOTREACHED(); |
235 return false; | 219 return false; |
236 } | 220 } |
237 Emf::EnumerationContext playback_context; | 221 Emf::EnumerationContext playback_context; |
238 playback_context.base_matrix = &base_matrix; | 222 playback_context.base_matrix = &base_matrix; |
239 RECT rect = GetPageBounds(1).ToRECT(); | 223 gfx::Rect bound = GetPageBounds(1); |
240 return EnumEnhMetaFile(context, | 224 RECT rect = bound.ToRECT(); |
| 225 return bound.IsEmpty() || |
| 226 EnumEnhMetaFile(context, |
241 emf_, | 227 emf_, |
242 &Emf::SafePlaybackProc, | 228 &Emf::SafePlaybackProc, |
243 reinterpret_cast<void*>(&playback_context), | 229 reinterpret_cast<void*>(&playback_context), |
244 &rect) != 0; | 230 &rect) != 0; |
245 } | 231 } |
246 | 232 |
247 gfx::Rect Emf::GetPageBounds(unsigned int page_number) const { | 233 gfx::Rect Emf::GetPageBounds(unsigned int page_number) const { |
248 DCHECK(emf_ && !hdc_); | 234 DCHECK(emf_ && !hdc_); |
249 DCHECK_EQ(1U, page_number); | 235 DCHECK_EQ(1U, page_number); |
250 ENHMETAHEADER header; | 236 ENHMETAHEADER header; |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 default: | 434 default: |
449 res = false; | 435 res = false; |
450 break; | 436 break; |
451 } | 437 } |
452 break; | 438 break; |
453 } | 439 } |
454 case EMR_SETLAYOUT: | 440 case EMR_SETLAYOUT: |
455 // Ignore it. | 441 // Ignore it. |
456 res = true; | 442 res = true; |
457 break; | 443 break; |
458 case EMR_GDICOMMENT: { | |
459 const EMRGDICOMMENT* comment_record = | |
460 reinterpret_cast<const EMRGDICOMMENT*>(record()); | |
461 if (comment_record->cbData == sizeof(PageBreakRecord)) { | |
462 const PageBreakRecord* page_break_record = | |
463 reinterpret_cast<const PageBreakRecord*>(comment_record->Data); | |
464 if (page_break_record && page_break_record->IsValid()) { | |
465 if (page_break_record->type == PageBreakRecord::START_PAGE) { | |
466 res = !!::StartPage(context->hdc); | |
467 DCHECK_EQ(0, context->dc_on_page_start); | |
468 context->dc_on_page_start = ::SaveDC(context->hdc); | |
469 } else if (page_break_record->type == PageBreakRecord::END_PAGE) { | |
470 DCHECK_NE(0, context->dc_on_page_start); | |
471 ::RestoreDC(context->hdc, context->dc_on_page_start); | |
472 context->dc_on_page_start = 0; | |
473 res = !!::EndPage(context->hdc); | |
474 } else { | |
475 res = false; | |
476 NOTREACHED(); | |
477 } | |
478 } else { | |
479 res = Play(context); | |
480 } | |
481 } else { | |
482 res = true; | |
483 } | |
484 break; | |
485 } | |
486 default: { | 444 default: { |
487 res = Play(context); | 445 res = Play(context); |
488 break; | 446 break; |
489 } | 447 } |
490 } | 448 } |
491 return res; | 449 return res; |
492 } | 450 } |
493 | 451 |
494 SkBaseDevice* Emf::StartPageForVectorCanvas( | 452 SkBaseDevice* Emf::StartPageForVectorCanvas( |
495 const gfx::Size& page_size, const gfx::Rect& content_area, | 453 const gfx::Size& page_size, const gfx::Rect& content_area, |
496 const float& scale_factor) { | 454 const float& scale_factor) { |
497 if (!StartPage(page_size, content_area, scale_factor)) | 455 if (!StartPage(page_size, content_area, scale_factor)) |
498 return NULL; | 456 return NULL; |
499 | 457 |
500 return skia::VectorPlatformDeviceEmf::CreateDevice(page_size.width(), | 458 return skia::VectorPlatformDeviceEmf::CreateDevice(page_size.width(), |
501 page_size.height(), | 459 page_size.height(), |
502 true, hdc_); | 460 true, hdc_); |
503 } | 461 } |
504 | 462 |
505 bool Emf::StartPage(const gfx::Size& /*page_size*/, | 463 bool Emf::StartPage(const gfx::Size& /*page_size*/, |
506 const gfx::Rect& /*content_area*/, | 464 const gfx::Rect& /*content_area*/, |
507 const float& /*scale_factor*/) { | 465 const float& /*scale_factor*/) { |
508 DCHECK(hdc_); | 466 return true; |
509 if (!hdc_) | |
510 return false; | |
511 page_count_++; | |
512 PageBreakRecord record(PageBreakRecord::START_PAGE); | |
513 return !!GdiComment(hdc_, sizeof(record), | |
514 reinterpret_cast<const BYTE *>(&record)); | |
515 } | 467 } |
516 | 468 |
517 bool Emf::FinishPage() { | 469 bool Emf::FinishPage() { |
518 DCHECK(hdc_); | 470 return true; |
519 if (!hdc_) | |
520 return false; | |
521 PageBreakRecord record(PageBreakRecord::END_PAGE); | |
522 return !!GdiComment(hdc_, sizeof(record), | |
523 reinterpret_cast<const BYTE *>(&record)); | |
524 } | 471 } |
525 | 472 |
526 Emf::Enumerator::Enumerator(const Emf& emf, HDC context, const RECT* rect) { | 473 Emf::Enumerator::Enumerator(const Emf& emf, HDC context, const RECT* rect) { |
527 items_.clear(); | 474 items_.clear(); |
528 if (!EnumEnhMetaFile(context, | 475 if (!EnumEnhMetaFile(context, |
529 emf.emf(), | 476 emf.emf(), |
530 &Emf::Enumerator::EnhMetaFileProc, | 477 &Emf::Enumerator::EnhMetaFileProc, |
531 reinterpret_cast<void*>(this), | 478 reinterpret_cast<void*>(this), |
532 rect)) { | 479 rect)) { |
533 NOTREACHED(); | 480 NOTREACHED(); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
643 RECT rect = page_bounds.ToRECT(); | 590 RECT rect = page_bounds.ToRECT(); |
644 ::EnumEnhMetaFile(hdc, emf(), &RasterizeAlphaBlendProc, &bitmap_dc, &rect); | 591 ::EnumEnhMetaFile(hdc, emf(), &RasterizeAlphaBlendProc, &bitmap_dc, &rect); |
645 | 592 |
646 result->FinishDocument(); | 593 result->FinishDocument(); |
647 | 594 |
648 return result.Pass(); | 595 return result.Pass(); |
649 } | 596 } |
650 | 597 |
651 | 598 |
652 } // namespace printing | 599 } // namespace printing |
OLD | NEW |