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

Side by Side Diff: printing/printing_context_mac.mm

Issue 345493003: Apply paper size selection for local printers on OSX. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Wed 06/18/2014 17:38:32.02 Created 6 years, 6 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 | Annotate | Revision Log
OLDNEW
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
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, &current_printer) != noErr) 262 if (PMSessionGetCurrentPrinter(print_session, &current_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
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
OLDNEW
« printing/printing_context_mac.h ('K') | « printing/printing_context_mac.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698