| 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 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 } | 167 } |
| 166 #endif | 168 #endif |
| 167 CGPDFContextClose(context_.get()); | 169 CGPDFContextClose(context_.get()); |
| 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 const MacRenderPageParams& params) const { |
| 176 bool stretch_to_fit, | |
| 177 bool center_horizontally, | |
| 178 bool center_vertically) const { | |
| 179 CGPDFDocumentRef pdf_doc = GetPDFDocument(); | 178 CGPDFDocumentRef pdf_doc = GetPDFDocument(); |
| 180 if (!pdf_doc) { | 179 if (!pdf_doc) { |
| 181 LOG(ERROR) << "Unable to create PDF document from data"; | 180 LOG(ERROR) << "Unable to create PDF document from data"; |
| 182 return false; | 181 return false; |
| 183 } | 182 } |
| 184 CGPDFPageRef pdf_page = CGPDFDocumentGetPage(pdf_doc, page_number); | 183 CGPDFPageRef pdf_page = CGPDFDocumentGetPage(pdf_doc, page_number); |
| 185 CGRect source_rect = CGPDFPageGetBoxRect(pdf_page, kCGPDFCropBox); | 184 CGRect source_rect = CGPDFPageGetBoxRect(pdf_page, kCGPDFCropBox); |
| 186 float scaling_factor = 1.0; | 185 float scaling_factor = 1.0; |
| 186 const bool source_is_landscape = |
| 187 (source_rect.size.width > source_rect.size.height); |
| 188 const bool dest_is_landscape = (rect.size.width > rect.size.height); |
| 189 const bool rotate = |
| 190 params.autorotate ? (source_is_landscape != dest_is_landscape) : false; |
| 191 const float source_width = |
| 192 rotate ? source_rect.size.height : source_rect.size.width; |
| 193 const float source_height = |
| 194 rotate ? source_rect.size.width : source_rect.size.height; |
| 195 |
| 187 // See if we need to scale the output. | 196 // See if we need to scale the output. |
| 188 bool scaling_needed = | 197 const bool scaling_needed = |
| 189 (shrink_to_fit && ((source_rect.size.width > rect.size.width) || | 198 (params.shrink_to_fit && ((source_width > rect.size.width) || |
| 190 (source_rect.size.height > rect.size.height))) || | 199 (source_height > rect.size.height))) || |
| 191 (stretch_to_fit && (source_rect.size.width < rect.size.width) && | 200 (params.stretch_to_fit && ((source_width < rect.size.width) && |
| 192 (source_rect.size.height < rect.size.height)); | 201 (source_height < rect.size.height))); |
| 193 if (scaling_needed) { | 202 if (scaling_needed) { |
| 194 float x_scaling_factor = rect.size.width / source_rect.size.width; | 203 float x_scaling_factor = rect.size.width / source_width; |
| 195 float y_scaling_factor = rect.size.height / source_rect.size.height; | 204 float y_scaling_factor = rect.size.height / source_height; |
| 196 if (x_scaling_factor > y_scaling_factor) { | 205 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 } | 206 } |
| 202 // Some PDFs have a non-zero origin. Need to take that into account. | 207 // 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; | 208 // the PDF to the origin. |
| 204 float y_offset = -1 * source_rect.origin.y * scaling_factor; | 209 const float x_origin_offset = -1 * source_rect.origin.x; |
| 210 const float y_origin_offset = -1 * source_rect.origin.y; |
| 205 | 211 |
| 206 if (center_horizontally) { | 212 // If the PDF needs to be centered, calculate the offsets here. |
| 207 x_offset += (rect.size.width - | 213 float x_offset = params.center_horizontally ? |
| 208 (source_rect.size.width * scaling_factor))/2; | 214 ((rect.size.width - (source_width * scaling_factor)) / 2) : 0; |
| 215 if (rotate) |
| 216 x_offset = -x_offset; |
| 217 |
| 218 float y_offset = params.center_vertically ? |
| 219 ((rect.size.height - (source_height * scaling_factor)) / 2) : 0; |
| 220 |
| 221 CGContextSaveGState(context); |
| 222 |
| 223 // The transform operations specified here gets applied in reverse order. |
| 224 // i.e. the origin offset translation happens first. |
| 225 // Origin is at bottom-left. |
| 226 CGContextTranslateCTM(context, x_offset, y_offset); |
| 227 if (rotate) { |
| 228 // After rotating by 90 degrees with the axis at the origin, the page |
| 229 // content is now "off screen". Shift it right to move it back on screen. |
| 230 CGContextTranslateCTM(context, rect.size.width, 0); |
| 231 // Rotates counter-clockwise by 90 degrees. |
| 232 CGContextRotateCTM(context, M_PI_2); |
| 209 } | 233 } |
| 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); | 234 CGContextScaleCTM(context, scaling_factor, scaling_factor); |
| 235 CGContextTranslateCTM(context, x_origin_offset, y_origin_offset); |
| 236 |
| 217 CGContextDrawPDFPage(context, pdf_page); | 237 CGContextDrawPDFPage(context, pdf_page); |
| 218 CGContextRestoreGState(context); | 238 CGContextRestoreGState(context); |
| 239 |
| 219 return true; | 240 return true; |
| 220 } | 241 } |
| 221 | 242 |
| 222 unsigned int PdfMetafileCg::GetPageCount() const { | 243 unsigned int PdfMetafileCg::GetPageCount() const { |
| 223 CGPDFDocumentRef pdf_doc = GetPDFDocument(); | 244 CGPDFDocumentRef pdf_doc = GetPDFDocument(); |
| 224 return pdf_doc ? CGPDFDocumentGetNumberOfPages(pdf_doc) : 0; | 245 return pdf_doc ? CGPDFDocumentGetNumberOfPages(pdf_doc) : 0; |
| 225 } | 246 } |
| 226 | 247 |
| 227 gfx::Rect PdfMetafileCg::GetPageBounds(unsigned int page_number) const { | 248 gfx::Rect PdfMetafileCg::GetPageBounds(unsigned int page_number) const { |
| 228 CGPDFDocumentRef pdf_doc = GetPDFDocument(); | 249 CGPDFDocumentRef pdf_doc = GetPDFDocument(); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 | 310 |
| 290 if (!pdf_doc_.get()) { | 311 if (!pdf_doc_.get()) { |
| 291 ScopedCFTypeRef<CGDataProviderRef> pdf_data_provider( | 312 ScopedCFTypeRef<CGDataProviderRef> pdf_data_provider( |
| 292 CGDataProviderCreateWithCFData(pdf_data_)); | 313 CGDataProviderCreateWithCFData(pdf_data_)); |
| 293 pdf_doc_.reset(CGPDFDocumentCreateWithProvider(pdf_data_provider)); | 314 pdf_doc_.reset(CGPDFDocumentCreateWithProvider(pdf_data_provider)); |
| 294 } | 315 } |
| 295 return pdf_doc_.get(); | 316 return pdf_doc_.get(); |
| 296 } | 317 } |
| 297 | 318 |
| 298 } // namespace printing | 319 } // namespace printing |
| OLD | NEW |