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
|