Chromium Code Reviews| 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/pdf_metafile_cg_mac.h" | 5 #include "printing/pdf_metafile_cg_mac.h" |
| 6 | 6 |
| 7 #include <algorithm> | |
| 8 | |
| 7 #include "base/file_path.h" | 9 #include "base/file_path.h" |
| 8 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| 9 #include "base/logging.h" | 11 #include "base/logging.h" |
| 10 #include "base/mac/mac_util.h" | 12 #include "base/mac/mac_util.h" |
| 11 #include "base/mac/scoped_cftyperef.h" | 13 #include "base/mac/scoped_cftyperef.h" |
| 12 #include "base/sys_string_conversions.h" | 14 #include "base/sys_string_conversions.h" |
| 13 #include "base/threading/thread_local.h" | 15 #include "base/threading/thread_local.h" |
| 14 #include "ui/gfx/rect.h" | 16 #include "ui/gfx/rect.h" |
| 15 #include "ui/gfx/size.h" | 17 #include "ui/gfx/size.h" |
| 16 | 18 |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 168 context_.reset(NULL); | 170 context_.reset(NULL); |
| 169 return true; | 171 return true; |
| 170 } | 172 } |
| 171 | 173 |
| 172 bool PdfMetafileCg::RenderPage(unsigned int page_number, | 174 bool PdfMetafileCg::RenderPage(unsigned int page_number, |
| 173 CGContextRef context, | 175 CGContextRef context, |
| 174 const CGRect rect, | 176 const CGRect rect, |
| 175 bool shrink_to_fit, | 177 bool shrink_to_fit, |
| 176 bool stretch_to_fit, | 178 bool stretch_to_fit, |
| 177 bool center_horizontally, | 179 bool center_horizontally, |
| 178 bool center_vertically) const { | 180 bool center_vertically, |
| 181 bool autorotate) const { | |
| 179 CGPDFDocumentRef pdf_doc = GetPDFDocument(); | 182 CGPDFDocumentRef pdf_doc = GetPDFDocument(); |
| 180 if (!pdf_doc) { | 183 if (!pdf_doc) { |
| 181 LOG(ERROR) << "Unable to create PDF document from data"; | 184 LOG(ERROR) << "Unable to create PDF document from data"; |
| 182 return false; | 185 return false; |
| 183 } | 186 } |
| 184 CGPDFPageRef pdf_page = CGPDFDocumentGetPage(pdf_doc, page_number); | 187 CGPDFPageRef pdf_page = CGPDFDocumentGetPage(pdf_doc, page_number); |
| 185 CGRect source_rect = CGPDFPageGetBoxRect(pdf_page, kCGPDFCropBox); | 188 CGRect source_rect = CGPDFPageGetBoxRect(pdf_page, kCGPDFCropBox); |
| 186 float scaling_factor = 1.0; | 189 float scaling_factor = 1.0; |
| 190 const bool source_is_landscape = | |
| 191 (source_rect.size.width > source_rect.size.height); | |
| 192 const bool dest_is_landscape = (rect.size.width > rect.size.height); | |
| 193 const bool rotate = | |
| 194 autorotate ? (source_is_landscape != dest_is_landscape) : false; | |
| 195 const float source_width = | |
| 196 rotate ? source_rect.size.height : source_rect.size.width; | |
| 197 const float source_height = | |
| 198 rotate ? source_rect.size.width : source_rect.size.height; | |
| 199 | |
| 187 // See if we need to scale the output. | 200 // See if we need to scale the output. |
| 188 bool scaling_needed = | 201 const bool scaling_needed = |
| 189 (shrink_to_fit && ((source_rect.size.width > rect.size.width) || | 202 (shrink_to_fit && ((source_width > rect.size.width) || |
| 190 (source_rect.size.height > rect.size.height))) || | 203 (source_height > rect.size.height))) || |
| 191 (stretch_to_fit && (source_rect.size.width < rect.size.width) && | 204 (stretch_to_fit && (source_width < rect.size.width) && |
| 192 (source_rect.size.height < rect.size.height)); | 205 (source_height < rect.size.height)); |
| 193 if (scaling_needed) { | 206 if (scaling_needed) { |
| 194 float x_scaling_factor = rect.size.width / source_rect.size.width; | 207 float x_scaling_factor = rect.size.width / source_width; |
| 195 float y_scaling_factor = rect.size.height / source_rect.size.height; | 208 float y_scaling_factor = rect.size.height / source_height; |
| 196 if (x_scaling_factor > y_scaling_factor) { | 209 scaling_factor = std::min(x_scaling_factor, y_scaling_factor); |
| 197 scaling_factor = y_scaling_factor; | |
| 198 } else { | |
| 199 scaling_factor = x_scaling_factor; | |
| 200 } | |
| 201 } | 210 } |
| 202 // Some PDFs have a non-zero origin. Need to take that into account. | 211 // Some PDFs have a non-zero origin. Need to take that into account and align |
| 203 float x_offset = -1 * source_rect.origin.x * scaling_factor; | 212 // the PDF to the origin. |
| 204 float y_offset = -1 * source_rect.origin.y * scaling_factor; | 213 const float x_origin_offset = -1 * source_rect.origin.x; |
| 214 const float y_origin_offset = -1 * source_rect.origin.y; | |
| 205 | 215 |
| 206 if (center_horizontally) { | 216 // If the PDF needs to be centered, calculate the offsets here. |
| 207 x_offset += (rect.size.width - | 217 float x_offset = center_horizontally ? |
| 208 (source_rect.size.width * scaling_factor))/2; | 218 ((rect.size.width - (source_width * scaling_factor)) / 2) : 0; |
| 219 if (rotate) | |
| 220 x_offset = -x_offset; | |
| 221 | |
| 222 float y_offset = center_vertically ? | |
| 223 ((rect.size.height - (source_height * scaling_factor)) / 2) : 0; | |
| 224 | |
| 225 CGContextSaveGState(context); | |
| 226 | |
| 227 // The transform operations specified here gets applied in reverse order. | |
| 228 // i.e. the origin offset translation happens first. | |
| 229 // Origin is at bottom-left. | |
| 230 CGContextTranslateCTM(context, x_offset, y_offset); | |
|
kmadhusu
2012/06/16 00:44:11
Why can't we do a single Translation operation lik
Lei Zhang
2012/06/16 01:47:20
We may be able to, but it's easier to visualize wh
| |
| 231 if (rotate) { | |
| 232 CGContextTranslateCTM(context, rect.size.width, 0); | |
|
kmadhusu
2012/06/16 00:44:11
Can you add a comment on why we need to do this tr
Lei Zhang
2012/06/16 01:47:20
Done.
| |
| 233 // Rotates counter-clockwise by 90 degrees. | |
| 234 CGContextRotateCTM(context, M_PI_2); | |
| 209 } | 235 } |
| 210 if (center_vertically) { | |
| 211 y_offset += (rect.size.height - | |
| 212 (source_rect.size.height * scaling_factor))/2; | |
| 213 } | |
| 214 CGContextSaveGState(context); | |
| 215 CGContextTranslateCTM(context, x_offset, y_offset); | |
| 216 CGContextScaleCTM(context, scaling_factor, scaling_factor); | 236 CGContextScaleCTM(context, scaling_factor, scaling_factor); |
| 237 CGContextTranslateCTM(context, x_origin_offset, y_origin_offset); | |
| 238 | |
| 217 CGContextDrawPDFPage(context, pdf_page); | 239 CGContextDrawPDFPage(context, pdf_page); |
| 218 CGContextRestoreGState(context); | 240 CGContextRestoreGState(context); |
| 241 | |
| 219 return true; | 242 return true; |
| 220 } | 243 } |
| 221 | 244 |
| 222 unsigned int PdfMetafileCg::GetPageCount() const { | 245 unsigned int PdfMetafileCg::GetPageCount() const { |
| 223 CGPDFDocumentRef pdf_doc = GetPDFDocument(); | 246 CGPDFDocumentRef pdf_doc = GetPDFDocument(); |
| 224 return pdf_doc ? CGPDFDocumentGetNumberOfPages(pdf_doc) : 0; | 247 return pdf_doc ? CGPDFDocumentGetNumberOfPages(pdf_doc) : 0; |
| 225 } | 248 } |
| 226 | 249 |
| 227 gfx::Rect PdfMetafileCg::GetPageBounds(unsigned int page_number) const { | 250 gfx::Rect PdfMetafileCg::GetPageBounds(unsigned int page_number) const { |
| 228 CGPDFDocumentRef pdf_doc = GetPDFDocument(); | 251 CGPDFDocumentRef pdf_doc = GetPDFDocument(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 262 | 285 |
| 263 CFDataGetBytes(pdf_data_, CFRangeMake(0, dst_buffer_size), | 286 CFDataGetBytes(pdf_data_, CFRangeMake(0, dst_buffer_size), |
| 264 static_cast<UInt8*>(dst_buffer)); | 287 static_cast<UInt8*>(dst_buffer)); |
| 265 return true; | 288 return true; |
| 266 } | 289 } |
| 267 | 290 |
| 268 bool PdfMetafileCg::SaveTo(const FilePath& file_path) const { | 291 bool PdfMetafileCg::SaveTo(const FilePath& file_path) const { |
| 269 DCHECK(pdf_data_.get()); | 292 DCHECK(pdf_data_.get()); |
| 270 DCHECK(!context_.get()); | 293 DCHECK(!context_.get()); |
| 271 | 294 |
| 272 std::string path_string = file_path.value(); | 295 const std::string& path_string = file_path.value(); |
| 273 ScopedCFTypeRef<CFURLRef> path_url(CFURLCreateFromFileSystemRepresentation( | 296 ScopedCFTypeRef<CFURLRef> path_url(CFURLCreateFromFileSystemRepresentation( |
| 274 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(path_string.c_str()), | 297 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(path_string.c_str()), |
| 275 path_string.length(), false)); | 298 path_string.length(), false)); |
| 276 SInt32 error_code; | 299 SInt32 error_code; |
| 277 CFURLWriteDataAndPropertiesToResource(path_url, pdf_data_, NULL, &error_code); | 300 CFURLWriteDataAndPropertiesToResource(path_url, pdf_data_, NULL, &error_code); |
| 278 return error_code == 0; | 301 return error_code == 0; |
| 279 } | 302 } |
| 280 | 303 |
| 281 CGContextRef PdfMetafileCg::context() const { | 304 CGContextRef PdfMetafileCg::context() const { |
| 282 return context_.get(); | 305 return context_.get(); |
| 283 } | 306 } |
| 284 | 307 |
| 285 CGPDFDocumentRef PdfMetafileCg::GetPDFDocument() const { | 308 CGPDFDocumentRef PdfMetafileCg::GetPDFDocument() const { |
| 286 // Make sure that we have data, and that it's not being modified any more. | 309 // Make sure that we have data, and that it's not being modified any more. |
| 287 DCHECK(pdf_data_.get()); | 310 DCHECK(pdf_data_.get()); |
| 288 DCHECK(!context_.get()); | 311 DCHECK(!context_.get()); |
| 289 | 312 |
| 290 if (!pdf_doc_.get()) { | 313 if (!pdf_doc_.get()) { |
| 291 ScopedCFTypeRef<CGDataProviderRef> pdf_data_provider( | 314 ScopedCFTypeRef<CGDataProviderRef> pdf_data_provider( |
| 292 CGDataProviderCreateWithCFData(pdf_data_)); | 315 CGDataProviderCreateWithCFData(pdf_data_)); |
| 293 pdf_doc_.reset(CGPDFDocumentCreateWithProvider(pdf_data_provider)); | 316 pdf_doc_.reset(CGPDFDocumentCreateWithProvider(pdf_data_provider)); |
| 294 } | 317 } |
| 295 return pdf_doc_.get(); | 318 return pdf_doc_.get(); |
| 296 } | 319 } |
| 297 | 320 |
| 298 } // namespace printing | 321 } // namespace printing |
| OLD | NEW |