File: print_backend_utils.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (181 lines) | stat: -rw-r--r-- 5,978 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "printing/backend/print_backend_utils.h"

#include <string_view>
#include <vector>

#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "printing/buildflags/buildflags.h"
#include "printing/units.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/size_f.h"

#if BUILDFLAG(USE_CUPS)
#include "printing/backend/cups_printer.h"
#endif  // BUILDFLAG(USE_CUPS)

namespace printing {

namespace {

constexpr float kMmPerInch = 25.4f;
constexpr float kMicronsPerInch = kMmPerInch * kMicronsPerMm;

// Defines two prefixes of a special breed of media sizes not meant for
// users' eyes. CUPS incidentally returns these IPP values to us, but
// we have no use for them.
constexpr std::string_view kMediaCustomMinPrefix = "custom_min";
constexpr std::string_view kMediaCustomMaxPrefix = "custom_max";

bool IsValidMediaName(std::string_view& value,
                      std::vector<std::string_view>& pieces) {
  // We expect at least a display string and a dimension string.
  // Additionally, we drop the "custom_min*" and "custom_max*" special
  // "sizes" (not for users' eyes).
  return pieces.size() >= 2 &&
         !base::StartsWith(value, kMediaCustomMinPrefix) &&
         !base::StartsWith(value, kMediaCustomMaxPrefix);
}

std::vector<std::string_view> GetStringPiecesIfValid(std::string_view value) {
  // <name>_<width>x<height>{in,mm}
  // e.g. na_letter_8.5x11in, iso_a4_210x297mm
  std::vector<std::string_view> pieces = base::SplitStringPiece(
      value, "_", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  if (!IsValidMediaName(value, pieces)) {
    return std::vector<std::string_view>();
  }
  return pieces;
}

gfx::Size DimensionsToMicrons(std::string_view value) {
  Unit unit;
  std::string_view dims;
  size_t unit_position;
  if ((unit_position = value.find("mm")) != std::string_view::npos) {
    unit = Unit::kMillimeters;
    dims = value.substr(0, unit_position);
  } else if ((unit_position = value.find("in")) != std::string_view::npos) {
    unit = Unit::kInches;
    dims = value.substr(0, unit_position);
  } else {
    LOG(WARNING) << "Could not parse paper dimensions";
    return {0, 0};
  }

  double width;
  double height;
  std::vector<std::string> pieces = base::SplitString(
      dims, "x", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  if (pieces.size() != 2 || !base::StringToDouble(pieces[0], &width) ||
      !base::StringToDouble(pieces[1], &height)) {
    return {0, 0};
  }

  float scale;
  switch (unit) {
    case Unit::kMillimeters:
      scale = kMicronsPerMm;
      break;
    case Unit::kInches:
      scale = kMicronsPerInch;
      break;
  }

  return gfx::ToFlooredSize(gfx::ScaleSize(gfx::SizeF(width, height), scale));
}

}  // namespace

gfx::Size ParsePaperSize(std::string_view value) {
  std::vector<std::string_view> pieces = GetStringPiecesIfValid(value);
  if (pieces.empty()) {
    return gfx::Size();
  }

  std::string_view dimensions = pieces.back();
  return DimensionsToMicrons(dimensions);
}

#if BUILDFLAG(USE_CUPS)
gfx::Rect PrintableAreaFromSizeAndPwgMargins(const gfx::Size& size_um,
                                             int bottom_pwg,
                                             int left_pwg,
                                             int right_pwg,
                                             int top_pwg) {
  // The margins of the printable area are expressed in PWG units (100ths of
  // mm) in the IPP 'media-col-database' attribute.
  int printable_area_left_um = left_pwg * kMicronsPerPwgUnit;
  int printable_area_bottom_um = bottom_pwg * kMicronsPerPwgUnit;
  int printable_area_width_um =
      size_um.width() - ((left_pwg + right_pwg) * kMicronsPerPwgUnit);
  int printable_area_height_um =
      size_um.height() - ((top_pwg + bottom_pwg) * kMicronsPerPwgUnit);
  return gfx::Rect(printable_area_left_um, printable_area_bottom_um,
                   printable_area_width_um, printable_area_height_um);
}

void MarginsMicronsFromSizeAndPrintableArea(const gfx::Size& size_um,
                                            const gfx::Rect& printable_area_um,
                                            int* bottom_um,
                                            int* left_um,
                                            int* right_um,
                                            int* top_um) {
  CHECK(bottom_um);
  CHECK(left_um);
  CHECK(right_um);
  CHECK(top_um);

  *bottom_um = printable_area_um.y();
  *left_um = printable_area_um.x();
  *right_um = size_um.width() - printable_area_um.right();
  *top_um = size_um.height() - printable_area_um.bottom();
}

int MarginMicronsToPWG(int margin_um) {
  // This value in microns was obtained from the printer and must be
  // convertible to PWG units.
  CHECK_EQ(margin_um % kMicronsPerPwgUnit, 0);

  return margin_um / kMicronsPerPwgUnit;
}
#endif  // BUILDFLAG(USE_CUPS)

COMPONENT_EXPORT(PRINT_BACKEND)
std::string GetDisplayName(const std::string& printer_name,
                           std::string_view info) {
#if BUILDFLAG(IS_MAC)
  // It is possible to create a printer with a blank display name, so just
  // use the printer name in such a case.
  if (!info.empty()) {
    return std::string(info);
  }
#endif
  return printer_name;
}

COMPONENT_EXPORT(PRINT_BACKEND)
std::string_view GetPrinterDescription(std::string_view drv_info,
                                       std::string_view info) {
#if BUILDFLAG(IS_MAC)
  // On Mac, `drv_info` specifies the printer description
  if (!drv_info.empty()) {
    return drv_info;
  }
#else
  if (!info.empty()) {
    return info;
  }
#endif
  return std::string_view();
}

}  // namespace printing