Commit 5a1cdd7a authored by Fredrik Söderquist's avatar Fredrik Söderquist Committed by Commit Bot

[CI] Add SVGLengthContext::ResolveLengthPair helper

With geometric presentation attributes it's quite common to need to
resolve an <x, y> pair of Lengths to produce a point or a size.
Add a helper ResolveLengthPair() that accepts a pair of Lengths and
return a FloatPoint. Except for a reduction in LoC, it also amortizes
the cost of determining a viewport when percentages are used.

Use the new helper for 'cx' / 'cy' and 'rx' / 'ry' on <ellipse>,
'cx' / 'cy' on <circle>, 'x' / 'y', 'width' / 'height' and 'rx' / 'ry'
on <rect>, 'x' / 'y' and 'width' / 'height' on <image> as well as
'x' / 'y' on <use>.

Since this means using FloatPoint/FloatSize to a larger degree than
before, use the abilities (operators et.c) of these a bit more where
possible.

Bug: 400725
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: I15f5c17190b060a7e8312d5e3e124846301804b9
Reviewed-on: https://chromium-review.googlesource.com/832606Reviewed-by: default avatarStephen Chenney <schenney@chromium.org>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#524740}
parent fe9306b1
......@@ -73,9 +73,7 @@ void LayoutSVGEllipse::UpdateShapeFromElement() {
if (!use_path_fallback_)
ClearPath();
fill_bounding_box_ =
FloatRect(center_.X() - radii_.Width(), center_.Y() - radii_.Height(),
2 * radii_.Width(), 2 * radii_.Height());
fill_bounding_box_ = FloatRect(center_ - radii_, radii_.ScaledBy(2));
stroke_bounding_box_ = fill_bounding_box_;
if (Style()->SvgStyle().HasStroke())
stroke_bounding_box_.Inflate(StrokeWidth() / 2);
......@@ -84,22 +82,18 @@ void LayoutSVGEllipse::UpdateShapeFromElement() {
void LayoutSVGEllipse::CalculateRadiiAndCenter() {
DCHECK(GetElement());
SVGLengthContext length_context(GetElement());
center_ = FloatPoint(
length_context.ValueForLength(Style()->SvgStyle().Cx(), StyleRef(),
SVGLengthMode::kWidth),
length_context.ValueForLength(Style()->SvgStyle().Cy(), StyleRef(),
SVGLengthMode::kHeight));
const ComputedStyle& style = StyleRef();
const SVGComputedStyle& svg_style = style.SvgStyle();
center_ =
length_context.ResolveLengthPair(svg_style.Cx(), svg_style.Cy(), style);
if (IsSVGCircleElement(*GetElement())) {
float radius = length_context.ValueForLength(
Style()->SvgStyle().R(), StyleRef(), SVGLengthMode::kOther);
float radius = length_context.ValueForLength(svg_style.R(), style,
SVGLengthMode::kOther);
radii_ = FloatSize(radius, radius);
} else {
radii_ = FloatSize(
length_context.ValueForLength(Style()->SvgStyle().Rx(), StyleRef(),
SVGLengthMode::kWidth),
length_context.ValueForLength(Style()->SvgStyle().Ry(), StyleRef(),
SVGLengthMode::kHeight));
radii_ = ToFloatSize(length_context.ResolveLengthPair(
svg_style.Rx(), svg_style.Ry(), style));
}
}
......
......@@ -90,17 +90,14 @@ bool LayoutSVGImage::UpdateBoundingBox() {
FloatRect old_object_bounding_box = object_bounding_box_;
SVGLengthContext length_context(GetElement());
const ComputedStyle& style = StyleRef();
const SVGComputedStyle& svg_style = style.SvgStyle();
object_bounding_box_ = FloatRect(
length_context.ValueForLength(StyleRef().SvgStyle().X(), StyleRef(),
SVGLengthMode::kWidth),
length_context.ValueForLength(StyleRef().SvgStyle().Y(), StyleRef(),
SVGLengthMode::kHeight),
length_context.ValueForLength(StyleRef().Width(), StyleRef(),
SVGLengthMode::kWidth),
length_context.ValueForLength(StyleRef().Height(), StyleRef(),
SVGLengthMode::kHeight));
if (StyleRef().Width().IsAuto() || StyleRef().Height().IsAuto())
length_context.ResolveLengthPair(svg_style.X(), svg_style.Y(), style),
ToFloatSize(length_context.ResolveLengthPair(style.Width(),
style.Height(), style)));
if (style.Width().IsAuto() || style.Height().IsAuto())
object_bounding_box_.SetSize(CalculateObjectSize());
if (old_object_bounding_box != object_bounding_box_) {
......
......@@ -47,16 +47,15 @@ void LayoutSVGRect::UpdateShapeFromElement() {
DCHECK(rect);
SVGLengthContext length_context(rect);
FloatSize bounding_box_size(
length_context.ValueForLength(StyleRef().Width(), StyleRef(),
SVGLengthMode::kWidth),
length_context.ValueForLength(StyleRef().Height(), StyleRef(),
SVGLengthMode::kHeight));
const ComputedStyle& style = StyleRef();
FloatSize bounding_box_size(ToFloatSize(
length_context.ResolveLengthPair(style.Width(), style.Height(), style)));
// Spec: "A negative value is an error."
if (bounding_box_size.Width() < 0 || bounding_box_size.Height() < 0)
return;
const SVGComputedStyle& svg_style = style.SvgStyle();
// Spec: "A value of zero disables rendering of the element."
if (!bounding_box_size.IsEmpty()) {
// Fallback to LayoutSVGShape and path-based hit detection if the rect
......@@ -69,25 +68,19 @@ void LayoutSVGRect::UpdateShapeFromElement() {
use_path_fallback_ = true;
return;
}
if (length_context.ValueForLength(StyleRef().SvgStyle().Rx(), StyleRef(),
SVGLengthMode::kWidth) > 0 ||
length_context.ValueForLength(StyleRef().SvgStyle().Ry(), StyleRef(),
SVGLengthMode::kHeight) > 0 ||
!DefinitelyHasSimpleStroke()) {
FloatPoint radii(length_context.ResolveLengthPair(svg_style.Rx(),
svg_style.Ry(), style));
if (radii.X() > 0 || radii.Y() > 0 || !DefinitelyHasSimpleStroke()) {
CreatePath();
use_path_fallback_ = true;
}
}
fill_bounding_box_ = FloatRect(
FloatPoint(
length_context.ValueForLength(StyleRef().SvgStyle().X(), StyleRef(),
SVGLengthMode::kWidth),
length_context.ValueForLength(StyleRef().SvgStyle().Y(), StyleRef(),
SVGLengthMode::kHeight)),
length_context.ResolveLengthPair(svg_style.X(), svg_style.Y(), style),
bounding_box_size);
stroke_bounding_box_ = fill_bounding_box_;
if (Style()->SvgStyle().HasStroke())
if (svg_style.HasStroke())
stroke_bounding_box_.Inflate(StrokeWidth() / 2);
}
......
......@@ -95,10 +95,8 @@ SVGTransformChange LayoutSVGTransformableContainer::CalculateLocalTransform() {
const ComputedStyle& style = StyleRef();
const SVGComputedStyle& svg_style = style.SvgStyle();
SVGLengthContext length_context(element);
FloatSize translation(length_context.ValueForLength(svg_style.X(), style,
SVGLengthMode::kWidth),
length_context.ValueForLength(
svg_style.Y(), style, SVGLengthMode::kHeight));
FloatSize translation(ToFloatSize(
length_context.ResolveLengthPair(svg_style.X(), svg_style.Y(), style)));
// TODO(fs): Signal this on style update instead.
if (translation != additional_translation_)
SetNeedsTransformUpdate();
......
......@@ -65,16 +65,11 @@ Path SVGCircleElement::AsPath() const {
float r = length_context.ValueForLength(svg_style.R(), style,
SVGLengthMode::kOther);
if (r > 0) {
path.AddEllipse(
FloatRect(length_context.ValueForLength(svg_style.Cx(), style,
SVGLengthMode::kWidth) -
r,
length_context.ValueForLength(svg_style.Cy(), style,
SVGLengthMode::kHeight) -
r,
r * 2, r * 2));
FloatPoint center(length_context.ResolveLengthPair(svg_style.Cx(),
svg_style.Cy(), style));
FloatSize radii(r, r);
path.AddEllipse(FloatRect(center - radii, radii.ScaledBy(2)));
}
return path;
}
......
......@@ -68,25 +68,15 @@ Path SVGEllipseElement::AsPath() const {
const ComputedStyle& style = GetLayoutObject()->StyleRef();
const SVGComputedStyle& svg_style = style.SvgStyle();
float rx = length_context.ValueForLength(svg_style.Rx(), style,
SVGLengthMode::kWidth);
if (rx < 0)
FloatSize radii(ToFloatSize(
length_context.ResolveLengthPair(svg_style.Rx(), svg_style.Ry(), style)));
if (radii.Width() < 0 || radii.Height() < 0 ||
(!radii.Width() && !radii.Height()))
return path;
float ry = length_context.ValueForLength(svg_style.Ry(), style,
SVGLengthMode::kHeight);
if (ry < 0)
return path;
if (!rx && !ry)
return path;
path.AddEllipse(FloatRect(length_context.ValueForLength(
svg_style.Cx(), style, SVGLengthMode::kWidth) -
rx,
length_context.ValueForLength(
svg_style.Cy(), style, SVGLengthMode::kHeight) -
ry,
rx * 2, ry * 2));
FloatPoint center(
length_context.ResolveLengthPair(svg_style.Cx(), svg_style.Cy(), style));
path.AddEllipse(FloatRect(center - radii, radii.ScaledBy(2)));
return path;
}
......
......@@ -197,6 +197,19 @@ FloatPoint SVGLengthContext::ResolvePoint(const SVGElement* context,
return FloatPoint(x.ValueAsPercentage(), y.ValueAsPercentage());
}
FloatPoint SVGLengthContext::ResolveLengthPair(
const Length& x_length,
const Length& y_length,
const ComputedStyle& style) const {
FloatSize viewport_size;
if (x_length.IsPercentOrCalc() || y_length.IsPercentOrCalc())
DetermineViewport(viewport_size);
float zoom = style.EffectiveZoom();
return FloatPoint(ValueForLength(x_length, zoom, viewport_size.Width()),
ValueForLength(y_length, zoom, viewport_size.Height()));
}
float SVGLengthContext::ResolveLength(const SVGElement* context,
SVGUnitTypes::SVGUnitType type,
const SVGLength& x) {
......
......@@ -64,6 +64,9 @@ class SVGLengthContext {
static float ResolveLength(const SVGElement*,
SVGUnitTypes::SVGUnitType,
const SVGLength&);
FloatPoint ResolveLengthPair(const Length& x_length,
const Length& y_length,
const ComputedStyle&) const;
float ConvertValueToUserUnits(float,
SVGLengthMode,
......
......@@ -79,40 +79,29 @@ Path SVGRectElement::AsPath() const {
SVGLengthContext length_context(this);
DCHECK(GetLayoutObject());
const ComputedStyle& style = GetLayoutObject()->StyleRef();
const SVGComputedStyle& svg_style = style.SvgStyle();
float width = length_context.ValueForLength(style.Width(), style,
SVGLengthMode::kWidth);
if (width < 0)
return path;
float height = length_context.ValueForLength(style.Height(), style,
SVGLengthMode::kHeight);
if (height < 0)
return path;
if (!width && !height)
FloatSize size(ToFloatSize(
length_context.ResolveLengthPair(style.Width(), style.Height(), style)));
if (size.Width() < 0 || size.Height() < 0 ||
(!size.Width() && !size.Height()))
return path;
float x = length_context.ValueForLength(svg_style.X(), style,
SVGLengthMode::kWidth);
float y = length_context.ValueForLength(svg_style.Y(), style,
SVGLengthMode::kHeight);
float rx = length_context.ValueForLength(svg_style.Rx(), style,
SVGLengthMode::kWidth);
float ry = length_context.ValueForLength(svg_style.Ry(), style,
SVGLengthMode::kHeight);
bool has_rx = rx > 0;
bool has_ry = ry > 0;
if (has_rx || has_ry) {
const SVGComputedStyle& svg_style = style.SvgStyle();
FloatRect rect(
length_context.ResolveLengthPair(svg_style.X(), svg_style.Y(), style),
size);
FloatPoint radii(
length_context.ResolveLengthPair(svg_style.Rx(), svg_style.Ry(), style));
if (radii.X() > 0 || radii.Y() > 0) {
if (svg_style.Rx().IsAuto())
rx = ry;
radii.SetX(radii.Y());
else if (svg_style.Ry().IsAuto())
ry = rx;
radii.SetY(radii.X());
path.AddRoundedRect(FloatRect(x, y, width, height), FloatSize(rx, ry));
return path;
path.AddRoundedRect(rect, ToFloatSize(radii));
} else {
path.AddRect(rect);
}
path.AddRect(FloatRect(x, y, width, height));
return path;
}
......
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