diff options
author | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-14 20:19:54 +0000 |
---|---|---|
committer | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-14 20:19:54 +0000 |
commit | b3b6b6fca87730c2bdda9c75d06c8823731db433 (patch) | |
tree | e552af1b44c8871683ca0dac7d7e9518e3f1c71b /printing/backend/win_helper.cc | |
parent | d652c33131ef384aea1f3a794957c1154fbc599d (diff) | |
download | chromium_src-b3b6b6fca87730c2bdda9c75d06c8823731db433.zip chromium_src-b3b6b6fca87730c2bdda9c75d06c8823731db433.tar.gz chromium_src-b3b6b6fca87730c2bdda9c75d06c8823731db433.tar.bz2 |
Use XPS to set color for HP printers.
Wrap DocumentProperties into printing::CreateDevMode().
BUG=166587
Review URL: https://codereview.chromium.org/165993002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@251408 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'printing/backend/win_helper.cc')
-rw-r--r-- | printing/backend/win_helper.cc | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/printing/backend/win_helper.cc b/printing/backend/win_helper.cc index f7b3310..8a66720 100644 --- a/printing/backend/win_helper.cc +++ b/printing/backend/win_helper.cc @@ -10,7 +10,11 @@ #include "base/files/file_path.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" +#include "base/numerics/safe_conversions.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "base/win/scoped_comptr.h" #include "printing/backend/print_backend.h" #include "printing/backend/print_backend_consts.h" #include "printing/backend/printing_info_win.h" @@ -75,6 +79,42 @@ PTReleaseMemoryProc g_release_memory_proc = NULL; PTCloseProviderProc g_close_provider_proc = NULL; StartXpsPrintJobProc g_start_xps_print_job_proc = NULL; +HRESULT StreamFromPrintTicket(const std::string& print_ticket, + IStream** stream) { + DCHECK(stream); + HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, stream); + if (FAILED(hr)) { + return hr; + } + ULONG bytes_written = 0; + (*stream)->Write(print_ticket.c_str(), + base::checked_cast<ULONG>(print_ticket.length()), + &bytes_written); + DCHECK(bytes_written == print_ticket.length()); + LARGE_INTEGER pos = {0}; + ULARGE_INTEGER new_pos = {0}; + (*stream)->Seek(pos, STREAM_SEEK_SET, &new_pos); + return S_OK; +} + +const char kXpsTicketTemplate[] = + "<?xml version='1.0' encoding='UTF-8'?>" + "<psf:PrintTicket " + "xmlns:psf='" + "http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework' " + "xmlns:psk=" + "'http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords' " + "version='1'>" + "<psf:Feature name='psk:PageOutputColor'>" + "<psf:Option name='psk:%s'>" + "</psf:Option>" + "</psf:Feature>" + "</psf:PrintTicket>"; + +const char kXpsTicketColor[] = "Color"; +const char kXpsTicketMonochrome[] = "Monochrome"; + + } // namespace @@ -345,4 +385,98 @@ std::string GetDriverInfo(HANDLE printer) { return driver_info; } +scoped_ptr<DEVMODE[]> XpsTicketToDevMode(const base::string16& printer_name, + const std::string& print_ticket) { + scoped_ptr<DEVMODE[]> scoped_dev_mode; + printing::ScopedXPSInitializer xps_initializer; + if (!xps_initializer.initialized()) { + // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll) + return scoped_dev_mode.Pass(); + } + + printing::ScopedPrinterHandle printer; + if (!printer.OpenPrinter(printer_name.c_str())) + return scoped_dev_mode.Pass(); + + base::win::ScopedComPtr<IStream> pt_stream; + HRESULT hr = StreamFromPrintTicket(print_ticket, pt_stream.Receive()); + if (FAILED(hr)) + return scoped_dev_mode.Pass(); + + HPTPROVIDER provider = NULL; + hr = printing::XPSModule::OpenProvider(printer_name, 1, &provider); + if (SUCCEEDED(hr)) { + ULONG size = 0; + DEVMODE* dm = NULL; + // Use kPTJobScope, because kPTDocumentScope breaks duplex. + hr = printing::XPSModule::ConvertPrintTicketToDevMode(provider, + pt_stream, + kUserDefaultDevmode, + kPTJobScope, + &size, + &dm, + NULL); + if (SUCCEEDED(hr)) { + // Correct DEVMODE using DocumentProperties. See documentation for + // PTConvertPrintTicketToDevMode. + scoped_dev_mode = CreateDevMode(printer, dm); + printing::XPSModule::ReleaseMemory(dm); + } + printing::XPSModule::CloseProvider(provider); + } + return scoped_dev_mode.Pass(); +} + +scoped_ptr<DEVMODE[]> CreateDevModeWithColor(HANDLE printer, + const base::string16& printer_name, + bool color) { + scoped_ptr<DEVMODE[]> default = CreateDevMode(printer, NULL); + if (default && (default.get()->dmFields & DM_COLOR) && + (default.get()->dmColor == DMCOLOR_COLOR) == color) { + return default.Pass(); + } + + default.get()->dmFields |= DM_COLOR; + default.get()->dmColor = color ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME; + + DriverInfo6 info_6; + if (!info_6.Init(printer)) + return default.Pass(); + + const DRIVER_INFO_6* p = info_6.get(); + + // Only HP known to have issues. + if (wcscmp(p->pszMfgName, L"HP") != 0) + return default.Pass(); + + // Need XPS for this workaround. + printing::ScopedXPSInitializer xps_initializer; + if (!xps_initializer.initialized()) + return default.Pass(); + + const char* xps_color = color ? kXpsTicketColor : kXpsTicketMonochrome; + std::string xps_ticket = base::StringPrintf(kXpsTicketTemplate, xps_color); + scoped_ptr<DEVMODE[]> ticket = printing::XpsTicketToDevMode(printer_name, + xps_ticket); + if (!ticket) + return default.Pass(); + + return ticket.Pass(); +} + +PRINTING_EXPORT scoped_ptr<DEVMODE[]> CreateDevMode(HANDLE printer, + DEVMODE* in) { + DWORD flags = in ? (DM_IN_BUFFER) : 0; + LONG buffer_size = DocumentProperties(NULL, printer, L"", NULL, in, flags); + if (buffer_size <= 0) + return scoped_ptr<DEVMODE[]>(); + scoped_ptr<DEVMODE[]> out( + reinterpret_cast<DEVMODE*>(new uint8[buffer_size])); + flags |= DM_OUT_BUFFER; + if (DocumentProperties(NULL, printer, L"", out.get(), in, flags) != IDOK) + return scoped_ptr<DEVMODE[]>(); + DCHECK_EQ(buffer_size, out.get()->dmSize + out.get()->dmDriverExtra); + return out.Pass(); +} + } // namespace printing |