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

Side by Side Diff: printing/printing_context_win.cc

Issue 268036: Implement the basic OS-level printing mechanics on Mac (Closed)
Patch Set: Address review comments Created 11 years, 2 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
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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.h" 5 #include "printing/printing_context.h"
6 6
7 #include <winspool.h> 7 #include <winspool.h>
8 8
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/i18n/file_util_icu.h" 10 #include "base/i18n/file_util_icu.h"
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 131
132 private: 132 private:
133 PrintingContext& owner_; 133 PrintingContext& owner_;
134 HWND owner_hwnd_; 134 HWND owner_hwnd_;
135 IPrintDialogServices* services_; 135 IPrintDialogServices* services_;
136 136
137 DISALLOW_EVIL_CONSTRUCTORS(CallbackHandler); 137 DISALLOW_EVIL_CONSTRUCTORS(CallbackHandler);
138 }; 138 };
139 139
140 PrintingContext::PrintingContext() 140 PrintingContext::PrintingContext()
141 : hdc_(NULL), 141 : context_(NULL),
142 #ifndef NDEBUG 142 #ifndef NDEBUG
143 page_number_(-1), 143 page_number_(-1),
144 #endif 144 #endif
145 dialog_box_(NULL), 145 dialog_box_(NULL),
146 dialog_box_dismissed_(false), 146 dialog_box_dismissed_(false),
147 in_print_job_(false), 147 in_print_job_(false),
148 abort_printing_(false) { 148 abort_printing_(false) {
149 } 149 }
150 150
151 PrintingContext::~PrintingContext() { 151 PrintingContext::~PrintingContext() {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 234
235 // Close the printer after retrieving the context. 235 // Close the printer after retrieving the context.
236 ClosePrinter(printer); 236 ClosePrinter(printer);
237 237
238 if (status != OK) 238 if (status != OK)
239 ResetSettings(); 239 ResetSettings();
240 return status; 240 return status;
241 } 241 }
242 242
243 void PrintingContext::ResetSettings() { 243 void PrintingContext::ResetSettings() {
244 if (hdc_ != NULL) { 244 if (context_ != NULL) {
245 DeleteDC(hdc_); 245 DeleteDC(context_);
246 hdc_ = NULL; 246 context_ = NULL;
247 } 247 }
248 settings_.Clear(); 248 settings_.Clear();
249 in_print_job_ = false; 249 in_print_job_ = false;
250 250
251 #ifndef NDEBUG 251 #ifndef NDEBUG
252 page_number_ = -1; 252 page_number_ = -1;
253 #endif 253 #endif
254 } 254 }
255 255
256 PrintingContext::Result PrintingContext::NewDocument( 256 PrintingContext::Result PrintingContext::NewDocument(
257 const std::wstring& document_name) { 257 const std::wstring& document_name) {
258 DCHECK(!in_print_job_); 258 DCHECK(!in_print_job_);
259 if (!hdc_) 259 if (!context_)
260 return OnError(); 260 return OnError();
261 261
262 // Set the flag used by the AbortPrintJob dialog procedure. 262 // Set the flag used by the AbortPrintJob dialog procedure.
263 abort_printing_ = false; 263 abort_printing_ = false;
264 264
265 in_print_job_ = true; 265 in_print_job_ = true;
266 266
267 // Register the application's AbortProc function with GDI. 267 // Register the application's AbortProc function with GDI.
268 if (SP_ERROR == SetAbortProc(hdc_, &AbortProc)) 268 if (SP_ERROR == SetAbortProc(context_, &AbortProc))
269 return OnError(); 269 return OnError();
270 270
271 DOCINFO di = { sizeof(DOCINFO) }; 271 DOCINFO di = { sizeof(DOCINFO) };
272 di.lpszDocName = document_name.c_str(); 272 di.lpszDocName = document_name.c_str();
273 273
274 // Is there a debug dump directory specified? If so, force to print to a file. 274 // Is there a debug dump directory specified? If so, force to print to a file.
275 std::wstring debug_dump_path = PrintedDocument::debug_dump_path(); 275 std::wstring debug_dump_path = PrintedDocument::debug_dump_path();
276 if (!debug_dump_path.empty()) { 276 if (!debug_dump_path.empty()) {
277 // Create a filename. 277 // Create a filename.
278 std::wstring filename; 278 std::wstring filename;
(...skipping 10 matching lines...) Expand all
289 di.lpszOutput = debug_dump_path.c_str(); 289 di.lpszOutput = debug_dump_path.c_str();
290 } 290 }
291 291
292 // No message loop running in unit tests. 292 // No message loop running in unit tests.
293 DCHECK(!MessageLoop::current() ? true : 293 DCHECK(!MessageLoop::current() ? true :
294 !MessageLoop::current()->NestableTasksAllowed()); 294 !MessageLoop::current()->NestableTasksAllowed());
295 295
296 // Begin a print job by calling the StartDoc function. 296 // Begin a print job by calling the StartDoc function.
297 // NOTE: StartDoc() starts a message loop. That causes a lot of problems with 297 // NOTE: StartDoc() starts a message loop. That causes a lot of problems with
298 // IPC. Make sure recursive task processing is disabled. 298 // IPC. Make sure recursive task processing is disabled.
299 if (StartDoc(hdc_, &di) <= 0) 299 if (StartDoc(context_, &di) <= 0)
300 return OnError(); 300 return OnError();
301 301
302 #ifndef NDEBUG 302 #ifndef NDEBUG
303 page_number_ = 0; 303 page_number_ = 0;
304 #endif 304 #endif
305 return OK; 305 return OK;
306 } 306 }
307 307
308 PrintingContext::Result PrintingContext::NewPage() { 308 PrintingContext::Result PrintingContext::NewPage() {
309 if (abort_printing_) 309 if (abort_printing_)
310 return CANCEL; 310 return CANCEL;
311 DCHECK(in_print_job_); 311 DCHECK(in_print_job_);
312 312
313 // Inform the driver that the application is about to begin sending data. 313 // Inform the driver that the application is about to begin sending data.
314 if (StartPage(hdc_) <= 0) 314 if (StartPage(context_) <= 0)
315 return OnError(); 315 return OnError();
316 316
317 #ifndef NDEBUG 317 #ifndef NDEBUG
318 ++page_number_; 318 ++page_number_;
319 #endif 319 #endif
320 320
321 return OK; 321 return OK;
322 } 322 }
323 323
324 PrintingContext::Result PrintingContext::PageDone() { 324 PrintingContext::Result PrintingContext::PageDone() {
325 if (abort_printing_) 325 if (abort_printing_)
326 return CANCEL; 326 return CANCEL;
327 DCHECK(in_print_job_); 327 DCHECK(in_print_job_);
328 328
329 if (EndPage(hdc_) <= 0) 329 if (EndPage(context_) <= 0)
330 return OnError(); 330 return OnError();
331 return OK; 331 return OK;
332 } 332 }
333 333
334 PrintingContext::Result PrintingContext::DocumentDone() { 334 PrintingContext::Result PrintingContext::DocumentDone() {
335 if (abort_printing_) 335 if (abort_printing_)
336 return CANCEL; 336 return CANCEL;
337 DCHECK(in_print_job_); 337 DCHECK(in_print_job_);
338 338
339 // Inform the driver that document has ended. 339 // Inform the driver that document has ended.
340 if (EndDoc(hdc_) <= 0) 340 if (EndDoc(context_) <= 0)
341 return OnError(); 341 return OnError();
342 342
343 ResetSettings(); 343 ResetSettings();
344 return OK; 344 return OK;
345 } 345 }
346 346
347 void PrintingContext::Cancel() { 347 void PrintingContext::Cancel() {
348 abort_printing_ = true; 348 abort_printing_ = true;
349 in_print_job_ = false; 349 in_print_job_ = false;
350 if (hdc_) 350 if (context_)
351 CancelDC(hdc_); 351 CancelDC(context_);
352 DismissDialog(); 352 DismissDialog();
353 } 353 }
354 354
355 void PrintingContext::DismissDialog() { 355 void PrintingContext::DismissDialog() {
356 if (dialog_box_) { 356 if (dialog_box_) {
357 DestroyWindow(dialog_box_); 357 DestroyWindow(dialog_box_);
358 dialog_box_dismissed_ = true; 358 dialog_box_dismissed_ = true;
359 } 359 }
360 } 360 }
361 361
362 PrintingContext::Result PrintingContext::OnError() { 362 PrintingContext::Result PrintingContext::OnError() {
363 // This will close hdc_ and clear settings_. 363 // This will close context_ and clear settings_.
364 ResetSettings(); 364 ResetSettings();
365 return abort_printing_ ? CANCEL : FAILED; 365 return abort_printing_ ? CANCEL : FAILED;
366 } 366 }
367 367
368 // static 368 // static
369 BOOL PrintingContext::AbortProc(HDC hdc, int nCode) { 369 BOOL PrintingContext::AbortProc(HDC hdc, int nCode) {
370 if (nCode) { 370 if (nCode) {
371 // TODO(maruel): Need a way to find the right instance to set. Should 371 // TODO(maruel): Need a way to find the right instance to set. Should
372 // leverage PrintJobManager here? 372 // leverage PrintJobManager here?
373 // abort_printing_ = true; 373 // abort_printing_ = true;
374 } 374 }
375 return true; 375 return true;
376 } 376 }
377 377
378 bool PrintingContext::InitializeSettings(const DEVMODE& dev_mode, 378 bool PrintingContext::InitializeSettings(const DEVMODE& dev_mode,
379 const std::wstring& new_device_name, 379 const std::wstring& new_device_name,
380 const PRINTPAGERANGE* ranges, 380 const PRINTPAGERANGE* ranges,
381 int number_ranges, 381 int number_ranges,
382 bool selection_only) { 382 bool selection_only) {
383 skia::PlatformDevice::InitializeDC(hdc_); 383 skia::PlatformDevice::InitializeDC(context_);
384 DCHECK(GetDeviceCaps(hdc_, CLIPCAPS)); 384 DCHECK(GetDeviceCaps(context_, CLIPCAPS));
385 DCHECK(GetDeviceCaps(hdc_, RASTERCAPS) & RC_STRETCHDIB); 385 DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_STRETCHDIB);
386 DCHECK(GetDeviceCaps(hdc_, RASTERCAPS) & RC_BITMAP64); 386 DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_BITMAP64);
387 // Some printers don't advertise these. 387 // Some printers don't advertise these.
388 // DCHECK(GetDeviceCaps(hdc_, RASTERCAPS) & RC_SCALING); 388 // DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_SCALING);
389 // DCHECK(GetDeviceCaps(hdc_, SHADEBLENDCAPS) & SB_CONST_ALPHA); 389 // DCHECK(GetDeviceCaps(context_, SHADEBLENDCAPS) & SB_CONST_ALPHA);
390 // DCHECK(GetDeviceCaps(hdc_, SHADEBLENDCAPS) & SB_PIXEL_ALPHA); 390 // DCHECK(GetDeviceCaps(context_, SHADEBLENDCAPS) & SB_PIXEL_ALPHA);
391 391
392 // StretchDIBits() support is needed for printing. 392 // StretchDIBits() support is needed for printing.
393 if (!(GetDeviceCaps(hdc_, RASTERCAPS) & RC_STRETCHDIB) || 393 if (!(GetDeviceCaps(context_, RASTERCAPS) & RC_STRETCHDIB) ||
394 !(GetDeviceCaps(hdc_, RASTERCAPS) & RC_BITMAP64)) { 394 !(GetDeviceCaps(context_, RASTERCAPS) & RC_BITMAP64)) {
395 NOTREACHED(); 395 NOTREACHED();
396 ResetSettings(); 396 ResetSettings();
397 return false; 397 return false;
398 } 398 }
399 399
400 DCHECK(!in_print_job_); 400 DCHECK(!in_print_job_);
401 DCHECK(hdc_); 401 DCHECK(context_);
402 PageRanges ranges_vector; 402 PageRanges ranges_vector;
403 if (!selection_only) { 403 if (!selection_only) {
404 // Convert the PRINTPAGERANGE array to a PrintSettings::PageRanges vector. 404 // Convert the PRINTPAGERANGE array to a PrintSettings::PageRanges vector.
405 ranges_vector.reserve(number_ranges); 405 ranges_vector.reserve(number_ranges);
406 for (int i = 0; i < number_ranges; ++i) { 406 for (int i = 0; i < number_ranges; ++i) {
407 PageRange range; 407 PageRange range;
408 // Transfer from 1-based to 0-based. 408 // Transfer from 1-based to 0-based.
409 range.from = ranges[i].nFromPage - 1; 409 range.from = ranges[i].nFromPage - 1;
410 range.to = ranges[i].nToPage - 1; 410 range.to = ranges[i].nToPage - 1;
411 ranges_vector.push_back(range); 411 ranges_vector.push_back(range);
412 } 412 }
413 } 413 }
414 settings_.Init(hdc_, 414 settings_.Init(context_,
415 dev_mode, 415 dev_mode,
416 ranges_vector, 416 ranges_vector,
417 new_device_name, 417 new_device_name,
418 selection_only); 418 selection_only);
419 return true; 419 return true;
420 } 420 }
421 421
422 bool PrintingContext::GetPrinterSettings(HANDLE printer, 422 bool PrintingContext::GetPrinterSettings(HANDLE printer,
423 const std::wstring& device_name) { 423 const std::wstring& device_name) {
424 DCHECK(!in_print_job_); 424 DCHECK(!in_print_job_);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 } 467 }
468 buffer.reset(); 468 buffer.reset();
469 } 469 }
470 // Failed to retrieve the printer settings. 470 // Failed to retrieve the printer settings.
471 ResetSettings(); 471 ResetSettings();
472 return false; 472 return false;
473 } 473 }
474 474
475 bool PrintingContext::AllocateContext(const std::wstring& printer_name, 475 bool PrintingContext::AllocateContext(const std::wstring& printer_name,
476 const DEVMODE* dev_mode) { 476 const DEVMODE* dev_mode) {
477 hdc_ = CreateDC(L"WINSPOOL", printer_name.c_str(), NULL, dev_mode); 477 context_ = CreateDC(L"WINSPOOL", printer_name.c_str(), NULL, dev_mode);
478 DCHECK(hdc_); 478 DCHECK(context_);
479 return hdc_ != NULL; 479 return context_ != NULL;
480 } 480 }
481 481
482 PrintingContext::Result PrintingContext::ParseDialogResultEx( 482 PrintingContext::Result PrintingContext::ParseDialogResultEx(
483 const PRINTDLGEX& dialog_options) { 483 const PRINTDLGEX& dialog_options) {
484 // If the user clicked OK or Apply then Cancel, but not only Cancel. 484 // If the user clicked OK or Apply then Cancel, but not only Cancel.
485 if (dialog_options.dwResultAction != PD_RESULT_CANCEL) { 485 if (dialog_options.dwResultAction != PD_RESULT_CANCEL) {
486 // Start fresh. 486 // Start fresh.
487 ResetSettings(); 487 ResetSettings();
488 488
489 DEVMODE* dev_mode = NULL; 489 DEVMODE* dev_mode = NULL;
(...skipping 12 matching lines...) Expand all
502 device_name = 502 device_name =
503 reinterpret_cast<const wchar_t*>( 503 reinterpret_cast<const wchar_t*>(
504 reinterpret_cast<const wchar_t*>(dev_names) + 504 reinterpret_cast<const wchar_t*>(dev_names) +
505 dev_names->wDeviceOffset); 505 dev_names->wDeviceOffset);
506 GlobalUnlock(dialog_options.hDevNames); 506 GlobalUnlock(dialog_options.hDevNames);
507 } 507 }
508 } 508 }
509 509
510 bool success = false; 510 bool success = false;
511 if (dev_mode && !device_name.empty()) { 511 if (dev_mode && !device_name.empty()) {
512 hdc_ = dialog_options.hDC; 512 context_ = dialog_options.hDC;
513 PRINTPAGERANGE* page_ranges = NULL; 513 PRINTPAGERANGE* page_ranges = NULL;
514 DWORD num_page_ranges = 0; 514 DWORD num_page_ranges = 0;
515 bool print_selection_only = false; 515 bool print_selection_only = false;
516 if (dialog_options.Flags & PD_PAGENUMS) { 516 if (dialog_options.Flags & PD_PAGENUMS) {
517 page_ranges = dialog_options.lpPageRanges; 517 page_ranges = dialog_options.lpPageRanges;
518 num_page_ranges = dialog_options.nPageRanges; 518 num_page_ranges = dialog_options.nPageRanges;
519 } 519 }
520 if (dialog_options.Flags & PD_SELECTION) { 520 if (dialog_options.Flags & PD_SELECTION) {
521 print_selection_only = true; 521 print_selection_only = true;
522 } 522 }
523 success = InitializeSettings(*dev_mode, 523 success = InitializeSettings(*dev_mode,
524 device_name, 524 device_name,
525 dialog_options.lpPageRanges, 525 dialog_options.lpPageRanges,
526 dialog_options.nPageRanges, 526 dialog_options.nPageRanges,
527 print_selection_only); 527 print_selection_only);
528 } 528 }
529 529
530 if (!success && dialog_options.hDC) { 530 if (!success && dialog_options.hDC) {
531 DeleteDC(dialog_options.hDC); 531 DeleteDC(dialog_options.hDC);
532 hdc_ = NULL; 532 context_ = NULL;
533 } 533 }
534 534
535 if (dev_mode) { 535 if (dev_mode) {
536 GlobalUnlock(dialog_options.hDevMode); 536 GlobalUnlock(dialog_options.hDevMode);
537 } 537 }
538 } else { 538 } else {
539 if (dialog_options.hDC) { 539 if (dialog_options.hDC) {
540 DeleteDC(dialog_options.hDC); 540 DeleteDC(dialog_options.hDC);
541 } 541 }
542 } 542 }
543 543
544 if (dialog_options.hDevMode != NULL) 544 if (dialog_options.hDevMode != NULL)
545 GlobalFree(dialog_options.hDevMode); 545 GlobalFree(dialog_options.hDevMode);
546 if (dialog_options.hDevNames != NULL) 546 if (dialog_options.hDevNames != NULL)
547 GlobalFree(dialog_options.hDevNames); 547 GlobalFree(dialog_options.hDevNames);
548 548
549 switch (dialog_options.dwResultAction) { 549 switch (dialog_options.dwResultAction) {
550 case PD_RESULT_PRINT: 550 case PD_RESULT_PRINT:
551 return hdc_ ? OK : FAILED; 551 return context_ ? OK : FAILED;
552 case PD_RESULT_APPLY: 552 case PD_RESULT_APPLY:
553 return hdc_ ? CANCEL : FAILED; 553 return context_ ? CANCEL : FAILED;
554 case PD_RESULT_CANCEL: 554 case PD_RESULT_CANCEL:
555 return CANCEL; 555 return CANCEL;
556 default: 556 default:
557 return FAILED; 557 return FAILED;
558 } 558 }
559 } 559 }
560 560
561 PrintingContext::Result PrintingContext::ParseDialogResult( 561 PrintingContext::Result PrintingContext::ParseDialogResult(
562 const PRINTDLG& dialog_options) { 562 const PRINTDLG& dialog_options) {
563 // If the user clicked OK or Apply then Cancel, but not only Cancel. 563 // If the user clicked OK or Apply then Cancel, but not only Cancel.
(...skipping 16 matching lines...) Expand all
580 device_name = 580 device_name =
581 reinterpret_cast<const wchar_t*>( 581 reinterpret_cast<const wchar_t*>(
582 reinterpret_cast<const wchar_t*>(dev_names) + 582 reinterpret_cast<const wchar_t*>(dev_names) +
583 dev_names->wDeviceOffset); 583 dev_names->wDeviceOffset);
584 GlobalUnlock(dialog_options.hDevNames); 584 GlobalUnlock(dialog_options.hDevNames);
585 } 585 }
586 } 586 }
587 587
588 bool success = false; 588 bool success = false;
589 if (dev_mode && !device_name.empty()) { 589 if (dev_mode && !device_name.empty()) {
590 hdc_ = dialog_options.hDC; 590 context_ = dialog_options.hDC;
591 success = InitializeSettings(*dev_mode, device_name, NULL, 0, false); 591 success = InitializeSettings(*dev_mode, device_name, NULL, 0, false);
592 } 592 }
593 593
594 if (!success && dialog_options.hDC) { 594 if (!success && dialog_options.hDC) {
595 DeleteDC(dialog_options.hDC); 595 DeleteDC(dialog_options.hDC);
596 hdc_ = NULL; 596 context_ = NULL;
597 } 597 }
598 598
599 if (dev_mode) { 599 if (dev_mode) {
600 GlobalUnlock(dialog_options.hDevMode); 600 GlobalUnlock(dialog_options.hDevMode);
601 } 601 }
602 602
603 if (dialog_options.hDevMode != NULL) 603 if (dialog_options.hDevMode != NULL)
604 GlobalFree(dialog_options.hDevMode); 604 GlobalFree(dialog_options.hDevMode);
605 if (dialog_options.hDevNames != NULL) 605 if (dialog_options.hDevNames != NULL)
606 GlobalFree(dialog_options.hDevNames); 606 GlobalFree(dialog_options.hDevNames);
607 607
608 return hdc_ ? OK : FAILED; 608 return context_ ? OK : FAILED;
609 } 609 }
610 610
611 } // namespace printing 611 } // namespace printing
OLDNEW
« printing/printed_document_mac.cc ('K') | « printing/printing_context_mac.mm ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698