Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(262)

Side by Side Diff: cc/animation/transform_operations_unittest.cc

Issue 55763004: Allow the computation of inflated bounds for non matrix transform operations. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « cc/animation/transform_operation.cc ('k') | ui/gfx/box_f.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <limits> 5 #include <limits>
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/memory/scoped_vector.h" 8 #include "base/memory/scoped_vector.h"
9 #include "cc/animation/transform_operations.h" 9 #include "cc/animation/transform_operations.h"
10 #include "cc/test/geometry_test_utils.h" 10 #include "cc/test/geometry_test_utils.h"
11 #include "testing/gtest/include/gtest/gtest.h" 11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/gfx/animation/tween.h" 12 #include "ui/gfx/animation/tween.h"
13 #include "ui/gfx/box_f.h" 13 #include "ui/gfx/box_f.h"
14 #include "ui/gfx/rect_conversions.h"
14 #include "ui/gfx/vector3d_f.h" 15 #include "ui/gfx/vector3d_f.h"
15 16
16 namespace cc { 17 namespace cc {
17 namespace { 18 namespace {
18 19
19 TEST(TransformOperationTest, TransformTypesAreUnique) { 20 TEST(TransformOperationTest, TransformTypesAreUnique) {
20 ScopedVector<TransformOperations> transforms; 21 ScopedVector<TransformOperations> transforms;
21 22
22 TransformOperations* to_add = new TransformOperations(); 23 TransformOperations* to_add = new TransformOperations();
23 to_add->AppendTranslate(1, 0, 0); 24 to_add->AppendTranslate(1, 0, 0);
(...skipping 855 matching lines...) Expand 10 before | Expand all | Expand 10 after
879 880
880 float min = -1.f / 3.f; 881 float min = -1.f / 3.f;
881 float max = 1.f; 882 float max = 1.f;
882 float size = max - min; 883 float size = max - min;
883 EXPECT_TRUE(operations_to.BlendedBoundsForBox( 884 EXPECT_TRUE(operations_to.BlendedBoundsForBox(
884 box, operations_from, 0.f, 1.f, &bounds)); 885 box, operations_from, 0.f, 1.f, &bounds));
885 EXPECT_EQ(gfx::BoxF(min, min, min, size, size, size).ToString(), 886 EXPECT_EQ(gfx::BoxF(min, min, min, size, size, size).ToString(),
886 bounds.ToString()); 887 bounds.ToString());
887 } 888 }
888 889
890 TEST(TransformOperationTest, BlendedBoundsForRotationDifferentAxes) {
891 // We can handle rotations about a single axis. If the axes are different,
892 // we revert to matrix interpolation for which inflated bounds cannot be
893 // computed.
894 TransformOperations operations_from;
895 operations_from.AppendRotate(1.f, 1.f, 1.f, 30.f);
896 TransformOperations operations_to_same;
897 operations_to_same.AppendRotate(1.f, 1.f, 1.f, 390.f);
898 TransformOperations operations_to_opposite;
899 operations_to_opposite.AppendRotate(-1.f, -1.f, -1.f, 390.f);
900 TransformOperations operations_to_different;
901 operations_to_different.AppendRotate(1.f, 3.f, 1.f, 390.f);
902
903 gfx::BoxF box(1.f, 0.f, 0.f, 0.f, 0.f, 0.f);
904 gfx::BoxF bounds;
905
906 EXPECT_TRUE(operations_to_same.BlendedBoundsForBox(
907 box, operations_from, 0.f, 1.f, &bounds));
908 EXPECT_TRUE(operations_to_opposite.BlendedBoundsForBox(
909 box, operations_from, 0.f, 1.f, &bounds));
910 EXPECT_FALSE(operations_to_different.BlendedBoundsForBox(
911 box, operations_from, 0.f, 1.f, &bounds));
912 }
913
889 TEST(TransformOperationTest, BlendedBoundsForRotationPointOnAxis) { 914 TEST(TransformOperationTest, BlendedBoundsForRotationPointOnAxis) {
890 // Checks that if the point to rotate is sitting on the axis of rotation, that 915 // Checks that if the point to rotate is sitting on the axis of rotation, that
891 // it does not get affected. 916 // it does not get affected.
892 TransformOperations operations_from; 917 TransformOperations operations_from;
893 operations_from.AppendRotate(1.f, 1.f, 1.f, 30.f); 918 operations_from.AppendRotate(1.f, 1.f, 1.f, 30.f);
894 TransformOperations operations_to; 919 TransformOperations operations_to;
895 operations_to.AppendRotate(1.f, 1.f, 1.f, 390.f); 920 operations_to.AppendRotate(1.f, 1.f, 1.f, 390.f);
896 921
897 gfx::BoxF box(1.f, 1.f, 1.f, 0.f, 0.f, 0.f); 922 gfx::BoxF box(1.f, 1.f, 1.f, 0.f, 0.f, 0.f);
898 gfx::BoxF bounds; 923 gfx::BoxF bounds;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
961 struct TestAngles { 986 struct TestAngles {
962 float theta_from; 987 float theta_from;
963 float theta_to; 988 float theta_to;
964 }; 989 };
965 990
966 struct TestProgress { 991 struct TestProgress {
967 float min_progress; 992 float min_progress;
968 float max_progress; 993 float max_progress;
969 }; 994 };
970 995
971 TEST(TransformOperationsTest, BlendedBoundsForRotationEmpiricalTests) { 996 static void ExpectBoxesApproximatelyEqual(const gfx::BoxF& lhs,
997 const gfx::BoxF& rhs,
998 float tolerance) {
999 EXPECT_NEAR(lhs.x(), rhs.x(), tolerance);
1000 EXPECT_NEAR(lhs.y(), rhs.y(), tolerance);
1001 EXPECT_NEAR(lhs.z(), rhs.z(), tolerance);
1002 EXPECT_NEAR(lhs.width(), rhs.width(), tolerance);
1003 EXPECT_NEAR(lhs.height(), rhs.height(), tolerance);
1004 EXPECT_NEAR(lhs.depth(), rhs.depth(), tolerance);
1005 }
1006
1007 static void EmpiricallyTestBounds(const TransformOperations& from,
1008 const TransformOperations& to,
1009 SkMScalar min_progress,
1010 SkMScalar max_progress,
1011 bool test_containment_only) {
1012 gfx::BoxF box(200.f, 500.f, 100.f, 100.f, 300.f, 200.f);
1013 gfx::BoxF bounds;
1014 EXPECT_TRUE(
1015 to.BlendedBoundsForBox(box, from, min_progress, max_progress, &bounds));
1016
1017 bool first_time = true;
1018 gfx::BoxF empirical_bounds;
1019 static const size_t kNumSteps = 10;
1020 for (size_t step = 0; step < kNumSteps; ++step) {
1021 float t = step / (kNumSteps - 1.f);
1022 t = gfx::Tween::FloatValueBetween(t, min_progress, max_progress);
1023 gfx::Transform partial_transform = to.Blend(from, t);
1024 gfx::BoxF transformed = box;
1025 partial_transform.TransformBox(&transformed);
1026
1027 if (first_time) {
1028 empirical_bounds = transformed;
1029 first_time = false;
1030 } else {
1031 empirical_bounds.Union(transformed);
1032 }
1033 }
1034
1035 if (test_containment_only) {
1036 gfx::BoxF unified_bounds = bounds;
1037 unified_bounds.Union(empirical_bounds);
1038 // Convert to the screen space rects these boxes represent.
1039 gfx::Rect bounds_rect = ToEnclosingRect(
1040 gfx::RectF(bounds.x(), bounds.y(), bounds.width(), bounds.height()));
1041 gfx::Rect unified_bounds_rect =
1042 ToEnclosingRect(gfx::RectF(unified_bounds.x(),
1043 unified_bounds.y(),
1044 unified_bounds.width(),
1045 unified_bounds.height()));
1046 EXPECT_EQ(bounds_rect.ToString(), unified_bounds_rect.ToString());
1047 } else {
1048 // Our empirical estimate will be a little rough since we're only doing
1049 // 100 samples.
1050 static const float kTolerance = 1e-2f;
1051 ExpectBoxesApproximatelyEqual(empirical_bounds, bounds, kTolerance);
1052 }
1053 }
1054
1055 static void EmpiricallyTestBoundsEquality(const TransformOperations& from,
1056 const TransformOperations& to,
1057 SkMScalar min_progress,
1058 SkMScalar max_progress) {
1059 EmpiricallyTestBounds(from, to, min_progress, max_progress, false);
1060 }
1061
1062 static void EmpiricallyTestBoundsContainment(const TransformOperations& from,
1063 const TransformOperations& to,
1064 SkMScalar min_progress,
1065 SkMScalar max_progress) {
1066 EmpiricallyTestBounds(from, to, min_progress, max_progress, true);
1067 }
1068
1069 TEST(TransformOperationTest, BlendedBoundsForRotationEmpiricalTests) {
972 // Sets up various axis angle combinations, computes the bounding box and 1070 // Sets up various axis angle combinations, computes the bounding box and
973 // empirically tests that the transformed bounds are indeed contained by the 1071 // empirically tests that the transformed bounds are indeed contained by the
974 // computed bounding box. 1072 // computed bounding box.
975 1073
976 TestAxis axes[] = { 1074 TestAxis axes[] = {
977 { 1.f, 1.f, 1.f }, 1075 { 1.f, 1.f, 1.f },
978 { -1.f, -1.f, -1.f }, 1076 { -1.f, -1.f, -1.f },
979 { -1.f, 2.f, 3.f }, 1077 { -1.f, 2.f, 3.f },
980 { 1.f, -2.f, 3.f }, 1078 { 1.f, -2.f, 3.f },
981 { 1.f, 2.f, -3.f }, 1079 { 1.f, 2.f, -3.f },
(...skipping 23 matching lines...) Expand all
1005 }; 1103 };
1006 1104
1007 // We can go beyond the range [0, 1] (the bezier might slide out of this range 1105 // We can go beyond the range [0, 1] (the bezier might slide out of this range
1008 // at either end), but since the first and last knots are at (0, 0) and (1, 1) 1106 // at either end), but since the first and last knots are at (0, 0) and (1, 1)
1009 // we will never go within it, so these tests are sufficient. 1107 // we will never go within it, so these tests are sufficient.
1010 TestProgress progress[] = { 1108 TestProgress progress[] = {
1011 { 0.f, 1.f }, 1109 { 0.f, 1.f },
1012 { -.25f, 1.25f }, 1110 { -.25f, 1.25f },
1013 }; 1111 };
1014 1112
1015 size_t num_steps = 150;
1016 for (size_t i = 0; i < arraysize(axes); ++i) { 1113 for (size_t i = 0; i < arraysize(axes); ++i) {
1017 for (size_t j = 0; j < arraysize(angles); ++j) { 1114 for (size_t j = 0; j < arraysize(angles); ++j) {
1018 for (size_t k = 0; k < arraysize(progress); ++k) { 1115 for (size_t k = 0; k < arraysize(progress); ++k) {
1019 float x = axes[i].x; 1116 float x = axes[i].x;
1020 float y = axes[i].y; 1117 float y = axes[i].y;
1021 float z = axes[i].z; 1118 float z = axes[i].z;
1022 TransformOperations operations_from; 1119 TransformOperations operations_from;
1023 operations_from.AppendRotate(x, y, z, angles[j].theta_from); 1120 operations_from.AppendRotate(x, y, z, angles[j].theta_from);
1024 TransformOperations operations_to; 1121 TransformOperations operations_to;
1025 operations_to.AppendRotate(x, y, z, angles[j].theta_to); 1122 operations_to.AppendRotate(x, y, z, angles[j].theta_to);
1026 1123 EmpiricallyTestBoundsContainment(operations_from,
1027 gfx::BoxF box(2.f, 5.f, 6.f, 1.f, 3.f, 2.f); 1124 operations_to,
1028 gfx::BoxF bounds; 1125 progress[k].min_progress,
1029 1126 progress[k].max_progress);
1030 EXPECT_TRUE(operations_to.BlendedBoundsForBox(box,
1031 operations_from,
1032 progress[k].min_progress,
1033 progress[k].max_progress,
1034 &bounds));
1035 bool first_point = true;
1036 gfx::BoxF empirical_bounds;
1037 for (size_t step = 0; step < num_steps; ++step) {
1038 float t = step / (num_steps - 1.f);
1039 t = gfx::Tween::FloatValueBetween(
1040 t, progress[k].min_progress, progress[k].max_progress);
1041 gfx::Transform partial_rotation =
1042 operations_to.Blend(operations_from, t);
1043
1044 for (int corner = 0; corner < 8; ++corner) {
1045 gfx::Point3F point = box.origin();
1046 point += gfx::Vector3dF(corner & 1 ? box.width() : 0.f,
1047 corner & 2 ? box.height() : 0.f,
1048 corner & 4 ? box.depth() : 0.f);
1049 partial_rotation.TransformPoint(&point);
1050 if (first_point) {
1051 empirical_bounds.set_origin(point);
1052 first_point = false;
1053 } else {
1054 empirical_bounds.ExpandTo(point);
1055 }
1056 }
1057 }
1058
1059 // Our empirical estimate will be a little rough since we're only doing
1060 // 100 samples.
1061 static const float kTolerance = 1e-2f;
1062 EXPECT_NEAR(empirical_bounds.x(), bounds.x(), kTolerance);
1063 EXPECT_NEAR(empirical_bounds.y(), bounds.y(), kTolerance);
1064 EXPECT_NEAR(empirical_bounds.z(), bounds.z(), kTolerance);
1065 EXPECT_NEAR(empirical_bounds.width(), bounds.width(), kTolerance);
1066 EXPECT_NEAR(empirical_bounds.height(), bounds.height(), kTolerance);
1067 EXPECT_NEAR(empirical_bounds.depth(), bounds.depth(), kTolerance);
1068 } 1127 }
1069 } 1128 }
1070 } 1129 }
1071 } 1130 }
1072 1131
1073 TEST(TransformOperationTest, PerspectiveMatrixAndTransformBlendingEquivalency) { 1132 TEST(TransformOperationTest, PerspectiveMatrixAndTransformBlendingEquivalency) {
1074 TransformOperations from_operations; 1133 TransformOperations from_operations;
1075 from_operations.AppendPerspective(200); 1134 from_operations.AppendPerspective(200);
1076 1135
1077 TransformOperations to_operations; 1136 TransformOperations to_operations;
(...skipping 12 matching lines...) Expand all
1090 gfx::Transform blended_matrix = to_transform; 1149 gfx::Transform blended_matrix = to_transform;
1091 EXPECT_TRUE(blended_matrix.Blend(from_transform, progress)); 1150 EXPECT_TRUE(blended_matrix.Blend(from_transform, progress));
1092 1151
1093 gfx::Transform blended_transform = 1152 gfx::Transform blended_transform =
1094 to_operations.Blend(from_operations, progress); 1153 to_operations.Blend(from_operations, progress);
1095 1154
1096 EXPECT_TRANSFORMATION_MATRIX_EQ(blended_matrix, blended_transform); 1155 EXPECT_TRANSFORMATION_MATRIX_EQ(blended_matrix, blended_transform);
1097 } 1156 }
1098 } 1157 }
1099 1158
1159 struct TestPerspectiveDepths {
1160 float from_depth;
1161 float to_depth;
1162 };
1163
1164 TEST(TransformOperationTest, BlendedBoundsForPerspective) {
1165 TestPerspectiveDepths perspective_depths[] = {
1166 { 600.f, 400.f },
1167 { 800.f, 1000.f },
1168 { 800.f, std::numeric_limits<float>::infinity() },
1169 };
1170
1171 TestProgress progress[] = {
1172 { 0.f, 1.f },
1173 { -0.1f, 1.1f },
1174 };
1175
1176 for (size_t i = 0; i < arraysize(perspective_depths); ++i) {
1177 for (size_t j = 0; j < arraysize(progress); ++j) {
1178 TransformOperations operations_from;
1179 operations_from.AppendPerspective(perspective_depths[i].from_depth);
1180 TransformOperations operations_to;
1181 operations_to.AppendPerspective(perspective_depths[i].to_depth);
1182 EmpiricallyTestBoundsEquality(operations_from,
1183 operations_to,
1184 progress[j].min_progress,
1185 progress[j].max_progress);
1186 }
1187 }
1188 }
1189
1190 struct TestSkews {
1191 float from_x;
1192 float from_y;
1193 float to_x;
1194 float to_y;
1195 };
1196
1197 TEST(TransformOperationTest, BlendedBoundsForSkew) {
1198 TestSkews skews[] = {
1199 { 1.f, 0.5f, 0.5f, 1.f },
1200 { 2.f, 1.f, 0.5f, 0.5f },
1201 };
1202
1203 TestProgress progress[] = {
1204 { 0.f, 1.f },
1205 { -0.1f, 1.1f },
1206 };
1207
1208 for (size_t i = 0; i < arraysize(skews); ++i) {
1209 for (size_t j = 0; j < arraysize(progress); ++j) {
1210 TransformOperations operations_from;
1211 operations_from.AppendSkew(skews[i].from_x, skews[i].from_y);
1212 TransformOperations operations_to;
1213 operations_to.AppendSkew(skews[i].to_x, skews[i].to_y);
1214 EmpiricallyTestBoundsEquality(operations_from,
1215 operations_to,
1216 progress[j].min_progress,
1217 progress[j].max_progress);
1218 }
1219 }
1220 }
1221
1100 TEST(TransformOperationTest, BlendedBoundsForSequence) { 1222 TEST(TransformOperationTest, BlendedBoundsForSequence) {
1101 TransformOperations operations_from; 1223 TransformOperations operations_from;
1102 operations_from.AppendTranslate(2.0, 4.0, -1.0); 1224 operations_from.AppendTranslate(2.0, 4.0, -1.0);
1103 operations_from.AppendScale(-1.0, 2.0, 3.0); 1225 operations_from.AppendScale(-1.0, 2.0, 3.0);
1104 operations_from.AppendTranslate(1.0, -5.0, 1.0); 1226 operations_from.AppendTranslate(1.0, -5.0, 1.0);
1105 TransformOperations operations_to; 1227 TransformOperations operations_to;
1106 operations_to.AppendTranslate(6.0, -2.0, 3.0); 1228 operations_to.AppendTranslate(6.0, -2.0, 3.0);
1107 operations_to.AppendScale(-3.0, -2.0, 5.0); 1229 operations_to.AppendScale(-3.0, -2.0, 5.0);
1108 operations_to.AppendTranslate(13.0, -1.0, 5.0); 1230 operations_to.AppendTranslate(13.0, -1.0, 5.0);
1109 1231
(...skipping 21 matching lines...) Expand all
1131 bounds.ToString()); 1253 bounds.ToString());
1132 1254
1133 EXPECT_TRUE(identity.BlendedBoundsForBox( 1255 EXPECT_TRUE(identity.BlendedBoundsForBox(
1134 box, operations_from, min_progress, max_progress, &bounds)); 1256 box, operations_from, min_progress, max_progress, &bounds));
1135 EXPECT_EQ(gfx::BoxF(-7.f, -3.f, 2.f, 15.f, 23.f, 20.f).ToString(), 1257 EXPECT_EQ(gfx::BoxF(-7.f, -3.f, 2.f, 15.f, 23.f, 20.f).ToString(),
1136 bounds.ToString()); 1258 bounds.ToString());
1137 } 1259 }
1138 1260
1139 } // namespace 1261 } // namespace
1140 } // namespace cc 1262 } // namespace cc
OLDNEW
« no previous file with comments | « cc/animation/transform_operation.cc ('k') | ui/gfx/box_f.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698