Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(97)

Side by Side Diff: printing/pdf_metafile_cg_mac.cc

Issue 2802093006: printing::Metafile: Simplify OS_MACOSX-specific code path (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/pdf_metafile_cg_mac.h" 5 #include "printing/pdf_metafile_cg_mac.h"
6 6
7 #include <ApplicationServices/ApplicationServices.h>
8 #include <CoreFoundation/CoreFoundation.h>
7 #include <stdint.h> 9 #include <stdint.h>
8 10
9 #include <algorithm> 11 #include <algorithm>
10 12
11 #include "base/logging.h" 13 #include "base/logging.h"
12 #include "base/mac/mac_util.h" 14 #include "base/mac/mac_util.h"
13 #include "base/mac/scoped_cftyperef.h" 15 #include "base/mac/scoped_cftyperef.h"
14 #include "base/numerics/safe_conversions.h" 16 #include "base/numerics/safe_conversions.h"
15 #include "base/strings/sys_string_conversions.h" 17 #include "base/strings/sys_string_conversions.h"
16 #include "ui/gfx/geometry/rect.h" 18 #include "ui/gfx/geometry/rect.h"
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 default: 52 default:
51 NOTREACHED(); 53 NOTREACHED();
52 break; 54 break;
53 } 55 }
54 } 56 }
55 57
56 } // namespace 58 } // namespace
57 59
58 namespace printing { 60 namespace printing {
59 61
60 PdfMetafileCg::PdfMetafileCg() : page_is_open_(false) {} 62 /* TODO(caryclark): The set up of PluginInstance::PrintPDFOutput may result in
61 63 rasterized output. Even if that flow uses PdfMetafileCg::RenderPage,
62 PdfMetafileCg::~PdfMetafileCg() {} 64 the drawing of the PDF into the canvas may result in a rasterized output.
63 65 PDFMetafileSkia::RenderPage should be not implemented as shown and instead
64 bool PdfMetafileCg::Init() { 66 should do something like the following CL in PluginInstance::PrintPDFOutput:
65 // Ensure that Init hasn't already been called. 67 http://codereview.chromium.org/7200040/diff/1/webkit/plugins/ppapi/ppapi_plug in_instance.cc
66 DCHECK(!context_.get()); 68 */
67 DCHECK(!pdf_data_.get()); 69 bool PdfMetafileCg::RenderPage(const void* src_buffer,
68 70 size_t src_buffer_size,
69 pdf_data_.reset(CFDataCreateMutable(kCFAllocatorDefault, 0)); 71 unsigned int page_number,
70 if (!pdf_data_.get()) { 72 CGContextRef context,
71 LOG(ERROR) << "Failed to create pdf data for metafile"; 73 const CGRect rect,
74 const PdfMetafileCg::RenderPageParams& params) {
75 if (!src_buffer || !src_buffer_size) {
76 LOG(ERROR) << "Empty PDF document";
72 return false; 77 return false;
73 } 78 }
74 ScopedCFTypeRef<CGDataConsumerRef> pdf_consumer( 79 if (!base::IsValueInRangeForNumericType<CFIndex>(src_buffer_size)) {
75 CGDataConsumerCreateWithCFData(pdf_data_)); 80 LOG(ERROR) << "Src PDF too long";
76 if (!pdf_consumer.get()) {
77 LOG(ERROR) << "Failed to create data consumer for metafile";
78 pdf_data_.reset();
79 return false; 81 return false;
80 } 82 }
81 context_.reset(CGPDFContextCreate(pdf_consumer, nullptr, nullptr)); 83 base::ScopedCFTypeRef<CFMutableDataRef> pdf_data(
82 if (!context_.get()) { 84 CFDataCreateMutable(kCFAllocatorDefault, src_buffer_size));
83 LOG(ERROR) << "Failed to create pdf context for metafile"; 85 DCHECK(pdf_data.get());
84 pdf_data_.reset(); 86 CFDataAppendBytes(pdf_data, static_cast<const UInt8*>(src_buffer),
85 }
86
87 return true;
88 }
89
90 bool PdfMetafileCg::InitFromData(const void* src_buffer,
91 size_t src_buffer_size) {
92 DCHECK(!context_.get());
93 DCHECK(!pdf_data_.get());
94
95 if (!src_buffer || !src_buffer_size)
96 return false;
97
98 if (!base::IsValueInRangeForNumericType<CFIndex>(src_buffer_size))
99 return false;
100
101 pdf_data_.reset(CFDataCreateMutable(kCFAllocatorDefault, src_buffer_size));
102 CFDataAppendBytes(pdf_data_, static_cast<const UInt8*>(src_buffer),
103 src_buffer_size); 87 src_buffer_size);
104 88 ScopedCFTypeRef<CGDataProviderRef> pdf_data_provider(
105 return true; 89 CGDataProviderCreateWithCFData(pdf_data));
106 } 90 base::ScopedCFTypeRef<CGPDFDocumentRef> pdf_doc(
107 91 CGPDFDocumentCreateWithProvider(pdf_data_provider));
108 void PdfMetafileCg::StartPage(const gfx::Size& page_size, 92 if (!pdf_doc.get()) {
109 const gfx::Rect& content_area,
110 const float& scale_factor) {
111 DCHECK(context_.get());
112 DCHECK(!page_is_open_);
113
114 double height = page_size.height();
115 double width = page_size.width();
116
117 CGRect bounds = CGRectMake(0, 0, width, height);
118 CGContextBeginPage(context_, &bounds);
119 page_is_open_ = true;
120 CGContextSaveGState(context_);
121
122 // Move to the context origin.
123 CGContextTranslateCTM(context_, content_area.x(), -content_area.y());
124
125 // Flip the context.
126 CGContextTranslateCTM(context_, 0, height);
127 CGContextScaleCTM(context_, scale_factor, -scale_factor);
128 }
129
130 bool PdfMetafileCg::FinishPage() {
131 DCHECK(context_.get());
132 DCHECK(page_is_open_);
133
134 CGContextRestoreGState(context_);
135 CGContextEndPage(context_);
136 page_is_open_ = false;
137 return true;
138 }
139
140 bool PdfMetafileCg::FinishDocument() {
141 DCHECK(context_.get());
142 DCHECK(!page_is_open_);
143
144 #ifndef NDEBUG
145 // Check that the context will be torn down properly; if it's not, pdf_data_
146 // will be incomplete and generate invalid PDF files/documents.
147 if (context_.get()) {
148 CFIndex extra_retain_count = CFGetRetainCount(context_.get()) - 1;
149 if (extra_retain_count > 0) {
150 LOG(ERROR) << "Metafile context has " << extra_retain_count
151 << " extra retain(s) on Close";
152 }
153 }
154 #endif
155 CGPDFContextClose(context_.get());
156 context_.reset();
157 return true;
158 }
159
160 bool PdfMetafileCg::RenderPage(unsigned int page_number,
161 CGContextRef context,
162 const CGRect rect,
163 const MacRenderPageParams& params) const {
164 CGPDFDocumentRef pdf_doc = GetPDFDocument();
165 if (!pdf_doc) {
166 LOG(ERROR) << "Unable to create PDF document from data"; 93 LOG(ERROR) << "Unable to create PDF document from data";
167 return false; 94 return false;
168 } 95 }
169 CGPDFPageRef pdf_page = CGPDFDocumentGetPage(pdf_doc, page_number); 96 CGPDFPageRef pdf_page = CGPDFDocumentGetPage(pdf_doc.get(), page_number);
170 CGRect source_rect = CGPDFPageGetBoxRect(pdf_page, kCGPDFCropBox); 97 CGRect source_rect = CGPDFPageGetBoxRect(pdf_page, kCGPDFCropBox);
171 int pdf_src_rotation = CGPDFPageGetRotationAngle(pdf_page); 98 int pdf_src_rotation = CGPDFPageGetRotationAngle(pdf_page);
172 float scaling_factor = 1.0; 99 float scaling_factor = 1.0;
173 const bool source_is_landscape = 100 const bool source_is_landscape =
174 (source_rect.size.width > source_rect.size.height); 101 (source_rect.size.width > source_rect.size.height);
175 const bool dest_is_landscape = (rect.size.width > rect.size.height); 102 const bool dest_is_landscape = (rect.size.width > rect.size.height);
176 const bool rotate = 103 const bool rotate =
177 params.autorotate ? (source_is_landscape != dest_is_landscape) : false; 104 params.autorotate ? (source_is_landscape != dest_is_landscape) : false;
178 const float source_width = 105 const float source_width =
179 rotate ? source_rect.size.height : source_rect.size.width; 106 rotate ? source_rect.size.height : source_rect.size.width;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 155
229 CGContextScaleCTM(context, scaling_factor, scaling_factor); 156 CGContextScaleCTM(context, scaling_factor, scaling_factor);
230 CGContextTranslateCTM(context, x_origin_offset, y_origin_offset); 157 CGContextTranslateCTM(context, x_origin_offset, y_origin_offset);
231 158
232 CGContextDrawPDFPage(context, pdf_page); 159 CGContextDrawPDFPage(context, pdf_page);
233 CGContextRestoreGState(context); 160 CGContextRestoreGState(context);
234 161
235 return true; 162 return true;
236 } 163 }
237 164
238 unsigned int PdfMetafileCg::GetPageCount() const {
239 CGPDFDocumentRef pdf_doc = GetPDFDocument();
240 return pdf_doc ? CGPDFDocumentGetNumberOfPages(pdf_doc) : 0;
241 }
242
243 gfx::Rect PdfMetafileCg::GetPageBounds(unsigned int page_number) const {
244 CGPDFDocumentRef pdf_doc = GetPDFDocument();
245 if (!pdf_doc) {
246 LOG(ERROR) << "Unable to create PDF document from data";
247 return gfx::Rect();
248 }
249 if (page_number > GetPageCount()) {
250 LOG(ERROR) << "Invalid page number: " << page_number;
251 return gfx::Rect();
252 }
253 CGPDFPageRef pdf_page = CGPDFDocumentGetPage(pdf_doc, page_number);
254 CGRect page_rect = CGPDFPageGetBoxRect(pdf_page, kCGPDFMediaBox);
255 return gfx::Rect(page_rect);
256 }
257
258 uint32_t PdfMetafileCg::GetDataSize() const {
259 // PDF data is only valid/complete once the context is released.
260 DCHECK(!context_);
261
262 if (!pdf_data_)
263 return 0;
264 return static_cast<uint32_t>(CFDataGetLength(pdf_data_));
265 }
266
267 bool PdfMetafileCg::GetData(void* dst_buffer, uint32_t dst_buffer_size) const {
268 // PDF data is only valid/complete once the context is released.
269 DCHECK(!context_);
270 DCHECK(pdf_data_);
271 DCHECK(dst_buffer);
272 DCHECK_GT(dst_buffer_size, 0U);
273
274 uint32_t data_size = GetDataSize();
275 if (dst_buffer_size > data_size) {
276 return false;
277 }
278
279 CFDataGetBytes(pdf_data_, CFRangeMake(0, dst_buffer_size),
280 static_cast<UInt8*>(dst_buffer));
281 return true;
282 }
283
284 CGContextRef PdfMetafileCg::context() const {
285 return context_.get();
286 }
287
288 CGPDFDocumentRef PdfMetafileCg::GetPDFDocument() const {
289 // Make sure that we have data, and that it's not being modified any more.
290 DCHECK(pdf_data_.get());
291 DCHECK(!context_.get());
292
293 if (!pdf_doc_.get()) {
294 ScopedCFTypeRef<CGDataProviderRef> pdf_data_provider(
295 CGDataProviderCreateWithCFData(pdf_data_));
296 pdf_doc_.reset(CGPDFDocumentCreateWithProvider(pdf_data_provider));
297 }
298 return pdf_doc_.get();
299 }
300
301 } // namespace printing 165 } // namespace printing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698