Commit f5124311 authored by Malay Keshav's avatar Malay Keshav Committed by Commit Bot

Apply complete surface transform to rounded corners

This patch applies the complete surface transform to the rounded corner
bounds instead of just the translation and scaling component. This may
however fail if the transform being applied does not result in an axis
aligned output.

Since this is done at multiple code locations, a new API is added to
gfx::Transform to perform this.

Test: Added unittests for the new API.
Change-Id: I75b7234ca7b1abc918b35251b77b0a9f8aec1e2d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1838980Reviewed-by: default avatarDaniele Castagna <dcastagna@chromium.org>
Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: Malay Keshav <malaykeshav@chromium.org>
Cr-Commit-Position: refs/heads/master@{#706813}
parent d9e39eeb
...@@ -713,14 +713,13 @@ std::pair<gfx::RRectF, bool> GetRoundedCornerRRect( ...@@ -713,14 +713,13 @@ std::pair<gfx::RRectF, bool> GetRoundedCornerRRect(
if (!property_trees->GetToTarget(node->transform_id, target_id, &to_target)) if (!property_trees->GetToTarget(node->transform_id, target_id, &to_target))
return kEmptyRoundedCornerInfo; return kEmptyRoundedCornerInfo;
DCHECK(to_target.Preserves2dAxisAlignment()); auto result =
std::make_pair(node->rounded_corner_bounds, node->is_fast_rounded_corner);
SkRRect result; if (!to_target.TransformRRectF(&result.first))
if (!SkRRect(node->rounded_corner_bounds)
.transform(to_target.matrix(), &result)) {
return kEmptyRoundedCornerInfo; return kEmptyRoundedCornerInfo;
}
return std::make_pair(gfx::RRectF(result), node->is_fast_rounded_corner); return result;
} }
void UpdateRenderTarget(EffectTree* effect_tree) { void UpdateRenderTarget(EffectTree* effect_tree) {
......
...@@ -98,17 +98,15 @@ struct SurfaceAggregator::RoundedCornerInfo { ...@@ -98,17 +98,15 @@ struct SurfaceAggregator::RoundedCornerInfo {
RoundedCornerInfo() = default; RoundedCornerInfo() = default;
// |target_transform| is the transform that maps |bounds_arg| from its current // |target_transform| is the transform that maps |bounds_arg| from its current
// space into the desired target space. It must be a scale+translation matrix. // space into the desired target space. It must be an axis aligned transform.
RoundedCornerInfo(const gfx::RRectF& bounds_arg, RoundedCornerInfo(const gfx::RRectF& bounds_arg,
bool is_fast_rounded_corner, bool is_fast_rounded_corner,
const gfx::Transform target_transform) const gfx::Transform target_transform)
: bounds(bounds_arg), is_fast_rounded_corner(is_fast_rounded_corner) { : bounds(bounds_arg), is_fast_rounded_corner(is_fast_rounded_corner) {
if (bounds.IsEmpty()) if (bounds.IsEmpty())
return; return;
DCHECK(target_transform.Preserves2dAxisAlignment()); bool success = target_transform.TransformRRectF(&bounds);
SkMatrix matrix = target_transform.matrix(); DCHECK(success);
bounds.Scale(matrix.getScaleX(), matrix.getScaleY());
bounds.Offset(target_transform.To2dTranslation());
} }
gfx::RRectF bounds; gfx::RRectF bounds;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/safe_integer_conversions.h" #include "ui/gfx/geometry/safe_integer_conversions.h"
#include "ui/gfx/geometry/vector3d_f.h" #include "ui/gfx/geometry/vector3d_f.h"
#include "ui/gfx/rrect_f.h"
#include "ui/gfx/skia_util.h" #include "ui/gfx/skia_util.h"
#include "ui/gfx/transform_util.h" #include "ui/gfx/transform_util.h"
...@@ -485,6 +486,14 @@ bool Transform::TransformRectReverse(RectF* rect) const { ...@@ -485,6 +486,14 @@ bool Transform::TransformRectReverse(RectF* rect) const {
return true; return true;
} }
bool Transform::TransformRRectF(RRectF* rrect) const {
SkRRect result;
if (!SkRRect(*rrect).transform(matrix_, &result))
return false;
*rrect = gfx::RRectF(result);
return true;
}
void Transform::TransformBox(BoxF* box) const { void Transform::TransformBox(BoxF* box) const {
BoxF bounds; BoxF bounds;
bool first_point = true; bool first_point = true;
......
...@@ -17,6 +17,7 @@ namespace gfx { ...@@ -17,6 +17,7 @@ namespace gfx {
class BoxF; class BoxF;
class RectF; class RectF;
class RRectF;
class Point; class Point;
class PointF; class PointF;
class Point3F; class Point3F;
...@@ -242,6 +243,10 @@ class GEOMETRY_SKIA_EXPORT Transform { ...@@ -242,6 +243,10 @@ class GEOMETRY_SKIA_EXPORT Transform {
// inverted. // inverted.
bool TransformRectReverse(RectF* rect) const; bool TransformRectReverse(RectF* rect) const;
// Applies transformation on the given |rrect|. Returns false if the transform
// matrix cannot be applied to rrect.
bool TransformRRectF(RRectF* rrect) const;
// Applies transformation on the given box. After the function completes, // Applies transformation on the given box. After the function completes,
// |box| will be the smallest axis aligned bounding box containing the // |box| will be the smallest axis aligned bounding box containing the
// transformed box. // transformed box.
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "ui/gfx/geometry/point3_f.h" #include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/geometry/quad_f.h" #include "ui/gfx/geometry/quad_f.h"
#include "ui/gfx/geometry/vector3d_f.h" #include "ui/gfx/geometry/vector3d_f.h"
#include "ui/gfx/rrect_f.h"
#include "ui/gfx/transform_util.h" #include "ui/gfx/transform_util.h"
namespace gfx { namespace gfx {
...@@ -2638,6 +2639,35 @@ TEST(XFormTest, TransformRectReverse) { ...@@ -2638,6 +2639,35 @@ TEST(XFormTest, TransformRectReverse) {
EXPECT_FALSE(singular.TransformRectReverse(&rect)); EXPECT_FALSE(singular.TransformRectReverse(&rect));
} }
TEST(XFormTest, TransformRRectF) {
Transform translation;
translation.Translate(-3.f, -7.f);
RRectF rrect(1.f, 2.f, 20.f, 25.f, 5.f);
RRectF expected(-2.f, -5.f, 20.f, 25.f, 5.f);
EXPECT_TRUE(translation.TransformRRectF(&rrect));
EXPECT_EQ(expected.ToString(), rrect.ToString());
SkMatrix44 rot(SkMatrix44::kUninitialized_Constructor);
rot.set3x3(0, 1, 0, -1, 0, 0, 0, 0, 1);
Transform rotation_90_Clock(rot);
rrect = RRectF(gfx::RectF(0, 0, 20.f, 25.f),
gfx::RoundedCornersF(1.f, 2.f, 3.f, 4.f));
expected = RRectF(gfx::RectF(-25.f, 0, 25.f, 20.f),
gfx::RoundedCornersF(4.f, 1.f, 2.f, 3.f));
EXPECT_TRUE(rotation_90_Clock.TransformRRectF(&rrect));
EXPECT_EQ(expected.ToString(), rrect.ToString());
Transform scale;
scale.Scale(2.f, 2.f);
rrect = RRectF(gfx::RectF(0, 0, 20.f, 25.f),
gfx::RoundedCornersF(1.f, 2.f, 3.f, 4.f));
expected = RRectF(gfx::RectF(0, 0, 40.f, 50.f),
gfx::RoundedCornersF(2.f, 4.f, 6.f, 8.f));
EXPECT_TRUE(scale.TransformRRectF(&rrect));
EXPECT_EQ(expected.ToString(), rrect.ToString());
}
TEST(XFormTest, TransformBox) { TEST(XFormTest, TransformBox) {
Transform translation; Transform translation;
translation.Translate3d(3.f, 7.f, 6.f); translation.Translate3d(3.f, 7.f, 6.f);
......
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