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

Unified Diff: printing/backend/cups_ipp_util.cc

Issue 2105463002: Create a new print backend for the updated CUPS APIs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix comment. Created 4 years, 5 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 side-by-side diff with in-line comments
Download patch
Index: printing/backend/cups_ipp_util.cc
diff --git a/printing/backend/cups_ipp_util.cc b/printing/backend/cups_ipp_util.cc
new file mode 100644
index 0000000000000000000000000000000000000000..91169ce4cab3d8c37c0d5d0b9a00b0b66e515286
--- /dev/null
+++ b/printing/backend/cups_ipp_util.cc
@@ -0,0 +1,289 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "printing/backend/cups_ipp_util.h"
+
+#include <cups/cups.h>
+
+#include <algorithm>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "printing/backend/cups_printer.h"
+#include "printing/backend/print_backend_consts.h"
+#include "printing/units.h"
+
+namespace printing {
+
+namespace {
+
+const char kIppCollate[] = "sheet-collate"; // RFC 3381
+const char kIppCopies[] = CUPS_COPIES;
+const char kIppColor[] = CUPS_PRINT_COLOR_MODE;
+const char kIppMedia[] = CUPS_MEDIA;
+const char kIppDuplex[] = CUPS_SIDES;
+
+const char kCollated[] = "collated";
+
+const int kMicronsPerMM = 1000;
+const double kMMPerInch = 25.4;
+const double kMicronsPerInch = kMMPerInch * kMicronsPerMM;
+
+enum Unit {
+ INCHES,
+ MILLIMETERS,
+};
+
+const std::map<const base::StringPiece, ColorModel> kColorMap{
Lei Zhang 2016/07/19 22:26:39 Can't do this. It adds a static initializer. Given
skau 2016/07/20 23:58:22 Thanks. That works well.
+ {CUPS_PRINT_COLOR_MODE_COLOR, COLORMODE_COLOR},
+ {CUPS_PRINT_COLOR_MODE_MONOCHROME, COLORMODE_MONOCHROME},
+};
+
+ColorModel ColorModelFromIppColor(base::StringPiece ippColor) {
+ auto found = kColorMap.find(ippColor);
+ return found == kColorMap.end() ? UNKNOWN_COLOR_MODEL : found->second;
+}
+
+bool PrinterSupportsValue(const CupsPrinter& printer,
+ base::StringPiece name,
+ base::StringPiece value) {
+ std::vector<base::StringPiece> values =
+ printer.GetSupportedOptionValueStrings(name);
+ auto iter = std::find(values.begin(), values.end(), value);
+ return iter != values.end();
+}
+
+DuplexMode PrinterDefaultDuplex(const CupsPrinter& printer) {
+ ipp_attribute_t* attr = printer.GetDefaultOptionValue(kIppDuplex);
+ if (!attr)
+ return UNKNOWN_DUPLEX_MODE;
+
+ const char* value = ippGetString(attr, 0, nullptr);
+ if (base::EqualsCaseInsensitiveASCII(value, CUPS_SIDES_ONE_SIDED))
+ return SIMPLEX;
+ if (base::EqualsCaseInsensitiveASCII(value, CUPS_SIDES_TWO_SIDED_PORTRAIT))
+ return LONG_EDGE;
+ if (base::EqualsCaseInsensitiveASCII(value, CUPS_SIDES_TWO_SIDED_LANDSCAPE))
+ return SHORT_EDGE;
+
+ return UNKNOWN_DUPLEX_MODE;
+}
+
+gfx::Size DimensionsToMicrons(base::StringPiece value) {
+ Unit unit;
+ base::StringPiece dims;
+ size_t unit_position;
+ if ((unit_position = value.find("mm")) != base::StringPiece::npos) {
+ unit = MILLIMETERS;
+ dims = value.substr(0, unit_position);
+ } else if ((unit_position = value.find("in")) != base::StringPiece::npos) {
+ unit = INCHES;
+ dims = value.substr(0, unit_position);
+ } else {
+ LOG(WARNING) << "Could not parse paper dimensions";
+ return {0, 0};
+ }
+
+ std::vector<std::string> pieces = base::SplitString(
+ dims, "x", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ double width;
+ double height;
+
+ if (pieces.size() != 2 || !base::StringToDouble(pieces[0], &width) ||
+ !base::StringToDouble(pieces[1], &height)) {
+ return {0, 0};
+ }
+
+ int width_microns;
+ int height_microns;
+
+ switch (unit) {
+ case MILLIMETERS:
+ width_microns = width * kMicronsPerMM;
+ height_microns = height * kMicronsPerMM;
+ break;
+ case INCHES:
+ width_microns = width * kMicronsPerInch;
+ height_microns = height * kMicronsPerInch;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ return gfx::Size{width_microns, height_microns};
+}
+
+PrinterSemanticCapsAndDefaults::Paper ParsePaper(base::StringPiece value) {
+ // <name>_<width>x<height>{in,mm}
+ // e.g. na_letter_8.5x11in, iso_a4_210x297mm
+
+ std::vector<base::StringPiece> pieces = base::SplitStringPiece(
+ value, "_", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ if (pieces.size() < 2) {
+ // we expect at least a display string and a dimension string
+ return PrinterSemanticCapsAndDefaults::Paper();
+ }
+
+ base::StringPiece dimensions = pieces.back();
+
+ std::string display = pieces[0].as_string();
+ for (size_t i = 1; i <= pieces.size() - 2; ++i) {
+ display.append(" ");
+ pieces[i].AppendToString(&display);
+ }
+
+ PrinterSemanticCapsAndDefaults::Paper paper;
+ paper.display_name = display;
+ paper.vendor_id = value.as_string();
+ paper.size_um = DimensionsToMicrons(dimensions);
+
+ return paper;
+}
+
+void ExtractColor(const CupsPrinter& printer,
+ PrinterSemanticCapsAndDefaults* printer_info) {
+ printer_info->bw_model = UNKNOWN_COLOR_MODEL;
+ printer_info->color_model = UNKNOWN_COLOR_MODEL;
+
+ // color and b&w
+ std::vector<ColorModel> color_models = SupportedColorModels(printer);
+ for (ColorModel color : color_models) {
+ switch (color) {
+ case COLORMODE_COLOR:
+ printer_info->color_model = COLORMODE_COLOR;
+ break;
+ case COLORMODE_MONOCHROME:
+ printer_info->bw_model = COLORMODE_MONOCHROME;
+ break;
+ default:
+ // value not needed
+ break;
+ }
+ }
+
+ // changeable
+ printer_info->color_changeable =
+ (printer_info->color_model != UNKNOWN_COLOR_MODEL &&
+ printer_info->bw_model != UNKNOWN_COLOR_MODEL);
+
+ // default color
+ printer_info->color_default = DefaultColorModel(printer);
+}
+
+void ExtractCopies(const CupsPrinter& printer,
+ PrinterSemanticCapsAndDefaults* printer_info) {
+ // copies
+ int upper_bound;
+ int lower_bound;
+ CopiesRange(printer, &lower_bound, &upper_bound);
+ printer_info->copies_capable = (lower_bound != -1) && (upper_bound >= 2);
+}
+
+} // anonymous namespace
Lei Zhang 2016/07/19 22:26:39 no "anonymous "
skau 2016/07/20 23:58:22 Done.
+
+ColorModel DefaultColorModel(const CupsPrinter& printer) {
+ // default color
+ ipp_attribute_t* attr = printer.GetDefaultOptionValue(kIppColor);
+ if (!attr)
+ return UNKNOWN_COLOR_MODEL;
+
+ const char* value = ippGetString(attr, 0, nullptr);
Lei Zhang 2016/07/19 22:26:39 Just combine with the next line and drop |value|.
skau 2016/07/20 23:58:23 Done.
+ return ColorModelFromIppColor(value);
+}
+
+std::vector<ColorModel> SupportedColorModels(const CupsPrinter& printer) {
+ std::vector<ColorModel> colors;
+
+ std::vector<base::StringPiece> color_modes =
+ printer.GetSupportedOptionValueStrings(kIppColor);
+
+ for (base::StringPiece color : color_modes) {
+ ColorModel color_model = ColorModelFromIppColor(color);
+ if (color_model != UNKNOWN_COLOR_MODEL) {
+ colors.push_back(color_model);
+ }
+ }
+
+ return colors;
+}
+
+PrinterSemanticCapsAndDefaults::Paper DefaultPaper(const CupsPrinter& printer) {
+ ipp_attribute_t* attr = printer.GetDefaultOptionValue(kIppMedia);
+ if (!attr)
+ return PrinterSemanticCapsAndDefaults::Paper();
+
+ const char* value = ippGetString(attr, 0, nullptr);
+ return ParsePaper(value);
+}
+
+std::vector<PrinterSemanticCapsAndDefaults::Paper> SupportedPapers(
+ const CupsPrinter& printer) {
+ std::vector<base::StringPiece> papers =
+ printer.GetSupportedOptionValueStrings(kIppMedia);
+ std::vector<PrinterSemanticCapsAndDefaults::Paper> parsed_papers;
+ for (base::StringPiece paper : papers) {
+ PrinterSemanticCapsAndDefaults::Paper p = ParsePaper(paper);
Lei Zhang 2016/07/19 22:26:39 Also less wordy if it's just combined with the nex
skau 2016/07/20 23:58:23 Done.
+ parsed_papers.push_back(p);
+ }
+
+ return parsed_papers;
+}
+
+void CopiesRange(const CupsPrinter& printer,
+ int* lower_bound,
+ int* upper_bound) {
+ ipp_attribute_t* attr = printer.GetSupportedOptionValues(kIppCopies);
+ if (attr) {
Lei Zhang 2016/07/19 22:26:39 If |attr| is nullptr, what happens? Does |lower_bo
skau 2016/07/20 23:58:22 Whoops. I'll write some unit tests.
+ *lower_bound = -1;
+ *upper_bound = -1;
+ }
+
+ *lower_bound = ippGetRange(attr, 0, upper_bound);
+}
+
+bool CollateCapable(const CupsPrinter& printer) {
+ std::vector<base::StringPiece> values =
+ printer.GetSupportedOptionValueStrings(kIppCollate);
+ auto iter = std::find(values.begin(), values.end(), kCollated);
Lei Zhang 2016/07/19 22:26:39 Just: return ContainsValue(values, kCollated); Sa
skau 2016/07/20 23:58:22 Thanks. I didn't know we had that.
+ return iter != values.end();
+}
+
+bool CollateDefault(const CupsPrinter& printer) {
+ ipp_attribute_t* attr = printer.GetDefaultOptionValue(kIppCollate);
+ if (!attr)
+ return false;
+
+ base::StringPiece name = ippGetString(attr, 0, nullptr);
+ return name.compare(kCollated) == 0;
+}
+
+void CapsAndDefaultsFromPrinter(const CupsPrinter& printer,
+ PrinterSemanticCapsAndDefaults* printer_info) {
+ // duplex
+ printer_info->duplex_default = PrinterDefaultDuplex(printer);
+ printer_info->duplex_capable =
+ PrinterSupportsValue(printer, kIppDuplex, CUPS_SIDES_TWO_SIDED_PORTRAIT);
+
+ // collate
+ printer_info->collate_default = CollateDefault(printer);
+ printer_info->collate_capable = CollateCapable(printer);
+
+ // paper
+ printer_info->default_paper = DefaultPaper(printer);
+ printer_info->papers = SupportedPapers(printer);
+
+ ExtractCopies(printer, printer_info);
+ ExtractColor(printer, printer_info);
+
+ // TODO(skau): Add dpi and default_dpi
+}
+
+} // namespace printing

Powered by Google App Engine
This is Rietveld 408576698