Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/printing_context_mac.h" | 5 #include "printing/printing_context_mac.h" |
| 6 | 6 |
| 7 #import <ApplicationServices/ApplicationServices.h> | 7 #import <ApplicationServices/ApplicationServices.h> |
| 8 #import <AppKit/AppKit.h> | 8 #import <AppKit/AppKit.h> |
| 9 | 9 |
| 10 #import <iomanip> | 10 #import <iomanip> |
| 11 #import <numeric> | 11 #import <numeric> |
| 12 | 12 |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/mac/scoped_cftyperef.h" | 14 #include "base/mac/scoped_cftyperef.h" |
| 15 #include "base/mac/scoped_nsautorelease_pool.h" | 15 #include "base/mac/scoped_nsautorelease_pool.h" |
| 16 #include "base/mac/scoped_nsexception_enabler.h" | 16 #include "base/mac/scoped_nsexception_enabler.h" |
| 17 #include "base/strings/sys_string_conversions.h" | 17 #include "base/strings/sys_string_conversions.h" |
| 18 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
| 19 #include "base/values.h" | 19 #include "base/values.h" |
| 20 #include "printing/print_settings_initializer_mac.h" | 20 #include "printing/print_settings_initializer_mac.h" |
| 21 #include "printing/units.h" | 21 #include "printing/units.h" |
| 22 | 22 |
| 23 namespace printing { | 23 namespace printing { |
| 24 | 24 |
| 25 namespace { | 25 namespace { |
| 26 | 26 |
| 27 // Return true if PPD name of paper is equal. | 27 // Return true if PPD name of paper is equal. |
| 28 bool IsPaperNameEqual(const PMPaper& paper1, const PMPaper& paper2) { | 28 bool IsPaperNameEqual(CFStringRef name1, const PMPaper& paper2) { |
| 29 CFStringRef name1 = NULL; | |
| 30 CFStringRef name2 = NULL; | 29 CFStringRef name2 = NULL; |
| 31 return (PMPaperGetPPDPaperName(paper1, &name1) == noErr) && | 30 return (name1 && PMPaperGetPPDPaperName(paper2, &name2) == noErr) && |
| 32 (PMPaperGetPPDPaperName(paper2, &name2) == noErr) && | 31 (CFStringCompare(name1, name2, kCFCompareCaseInsensitive) == |
| 33 (CFStringCompare(name1, name2, | 32 kCFCompareEqualTo); |
| 34 kCFCompareCaseInsensitive) == kCFCompareEqualTo); | 33 } |
| 34 | |
| 35 PMPaper MatchPaper(CFArrayRef paper_list, | |
| 36 CFStringRef name, | |
| 37 double width, | |
| 38 double height) { | |
| 39 double best_match = std::numeric_limits<double>::max(); | |
| 40 PMPaper best_matching_paper = NULL; | |
| 41 int num_papers = CFArrayGetCount(paper_list); | |
| 42 for (int i = 0; i < num_papers; ++i) { | |
| 43 PMPaper paper = (PMPaper)[(NSArray*)paper_list objectAtIndex : i]; | |
| 44 double paper_width = 0.0; | |
| 45 double paper_height = 0.0; | |
| 46 PMPaperGetWidth(paper, &paper_width); | |
| 47 PMPaperGetHeight(paper, &paper_height); | |
| 48 double difference = | |
| 49 std::max(fabs(width - paper_width), fabs(height - paper_height)); | |
| 50 | |
| 51 // Ignore paper sizes that are very different. | |
| 52 if (difference > 2) | |
|
Aleksey Shlyapnikov
2014/06/19 02:13:08
Make it a constant with units in the name, so it's
Vitaly Buka (NO REVIEWS)
2014/06/19 17:44:38
Done.
| |
| 53 continue; | |
| 54 | |
| 55 if (name && IsPaperNameEqual(name, paper)) | |
| 56 return paper; | |
| 57 | |
| 58 if (difference < best_match) { | |
| 59 best_matching_paper = paper; | |
| 60 best_match = difference; | |
| 61 } | |
| 62 } | |
| 63 return best_matching_paper; | |
| 35 } | 64 } |
| 36 | 65 |
| 37 } // namespace | 66 } // namespace |
| 38 | 67 |
| 39 // static | 68 // static |
| 40 PrintingContext* PrintingContext::Create(const std::string& app_locale) { | 69 PrintingContext* PrintingContext::Create(const std::string& app_locale) { |
| 41 return static_cast<PrintingContext*>(new PrintingContextMac(app_locale)); | 70 return static_cast<PrintingContext*>(new PrintingContextMac(app_locale)); |
| 42 } | 71 } |
| 43 | 72 |
| 44 PrintingContextMac::PrintingContextMac(const std::string& app_locale) | 73 PrintingContextMac::PrintingContextMac(const std::string& app_locale) |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 207 base::SysUTF8ToCFStringRef(device_name)); | 236 base::SysUTF8ToCFStringRef(device_name)); |
| 208 if (!new_printer_id.get()) | 237 if (!new_printer_id.get()) |
| 209 return false; | 238 return false; |
| 210 | 239 |
| 211 if (CFStringCompare(new_printer_id.get(), current_printer_id, 0) == | 240 if (CFStringCompare(new_printer_id.get(), current_printer_id, 0) == |
| 212 kCFCompareEqualTo) { | 241 kCFCompareEqualTo) { |
| 213 return true; | 242 return true; |
| 214 } | 243 } |
| 215 | 244 |
| 216 PMPrinter new_printer = PMPrinterCreateFromPrinterID(new_printer_id.get()); | 245 PMPrinter new_printer = PMPrinterCreateFromPrinterID(new_printer_id.get()); |
| 217 if (new_printer == NULL) | 246 if (!new_printer) |
| 218 return false; | 247 return false; |
| 219 | 248 |
| 220 OSStatus status = PMSessionSetCurrentPMPrinter(print_session, new_printer); | 249 OSStatus status = PMSessionSetCurrentPMPrinter(print_session, new_printer); |
| 221 PMRelease(new_printer); | 250 PMRelease(new_printer); |
| 222 return status == noErr; | 251 return status == noErr; |
| 223 } | 252 } |
| 224 | 253 |
| 225 bool PrintingContextMac::UpdatePageFormatWithPaperInfo() { | 254 bool PrintingContextMac::UpdatePageFormatWithPaperInfo() { |
| 226 PMPrintSession print_session = | 255 PMPrintSession print_session = |
| 227 static_cast<PMPrintSession>([print_info_.get() PMPrintSession]); | 256 static_cast<PMPrintSession>([print_info_.get() PMPrintSession]); |
| 228 | 257 |
| 229 PMPageFormat default_page_format = | 258 PMPageFormat default_page_format = |
| 230 static_cast<PMPageFormat>([print_info_.get() PMPageFormat]); | 259 static_cast<PMPageFormat>([print_info_.get() PMPageFormat]); |
| 231 | 260 |
| 232 PMPaper default_paper; | |
| 233 if (PMGetPageFormatPaper(default_page_format, &default_paper) != noErr) | |
| 234 return false; | |
| 235 | |
| 236 double default_page_width = 0.0; | |
| 237 double default_page_height = 0.0; | |
| 238 if (PMPaperGetWidth(default_paper, &default_page_width) != noErr) | |
| 239 return false; | |
| 240 | |
| 241 if (PMPaperGetHeight(default_paper, &default_page_height) != noErr) | |
| 242 return false; | |
| 243 | |
| 244 PMPrinter current_printer = NULL; | 261 PMPrinter current_printer = NULL; |
| 245 if (PMSessionGetCurrentPrinter(print_session, ¤t_printer) != noErr) | 262 if (PMSessionGetCurrentPrinter(print_session, ¤t_printer) != noErr) |
| 246 return false; | 263 return false; |
| 247 | 264 |
| 248 if (current_printer == nil) | 265 double page_width = 0.0; |
| 249 return false; | 266 double page_height = 0.0; |
| 267 base::ScopedCFTypeRef<CFStringRef> paper_name; | |
| 268 PMPaperMargins margins = {0}; | |
| 269 | |
| 270 const PrintSettings::RequestedMedia& media = settings_.requested_media(); | |
| 271 if (media.size_microns.IsEmpty()) { | |
|
Aleksey Shlyapnikov
2014/06/19 02:13:08
media.IsDefault().
Vitaly Buka (NO REVIEWS)
2014/06/19 17:44:38
Done.
| |
| 272 PMPaper default_paper; | |
| 273 if (PMGetPageFormatPaper(default_page_format, &default_paper) != noErr || | |
| 274 PMPaperGetWidth(default_paper, &page_width) != noErr || | |
| 275 PMPaperGetHeight(default_paper, &page_height) != noErr) { | |
| 276 return false; | |
| 277 } | |
| 278 | |
| 279 // Ignore result, because we can continue without following. | |
| 280 CFStringRef tmp_paper_name = NULL; | |
| 281 PMPaperGetPPDPaperName(default_paper, &tmp_paper_name); | |
| 282 PMPaperGetMargins(default_paper, &margins); | |
| 283 paper_name.reset(tmp_paper_name, base::scoped_policy::RETAIN); | |
| 284 } else { | |
| 285 const double kMutiplier = kPointsPerInch / (10.0f * kHundrethsMMPerInch); | |
| 286 page_width = media.size_microns.width() * kMutiplier; | |
| 287 page_height = media.size_microns.height() * kMutiplier; | |
| 288 paper_name.reset(base::SysUTF8ToCFStringRef(media.vendor_id)); | |
| 289 } | |
| 250 | 290 |
| 251 CFArrayRef paper_list = NULL; | 291 CFArrayRef paper_list = NULL; |
| 252 if (PMPrinterGetPaperList(current_printer, &paper_list) != noErr) | 292 if (PMPrinterGetPaperList(current_printer, &paper_list) != noErr) |
| 253 return false; | 293 return false; |
| 254 | 294 |
| 255 double best_match = std::numeric_limits<double>::max(); | 295 PMPaper best_matching_paper = |
| 256 PMPaper best_matching_paper = kPMNoData; | 296 MatchPaper(paper_list, paper_name, page_width, page_height); |
| 257 int num_papers = CFArrayGetCount(paper_list); | 297 |
| 258 for (int i = 0; i < num_papers; ++i) { | 298 if (best_matching_paper) |
| 259 PMPaper paper = (PMPaper)[(NSArray*)paper_list objectAtIndex: i]; | 299 return UpdatePageFormatWithPaper(best_matching_paper, default_page_format); |
| 260 double paper_width = 0.0; | 300 |
| 261 double paper_height = 0.0; | 301 // Do nothing if we can't match default system paper. It's already set there. |
| 262 PMPaperGetWidth(paper, &paper_width); | 302 if (media.size_microns.IsEmpty()) |
|
Aleksey Shlyapnikov
2014/06/19 02:13:08
media.IsDefault()
Vitaly Buka (NO REVIEWS)
2014/06/19 17:44:38
Done.
| |
| 263 PMPaperGetHeight(paper, &paper_height); | 303 return true; |
| 264 double current_match = std::max(fabs(default_page_width - paper_width), | 304 |
| 265 fabs(default_page_height - paper_height)); | 305 PMPaper paper = NULL; |
| 266 // Ignore paper sizes that are very different. | 306 if (PMPaperCreateCustom(current_printer, |
| 267 if (current_match > 2) | 307 CFSTR("Custom paper ID"), |
| 268 continue; | 308 CFSTR("Custom paper"), |
| 269 current_match += IsPaperNameEqual(paper, default_paper) ? 0 : 1; | 309 page_width, |
| 270 if (current_match < best_match) { | 310 page_height, |
| 271 best_matching_paper = paper; | 311 &margins, |
| 272 best_match = current_match; | 312 &paper) != noErr) { |
| 273 } | 313 return false; |
| 274 } | 314 } |
| 315 bool result = UpdatePageFormatWithPaper(paper, default_page_format); | |
| 316 PMRelease(paper); | |
| 317 return result; | |
| 318 } | |
| 275 | 319 |
| 276 if (best_matching_paper == kPMNoData) { | 320 bool PrintingContextMac::UpdatePageFormatWithPaper(PMPaper paper, |
| 277 PMPaper paper = kPMNoData; | 321 PMPageFormat page_format) { |
| 278 // Create a custom paper for the specified default page size. | 322 PMPageFormat new_format = NULL; |
| 279 PMPaperMargins default_margins; | 323 if (PMCreatePageFormatWithPMPaper(&new_format, paper) != noErr) |
| 280 if (PMPaperGetMargins(default_paper, &default_margins) != noErr) | 324 return false; |
| 281 return false; | 325 // Copy over the original format with the new page format. |
| 282 | 326 bool result = (PMCopyPageFormat(new_format, page_format) == noErr); |
| 283 const PMPaperMargins margins = | 327 [print_info_.get() updateFromPMPageFormat]; |
| 284 {default_margins.top, default_margins.left, default_margins.bottom, | 328 PMRelease(new_format); |
| 285 default_margins.right}; | 329 return result; |
| 286 CFStringRef paper_id = CFSTR("Custom paper ID"); | |
| 287 CFStringRef paper_name = CFSTR("Custom paper"); | |
| 288 if (PMPaperCreateCustom(current_printer, paper_id, paper_name, | |
| 289 default_page_width, default_page_height, &margins, &paper) != | |
| 290 noErr) { | |
| 291 return false; | |
| 292 } | |
| 293 [print_info_.get() updateFromPMPageFormat]; | |
| 294 PMRelease(paper); | |
| 295 } else { | |
| 296 PMPageFormat chosen_page_format = NULL; | |
| 297 if (PMCreatePageFormat((PMPageFormat*) &chosen_page_format) != noErr) | |
| 298 return false; | |
| 299 | |
| 300 // Create page format from that paper. | |
| 301 if (PMCreatePageFormatWithPMPaper(&chosen_page_format, | |
| 302 best_matching_paper) != noErr) { | |
| 303 PMRelease(chosen_page_format); | |
| 304 return false; | |
| 305 } | |
| 306 // Copy over the original format with the new page format. | |
| 307 if (PMCopyPageFormat(chosen_page_format, default_page_format) != noErr) { | |
| 308 PMRelease(chosen_page_format); | |
| 309 return false; | |
| 310 } | |
| 311 [print_info_.get() updateFromPMPageFormat]; | |
| 312 PMRelease(chosen_page_format); | |
| 313 } | |
| 314 return true; | |
| 315 } | 330 } |
| 316 | 331 |
| 317 bool PrintingContextMac::SetCopiesInPrintSettings(int copies) { | 332 bool PrintingContextMac::SetCopiesInPrintSettings(int copies) { |
| 318 if (copies < 1) | 333 if (copies < 1) |
| 319 return false; | 334 return false; |
| 320 | 335 |
| 321 PMPrintSettings pmPrintSettings = | 336 PMPrintSettings pmPrintSettings = |
| 322 static_cast<PMPrintSettings>([print_info_.get() PMPrintSettings]); | 337 static_cast<PMPrintSettings>([print_info_.get() PMPrintSettings]); |
| 323 return PMSetCopies(pmPrintSettings, copies, false) == noErr; | 338 return PMSetCopies(pmPrintSettings, copies, false) == noErr; |
| 324 } | 339 } |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 499 void PrintingContextMac::ReleaseContext() { | 514 void PrintingContextMac::ReleaseContext() { |
| 500 print_info_.reset(); | 515 print_info_.reset(); |
| 501 context_ = NULL; | 516 context_ = NULL; |
| 502 } | 517 } |
| 503 | 518 |
| 504 gfx::NativeDrawingContext PrintingContextMac::context() const { | 519 gfx::NativeDrawingContext PrintingContextMac::context() const { |
| 505 return context_; | 520 return context_; |
| 506 } | 521 } |
| 507 | 522 |
| 508 } // namespace printing | 523 } // namespace printing |
| OLD | NEW |