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