Commit 7261c044 authored by Stephen Chenney's avatar Stephen Chenney Committed by Commit Bot

[Text Decorations] Cache computed paths

The paths for wavy, dashed and dotted paths are quite expensive
to compute and are used in both bounds and painting. Cache them,
recomputing when needed and resetting when any line data changes.

No change in net behavior.

Bug: 896295
Change-Id: If0e58f49e6ecc9246b95d4b883eec1ac7d006ce6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2342641
Commit-Queue: Stephen Chenney <schenney@chromium.org>
Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#796244}
parent d7698b67
...@@ -35,7 +35,7 @@ void AppliedDecorationPainter::Paint() { ...@@ -35,7 +35,7 @@ void AppliedDecorationPainter::Paint() {
void AppliedDecorationPainter::StrokeWavyTextDecoration() { void AppliedDecorationPainter::StrokeWavyTextDecoration() {
context_.SetShouldAntialias(true); context_.SetShouldAntialias(true);
context_.StrokePath(decoration_info_.PrepareWavyStrokePath(line_)); context_.StrokePath(decoration_info_.PrepareWavyStrokePath(line_).value());
} }
} // namespace blink } // namespace blink
...@@ -194,6 +194,7 @@ void TextDecorationInfo::SetPerLineData(TextDecoration line, ...@@ -194,6 +194,7 @@ void TextDecorationInfo::SetPerLineData(TextDecoration line,
line_data_[index].line_offset = line_offset; line_data_[index].line_offset = line_offset;
line_data_[index].double_offset = double_offset; line_data_[index].double_offset = double_offset;
line_data_[index].wavy_offset_factor = wavy_offset_factor; line_data_[index].wavy_offset_factor = wavy_offset_factor;
line_data_[index].stroke_path.reset();
} }
ETextDecorationStyle TextDecorationInfo::DecorationStyle() const { ETextDecorationStyle TextDecorationInfo::DecorationStyle() const {
...@@ -272,30 +273,35 @@ FloatRect TextDecorationInfo::BoundsForLine(TextDecoration line) const { ...@@ -272,30 +273,35 @@ FloatRect TextDecorationInfo::BoundsForLine(TextDecoration line) const {
FloatRect TextDecorationInfo::BoundsForDottedOrDashed( FloatRect TextDecorationInfo::BoundsForDottedOrDashed(
TextDecoration line) const { TextDecoration line) const {
// These coordinate transforms need to match what's happening in int line_data_index = TextDecorationToLineDataIndex(line);
// GraphicsContext's drawLineForText and drawLine. if (!line_data_[line_data_index].stroke_path) {
FloatPoint start_point = StartPoint(line); // These coordinate transforms need to match what's happening in
int y = floorf(start_point.Y() + // GraphicsContext's drawLineForText and drawLine.
std::max<float>(ResolvedThickness() / 2.0f, 0.5f)); FloatPoint start_point = StartPoint(line);
FloatPoint rounded_start_point(start_point.X(), y); int y = floorf(start_point.Y() +
FloatPoint rounded_end_point(rounded_start_point + FloatPoint(width_, 0)); std::max<float>(ResolvedThickness() / 2.0f, 0.5f));
GraphicsContext::AdjustLineToPixelBoundaries( FloatPoint rounded_start_point(start_point.X(), y);
rounded_start_point, rounded_end_point, roundf(ResolvedThickness())); FloatPoint rounded_end_point(rounded_start_point + FloatPoint(width_, 0));
GraphicsContext::AdjustLineToPixelBoundaries(
Path stroke_path; rounded_start_point, rounded_end_point, roundf(ResolvedThickness()));
stroke_path.MoveTo(rounded_start_point);
stroke_path.AddLineTo(rounded_end_point); Path& stroke_path =
line_data_[TextDecorationToLineDataIndex(line)].stroke_path.emplace();
stroke_path.MoveTo(rounded_start_point);
stroke_path.AddLineTo(rounded_end_point);
}
StrokeData stroke_data; StrokeData stroke_data;
stroke_data.SetThickness(ResolvedThickness()); stroke_data.SetThickness(ResolvedThickness());
stroke_data.SetStyle(TextDecorationStyleToStrokeStyle(DecorationStyle())); stroke_data.SetStyle(TextDecorationStyleToStrokeStyle(DecorationStyle()));
return stroke_path.StrokeBoundingRect(stroke_data); return line_data_[line_data_index].stroke_path.value().StrokeBoundingRect(
stroke_data);
} }
FloatRect TextDecorationInfo::BoundsForWavy(TextDecoration line) const { FloatRect TextDecorationInfo::BoundsForWavy(TextDecoration line) const {
StrokeData stroke_data; StrokeData stroke_data;
stroke_data.SetThickness(ResolvedThickness()); stroke_data.SetThickness(ResolvedThickness());
return PrepareWavyStrokePath(line).StrokeBoundingRect(stroke_data); return PrepareWavyStrokePath(line)->StrokeBoundingRect(stroke_data);
} }
/* /*
...@@ -325,7 +331,12 @@ FloatRect TextDecorationInfo::BoundsForWavy(TextDecoration line) const { ...@@ -325,7 +331,12 @@ FloatRect TextDecorationInfo::BoundsForWavy(TextDecoration line) const {
* |-----------| * |-----------|
* step * step
*/ */
Path TextDecorationInfo::PrepareWavyStrokePath(TextDecoration line) const { base::Optional<Path> TextDecorationInfo::PrepareWavyStrokePath(
TextDecoration line) const {
int line_data_index = TextDecorationToLineDataIndex(line);
if (line_data_[line_data_index].stroke_path)
return line_data_[line_data_index].stroke_path;
FloatPoint start_point = StartPoint(line); FloatPoint start_point = StartPoint(line);
float wave_offset = float wave_offset =
DoubleOffset(line) * DoubleOffset(line) *
...@@ -336,7 +347,7 @@ Path TextDecorationInfo::PrepareWavyStrokePath(TextDecoration line) const { ...@@ -336,7 +347,7 @@ Path TextDecorationInfo::PrepareWavyStrokePath(TextDecoration line) const {
GraphicsContext::AdjustLineToPixelBoundaries(p1, p2, ResolvedThickness()); GraphicsContext::AdjustLineToPixelBoundaries(p1, p2, ResolvedThickness());
Path path; Path& path = line_data_[line_data_index].stroke_path.emplace();
path.MoveTo(p1); path.MoveTo(p1);
// Distance between decoration's axis and Bezier curve's control points. // Distance between decoration's axis and Bezier curve's control points.
...@@ -349,9 +360,10 @@ Path TextDecorationInfo::PrepareWavyStrokePath(TextDecoration line) const { ...@@ -349,9 +360,10 @@ Path TextDecorationInfo::PrepareWavyStrokePath(TextDecoration line) const {
// as strockThickness increases to make the curve looks better. // as strockThickness increases to make the curve looks better.
float control_point_distance = 3 * std::max<float>(2, ResolvedThickness()); float control_point_distance = 3 * std::max<float>(2, ResolvedThickness());
// Increment used to form the diamond shape between start point (p1), control // Increment used to form the diamond shape between start point (p1),
// points and end point (p2) along the axis of the decoration. Makes the // control points and end point (p2) along the axis of the decoration. Makes
// curve wider as strockThickness increases to make the curve looks better. // the curve wider as strockThickness increases to make the curve looks
// better.
float step = 2 * std::max<float>(2, ResolvedThickness()); float step = 2 * std::max<float>(2, ResolvedThickness());
bool is_vertical_line = (p1.X() == p2.X()); bool is_vertical_line = (p1.X() == p2.X());
...@@ -409,7 +421,7 @@ Path TextDecorationInfo::PrepareWavyStrokePath(TextDecoration line) const { ...@@ -409,7 +421,7 @@ Path TextDecorationInfo::PrepareWavyStrokePath(TextDecoration line) const {
FloatPoint(x, y_axis)); FloatPoint(x, y_axis));
} }
} }
return path; return line_data_[line_data_index].stroke_path;
} }
} // namespace blink } // namespace blink
...@@ -93,7 +93,7 @@ class CORE_EXPORT TextDecorationInfo { ...@@ -93,7 +93,7 @@ class CORE_EXPORT TextDecorationInfo {
// Return a path for a wavy line at the given position, for the // Return a path for a wavy line at the given position, for the
// current decoration. // current decoration.
Path PrepareWavyStrokePath(TextDecoration line) const; base::Optional<Path> PrepareWavyStrokePath(TextDecoration line) const;
private: private:
float ComputeUnderlineThickness( float ComputeUnderlineThickness(
...@@ -124,6 +124,7 @@ class CORE_EXPORT TextDecorationInfo { ...@@ -124,6 +124,7 @@ class CORE_EXPORT TextDecorationInfo {
float line_offset; float line_offset;
float double_offset; float double_offset;
int wavy_offset_factor; int wavy_offset_factor;
mutable base::Optional<Path> stroke_path;
}; };
PerLineData line_data_[3]; PerLineData line_data_[3];
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment