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
pdf / pdf_ink_brush.cc [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "pdf/pdf_ink_brush.h"
#include <optional>
#include "base/check_op.h"
#include "base/notreached.h"
#include "third_party/ink/src/ink/brush/brush.h"
#include "third_party/ink/src/ink/brush/brush_family.h"
#include "third_party/ink/src/ink/brush/brush_paint.h"
#include "third_party/ink/src/ink/brush/brush_tip.h"
#include "third_party/ink/src/ink/color/color.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect_conversions.h"
namespace chrome_pdf {
namespace {
float GetCornerRounding(PdfInkBrush::Type type) {
switch (type) {
case PdfInkBrush::Type::kHighlighter:
return 0.0f;
case PdfInkBrush::Type::kPen:
return 1.0f;
}
NOTREACHED();
}
float GetOpacity(PdfInkBrush::Type type) {
switch (type) {
case PdfInkBrush::Type::kHighlighter:
// LINT.IfChange(HighlighterOpacity)
return 0.4f;
// LINT.ThenChange(//chrome/browser/resources/pdf/pdf_viewer_utils.ts:HighlighterOpacity)
case PdfInkBrush::Type::kPen:
return 1.0f;
}
NOTREACHED();
}
// ink::Brush actually uses ink::Color, but pdf/ uses SkColor. To avoid having
// multiple color representations, do not expose ink::Color and just convert
// `color`.
ink::Color GetInkColorFromSkColor(SkColor color) {
return ink::Color::FromUint8(
/*red=*/SkColorGetR(color),
/*green=*/SkColorGetG(color),
/*blue=*/SkColorGetB(color),
/*alpha=*/SkColorGetA(color));
}
ink::Brush CreateInkBrush(PdfInkBrush::Type type, SkColor color, float size) {
CHECK(PdfInkBrush::IsToolSizeInRange(size));
// TODO(crbug.com/353942923): Use real values here.
ink::BrushTip tip;
tip.corner_rounding = GetCornerRounding(type);
tip.opacity_multiplier = GetOpacity(type);
// TODO(crbug.com/353942923): Use real `uri_string` here.
auto family = ink::BrushFamily::Create(tip, ink::BrushPaint(),
/*uri_string=*/"");
CHECK(family.ok());
auto brush = ink::Brush::Create(*family,
/*color=*/
GetInkColorFromSkColor(color),
/*size=*/size,
/*epsilon=*/0.1f);
CHECK(brush.ok());
return *brush;
}
// Determine the area to invalidate centered around a point where a brush is
// applied.
gfx::Rect GetPointInvalidateArea(float brush_diameter,
const gfx::PointF& center) {
// Choose a rectangle that surrounds the point for the brush radius.
float brush_radius = brush_diameter / 2;
return gfx::ToEnclosingRect(gfx::RectF(center.x() - brush_radius,
center.y() - brush_radius,
brush_diameter, brush_diameter));
}
} // namespace
// static
std::optional<PdfInkBrush::Type> PdfInkBrush::StringToType(
const std::string& brush_type) {
if (brush_type == "highlighter") {
return Type::kHighlighter;
}
if (brush_type == "pen") {
return Type::kPen;
}
return std::nullopt;
}
// static
std::string PdfInkBrush::TypeToString(Type brush_type) {
switch (brush_type) {
case Type::kHighlighter:
return "highlighter";
case Type::kPen:
return "pen";
}
NOTREACHED();
}
// static
bool PdfInkBrush::IsToolSizeInRange(float size) {
return size >= 1 && size <= 16;
}
PdfInkBrush::PdfInkBrush(Type brush_type, SkColor color, float size)
: ink_brush_(CreateInkBrush(brush_type, color, size)) {}
PdfInkBrush::~PdfInkBrush() = default;
gfx::Rect PdfInkBrush::GetInvalidateArea(const gfx::PointF& center1,
const gfx::PointF& center2) const {
// For a line connecting `center1` to `center2`, the invalidate
// region is the union between the areas affected by them both.
float brush_diameter = ink_brush_.GetSize();
gfx::Rect area1 = GetPointInvalidateArea(brush_diameter, center1);
gfx::Rect area2 = GetPointInvalidateArea(brush_diameter, center2);
area2.Union(area1);
return area2;
}
void PdfInkBrush::SetColor(SkColor color) {
ink_brush_.SetColor(GetInkColorFromSkColor(color));
}
void PdfInkBrush::SetSize(float size) {
auto size_result = ink_brush_.SetSize(std::move(size));
CHECK(size_result.ok());
}
} // namespace chrome_pdf