diff options
author | alekseys@chromium.org <alekseys@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-13 22:00:57 +0000 |
---|---|---|
committer | alekseys@chromium.org <alekseys@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-13 22:00:57 +0000 |
commit | 117eb82d7a3b62cb363fb8e64dc9aa3a7ef7e028 (patch) | |
tree | 996988f3b9d32f0c8db3453dfcb9a62c1d8d6fc6 | |
parent | 3a8b058d8c2eb1a6345196fdf8158593a3bcfeef (diff) | |
download | chromium_src-117eb82d7a3b62cb363fb8e64dc9aa3a7ef7e028.zip chromium_src-117eb82d7a3b62cb363fb8e64dc9aa3a7ef7e028.tar.gz chromium_src-117eb82d7a3b62cb363fb8e64dc9aa3a7ef7e028.tar.bz2 |
Add paper size reporting for CUPS printers (to let user to select one in the Print Preview).
BUG=239879
Review URL: https://codereview.chromium.org/334763002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@277098 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/ui/libgtk2ui/print_dialog_gtk2.cc | 83 | ||||
-rw-r--r-- | chrome/common/chrome_utility_messages.h | 3 | ||||
-rw-r--r-- | chrome/common/cloud_print/cloud_print_cdd_conversion.cc | 8 | ||||
-rw-r--r-- | printing/backend/cups_helper.cc | 39 | ||||
-rw-r--r-- | printing/backend/cups_helper_unittest.cc | 33 | ||||
-rw-r--r-- | printing/backend/print_backend.h | 3 | ||||
-rw-r--r-- | printing/backend/print_backend_win.cc | 4 |
7 files changed, 164 insertions, 9 deletions
diff --git a/chrome/browser/ui/libgtk2ui/print_dialog_gtk2.cc b/chrome/browser/ui/libgtk2ui/print_dialog_gtk2.cc index 971eecc..b8b0141 100644 --- a/chrome/browser/ui/libgtk2ui/print_dialog_gtk2.cc +++ b/chrome/browser/ui/libgtk2ui/print_dialog_gtk2.cc @@ -6,6 +6,8 @@ #include <gtk/gtkunixprint.h> +#include <algorithm> +#include <cmath> #include <string> #include <vector> @@ -36,6 +38,53 @@ const char kDuplexNone[] = "None"; const char kDuplexTumble[] = "DuplexTumble"; const char kDuplexNoTumble[] = "DuplexNoTumble"; +int kPaperSizeTresholdMicrons = 100; +int kMicronsInMm = 1000; + +// Checks whether gtk_paper_size can be used to represent user selected media. +// In fuzzy match mode checks that paper sizes are "close enough" (less than +// 1mm difference). In the exact mode, looks for the paper with the same PPD +// name and "close enough" size. +bool PaperSizeMatch(GtkPaperSize* gtk_paper_size, + const PrintSettings::RequestedMedia& media, + bool fuzzy_match) { + if (!gtk_paper_size) { + return false; + } + gfx::Size paper_size_microns( + static_cast<int>(gtk_paper_size_get_width(gtk_paper_size, GTK_UNIT_MM) * + kMicronsInMm + 0.5), + static_cast<int>(gtk_paper_size_get_height(gtk_paper_size, GTK_UNIT_MM) * + kMicronsInMm + 0.5)); + int diff = std::max( + std::abs(paper_size_microns.width() - media.size_microns.width()), + std::abs(paper_size_microns.height() - media.size_microns.height())); + if (fuzzy_match) { + return diff <= kPaperSizeTresholdMicrons; + } + return !media.vendor_id.empty() && + media.vendor_id == gtk_paper_size_get_ppd_name(gtk_paper_size) && + diff <= kPaperSizeTresholdMicrons; +} + +// Looks up a paper size matching (in terms of PaperSizeMatch) the user selected +// media in the paper size list reported by GTK. Returns NULL if there's no +// match found. +GtkPaperSize* FindPaperSizeMatch(GList* gtk_paper_sizes, + const PrintSettings::RequestedMedia& media) { + GtkPaperSize* first_fuzzy_match = NULL; + for (GList* p = gtk_paper_sizes; p && p->data; p = g_list_next(p)) { + GtkPaperSize* gtk_paper_size = static_cast<GtkPaperSize*>(p->data); + if (PaperSizeMatch(gtk_paper_size, media, false)) { + return gtk_paper_size; + } + if (!first_fuzzy_match && PaperSizeMatch(gtk_paper_size, media, true)) { + first_fuzzy_match = gtk_paper_size; + } + } + return first_fuzzy_match; +} + class StickyPrintSettingGtk { public: StickyPrintSettingGtk() : last_used_settings_(gtk_print_settings_new()) { @@ -224,6 +273,40 @@ bool PrintDialogGtk2::UpdateSettings(printing::PrintSettings* settings) { if (!page_setup_) page_setup_ = gtk_page_setup_new(); + if (page_setup_ && !settings->requested_media().IsDefault()) { + const PrintSettings::RequestedMedia& requested_media = + settings->requested_media(); + GtkPaperSize* gtk_current_paper_size = + gtk_page_setup_get_paper_size(page_setup_); + if (!PaperSizeMatch(gtk_current_paper_size, requested_media, + true /*fuzzy_match*/)) { + GList* gtk_paper_sizes = + gtk_paper_size_get_paper_sizes(false /*include_custom*/); + if (gtk_paper_sizes) { + GtkPaperSize* matching_gtk_paper_size = + FindPaperSizeMatch(gtk_paper_sizes, requested_media); + if (matching_gtk_paper_size) { + VLOG(1) << "Using listed paper size"; + gtk_page_setup_set_paper_size(page_setup_, matching_gtk_paper_size); + } else { + VLOG(1) << "Using custom paper size"; + GtkPaperSize* custom_size = gtk_paper_size_new_custom( + requested_media.vendor_id.c_str(), + requested_media.vendor_id.c_str(), + requested_media.size_microns.width() / kMicronsInMm, + requested_media.size_microns.height() / kMicronsInMm, + GTK_UNIT_MM); + gtk_page_setup_set_paper_size(page_setup_, custom_size); + gtk_paper_size_free(custom_size); + } + g_list_free_full(gtk_paper_sizes, + reinterpret_cast<GDestroyNotify>(gtk_paper_size_free)); + } + } else { + VLOG(1) << "Using default paper size"; + } + } + gtk_print_settings_set_orientation( gtk_settings_, settings->landscape() ? GTK_PAGE_ORIENTATION_LANDSCAPE : diff --git a/chrome/common/chrome_utility_messages.h b/chrome/common/chrome_utility_messages.h index b706ee54..b916536 100644 --- a/chrome/common/chrome_utility_messages.h +++ b/chrome/common/chrome_utility_messages.h @@ -52,7 +52,8 @@ IPC_ENUM_TRAITS_MAX_VALUE(printing::ColorModel, printing::PROCESSCOLORMODEL_RGB) IPC_ENUM_TRAITS_MAX_VALUE(printing::DuplexMode, printing::SHORT_EDGE) IPC_STRUCT_TRAITS_BEGIN(printing::PrinterSemanticCapsAndDefaults::Paper) - IPC_STRUCT_TRAITS_MEMBER(name) + IPC_STRUCT_TRAITS_MEMBER(display_name) + IPC_STRUCT_TRAITS_MEMBER(vendor_id) IPC_STRUCT_TRAITS_MEMBER(size_um) IPC_STRUCT_TRAITS_END() diff --git a/chrome/common/cloud_print/cloud_print_cdd_conversion.cc b/chrome/common/cloud_print/cloud_print_cdd_conversion.cc index b485cff..70c774d 100644 --- a/chrome/common/cloud_print/cloud_print_cdd_conversion.cc +++ b/chrome/common/cloud_print/cloud_print_cdd_conversion.cc @@ -55,8 +55,8 @@ scoped_ptr<base::DictionaryValue> PrinterSemanticCapsAndDefaultsToCdd( color.SaveTo(&description); if (!semantic_info.papers.empty()) { - Media default_media(semantic_info.default_paper.name, - "", + Media default_media(semantic_info.default_paper.display_name, + semantic_info.default_paper.vendor_id, semantic_info.default_paper.size_um.width(), semantic_info.default_paper.size_um.height()); default_media.MatchBySize(); @@ -67,8 +67,8 @@ scoped_ptr<base::DictionaryValue> PrinterSemanticCapsAndDefaultsToCdd( gfx::Size paper_size = semantic_info.papers[i].size_um; if (paper_size.width() > paper_size.height()) paper_size.SetSize(paper_size.height(), paper_size.width()); - Media new_media(semantic_info.papers[i].name, - "", + Media new_media(semantic_info.papers[i].display_name, + semantic_info.papers[i].vendor_id, paper_size.width(), paper_size.height()); new_media.MatchBySize(); diff --git a/printing/backend/cups_helper.cc b/printing/backend/cups_helper.cc index 981a539..b36722d 100644 --- a/printing/backend/cups_helper.cc +++ b/printing/backend/cups_helper.cc @@ -16,6 +16,7 @@ #include "base/values.h" #include "printing/backend/print_backend.h" #include "printing/backend/print_backend_consts.h" +#include "printing/units.h" #include "url/gurl.h" namespace printing { @@ -33,6 +34,9 @@ const char kHighGray[] = "High.Gray"; const char kDuplex[] = "Duplex"; const char kDuplexNone[] = "None"; +const char kPageSize[] = "PageSize"; + +const double kMicronsPerPoint = kHundrethsMMPerInch / kPointsPerInch * 10; #if !defined(OS_MACOSX) void ParseLpOptions(const base::FilePath& filepath, @@ -358,8 +362,13 @@ bool ParsePpdCapabilities( } ppd_file_t* ppd = ppdOpenFile(ppd_file_path.value().c_str()); - if (!ppd) + if (!ppd) { + int line = 0; + ppd_status_t ppd_status = ppdLastError(&line); + LOG(ERROR) << "Failed to open PDD file: error " << ppd_status << " at line " + << line << ", " << ppdErrorString(ppd_status); return false; + } printing::PrinterSemanticCapsAndDefaults caps; #if !defined(OS_MACOSX) @@ -397,6 +406,34 @@ bool ParsePpdCapabilities( caps.color_model = cm_color; caps.bw_model = cm_black; + if (ppd->num_sizes > 0 && ppd->sizes) { + VLOG(1) << "Paper list size - " << ppd->num_sizes; + ppd_option_t* paper_option = ppdFindOption(ppd, kPageSize); + for (int i = 0; i < ppd->num_sizes; ++i) { + gfx::Size paper_size_microns( + static_cast<int>(ppd->sizes[i].width * kMicronsPerPoint + 0.5), + static_cast<int>(ppd->sizes[i].length * kMicronsPerPoint + 0.5)); + if (paper_size_microns.width() > 0 && paper_size_microns.height() > 0) { + PrinterSemanticCapsAndDefaults::Paper paper; + paper.size_um = paper_size_microns; + paper.vendor_id = ppd->sizes[i].name; + if (paper_option) { + ppd_choice_t* paper_choice = + ppdFindChoice(paper_option, ppd->sizes[i].name); + // Human readable paper name should be UTF-8 encoded, but some PPDs + // do not follow this standard. + if (paper_choice && base::IsStringUTF8(paper_choice->text)) { + paper.display_name = paper_choice->text; + } + } + caps.papers.push_back(paper); + if (i == 0 || ppd->sizes[i].marked) { + caps.default_paper = paper; + } + } + } + } + ppdClose(ppd); base::DeleteFile(ppd_file_path, false); diff --git a/printing/backend/cups_helper_unittest.cc b/printing/backend/cups_helper_unittest.cc index 83dc0a1..2a0e72b 100644 --- a/printing/backend/cups_helper_unittest.cc +++ b/printing/backend/cups_helper_unittest.cc @@ -172,3 +172,36 @@ TEST(PrintBackendCupsHelperTest, TestPpdParsingColorFalseDuplexLongEdge) { EXPECT_TRUE(caps.color_changeable); EXPECT_FALSE(caps.color_default); } + +TEST(PrintBackendCupsHelperTest, TestPpdParsingPageSize) { + std::string test_ppd_data; + test_ppd_data.append( + "*PPD-Adobe: \"4.3\"\n\n" + "*OpenUI *PageSize: PickOne\n" + "*OrderDependency: 30 AnySetup *PageSize\n" + "*DefaultPageSize: Letter\n" + "*PageSize Letter/US Letter: \"" + " <</DeferredMediaSelection true /PageSize [612 792] " + " /ImagingBBox null /MediaClass null >> setpagedevice\"\n" + "*End\n" + "*PageSize Legal/US Legal: \"" + " <</DeferredMediaSelection true /PageSize [612 1008] " + " /ImagingBBox null /MediaClass null >> setpagedevice\"\n" + "*End\n" + "*DefaultPaperDimension: Letter\n" + "*PaperDimension Letter/US Letter: \"612 792\"\n" + "*PaperDimension Legal/US Legal: \"612 1008\"\n\n" + "*CloseUI: *PageSize\n\n"); + + printing::PrinterSemanticCapsAndDefaults caps; + EXPECT_TRUE(printing::ParsePpdCapabilities("test", test_ppd_data, &caps)); + ASSERT_EQ(2UL, caps.papers.size()); + EXPECT_EQ("Letter", caps.papers[0].vendor_id); + EXPECT_EQ("US Letter", caps.papers[0].display_name); + EXPECT_EQ(214200, caps.papers[0].size_um.width()); + EXPECT_EQ(277200, caps.papers[0].size_um.height()); + EXPECT_EQ("Legal", caps.papers[1].vendor_id); + EXPECT_EQ("US Legal", caps.papers[1].display_name); + EXPECT_EQ(214200, caps.papers[1].size_um.width()); + EXPECT_EQ(352800, caps.papers[1].size_um.height()); +} diff --git a/printing/backend/print_backend.h b/printing/backend/print_backend.h index 3b307f1..e03ef42 100644 --- a/printing/backend/print_backend.h +++ b/printing/backend/print_backend.h @@ -52,7 +52,8 @@ struct PRINTING_EXPORT PrinterSemanticCapsAndDefaults { ColorModel bw_model; struct Paper { - std::string name; + std::string display_name; + std::string vendor_id; gfx::Size size_um; }; std::vector<Paper> papers; diff --git a/printing/backend/print_backend_win.cc b/printing/backend/print_backend_win.cc index 87c69ee..287a1f0 100644 --- a/printing/backend/print_backend_win.cc +++ b/printing/backend/print_backend_win.cc @@ -93,7 +93,7 @@ void LoadPaper(const wchar_t* printer, base::string16 tmp_name(name_start, kMaxPaperName); // Trim trailing zeros. tmp_name = tmp_name.c_str(); - paper.name = base::WideToUTF8(tmp_name); + paper.display_name = base::WideToUTF8(tmp_name); } caps->papers.push_back(paper); } @@ -119,7 +119,7 @@ void LoadPaper(const wchar_t* printer, base::string16 tmp_name(name_start, kMaxPaperName); // Trim trailing zeros. tmp_name = tmp_name.c_str(); - paper.name = base::WideToUTF8(tmp_name); + paper.display_name = base::WideToUTF8(tmp_name); } caps->default_paper = paper; break; |