transform_operations_unittest.cc 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809
  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
  3. // found in the LICENSE file.
  4. #include "ui/gfx/geometry/transform_operations.h"
  5. #include <stddef.h>
  6. #include <limits>
  7. #include <utility>
  8. #include <vector>
  9. #include "base/cxx17_backports.h"
  10. #include "testing/gtest/include/gtest/gtest.h"
  11. #include "ui/gfx/animation/tween.h"
  12. #include "ui/gfx/geometry/box_f.h"
  13. #include "ui/gfx/geometry/rect_conversions.h"
  14. #include "ui/gfx/geometry/test/geometry_util.h"
  15. #include "ui/gfx/geometry/vector3d_f.h"
  16. namespace gfx {
  17. namespace {
  18. void ExpectTransformOperationEqual(const TransformOperation& lhs,
  19. const TransformOperation& rhs) {
  20. EXPECT_EQ(lhs.type, rhs.type);
  21. EXPECT_TRANSFORM_EQ(lhs.matrix, rhs.matrix);
  22. switch (lhs.type) {
  23. case TransformOperation::TRANSFORM_OPERATION_TRANSLATE:
  24. EXPECT_FLOAT_EQ(lhs.translate.x, rhs.translate.x);
  25. EXPECT_FLOAT_EQ(lhs.translate.y, rhs.translate.y);
  26. EXPECT_FLOAT_EQ(lhs.translate.z, rhs.translate.z);
  27. break;
  28. case TransformOperation::TRANSFORM_OPERATION_ROTATE:
  29. EXPECT_FLOAT_EQ(lhs.rotate.axis.x, rhs.rotate.axis.x);
  30. EXPECT_FLOAT_EQ(lhs.rotate.axis.y, rhs.rotate.axis.y);
  31. EXPECT_FLOAT_EQ(lhs.rotate.axis.z, rhs.rotate.axis.z);
  32. EXPECT_FLOAT_EQ(lhs.rotate.angle, rhs.rotate.angle);
  33. break;
  34. case TransformOperation::TRANSFORM_OPERATION_SCALE:
  35. EXPECT_FLOAT_EQ(lhs.scale.x, rhs.scale.x);
  36. EXPECT_FLOAT_EQ(lhs.scale.y, rhs.scale.y);
  37. EXPECT_FLOAT_EQ(lhs.scale.z, rhs.scale.z);
  38. break;
  39. case TransformOperation::TRANSFORM_OPERATION_SKEWX:
  40. case TransformOperation::TRANSFORM_OPERATION_SKEWY:
  41. case TransformOperation::TRANSFORM_OPERATION_SKEW:
  42. EXPECT_FLOAT_EQ(lhs.skew.x, rhs.skew.x);
  43. EXPECT_FLOAT_EQ(lhs.skew.y, rhs.skew.y);
  44. break;
  45. case TransformOperation::TRANSFORM_OPERATION_PERSPECTIVE:
  46. EXPECT_FLOAT_EQ(lhs.perspective_m43, rhs.perspective_m43);
  47. break;
  48. case TransformOperation::TRANSFORM_OPERATION_MATRIX:
  49. case TransformOperation::TRANSFORM_OPERATION_IDENTITY:
  50. break;
  51. }
  52. }
  53. TEST(TransformOperationTest, TransformTypesAreUnique) {
  54. std::vector<std::unique_ptr<TransformOperations>> transforms;
  55. std::unique_ptr<TransformOperations> to_add(
  56. std::make_unique<TransformOperations>());
  57. to_add->AppendTranslate(1, 0, 0);
  58. transforms.push_back(std::move(to_add));
  59. to_add = std::make_unique<TransformOperations>();
  60. to_add->AppendRotate(0, 0, 1, 2);
  61. transforms.push_back(std::move(to_add));
  62. to_add = std::make_unique<TransformOperations>();
  63. to_add->AppendScale(2, 2, 2);
  64. transforms.push_back(std::move(to_add));
  65. to_add = std::make_unique<TransformOperations>();
  66. to_add->AppendSkew(1, 0);
  67. transforms.push_back(std::move(to_add));
  68. to_add = std::make_unique<TransformOperations>();
  69. to_add->AppendPerspective(800);
  70. transforms.push_back(std::move(to_add));
  71. for (size_t i = 0; i < transforms.size(); ++i) {
  72. for (size_t j = 0; j < transforms.size(); ++j) {
  73. bool matches_type = transforms[i]->MatchesTypes(*transforms[j]);
  74. EXPECT_TRUE((i == j && matches_type) || !matches_type);
  75. }
  76. }
  77. }
  78. TEST(TransformOperationTest, MatchingPrefixSameLength) {
  79. TransformOperations translates;
  80. translates.AppendTranslate(1, 0, 0);
  81. translates.AppendTranslate(1, 0, 0);
  82. translates.AppendTranslate(1, 0, 0);
  83. TransformOperations skews;
  84. skews.AppendSkew(0, 2);
  85. skews.AppendSkew(0, 2);
  86. skews.AppendSkew(0, 2);
  87. TransformOperations translates2;
  88. translates2.AppendTranslate(0, 2, 0);
  89. translates2.AppendTranslate(0, 2, 0);
  90. translates2.AppendTranslate(0, 2, 0);
  91. TransformOperations mixed;
  92. mixed.AppendTranslate(0, 2, 0);
  93. mixed.AppendScale(2, 1, 1);
  94. mixed.AppendSkew(0, 2);
  95. TransformOperations translates3 = translates2;
  96. EXPECT_EQ(0UL, translates.MatchingPrefixLength(skews));
  97. EXPECT_EQ(3UL, translates.MatchingPrefixLength(translates2));
  98. EXPECT_EQ(3UL, translates.MatchingPrefixLength(translates3));
  99. EXPECT_EQ(1UL, translates.MatchingPrefixLength(mixed));
  100. }
  101. TEST(TransformOperationTest, MatchingPrefixDifferentLength) {
  102. TransformOperations translates;
  103. translates.AppendTranslate(1, 0, 0);
  104. translates.AppendTranslate(1, 0, 0);
  105. translates.AppendTranslate(1, 0, 0);
  106. TransformOperations skews;
  107. skews.AppendSkew(2, 0);
  108. skews.AppendSkew(2, 0);
  109. TransformOperations translates2;
  110. translates2.AppendTranslate(0, 2, 0);
  111. translates2.AppendTranslate(0, 2, 0);
  112. TransformOperations none;
  113. EXPECT_EQ(0UL, translates.MatchingPrefixLength(skews));
  114. // Pad the length of the shorter list provided all previous operation-
  115. // pairs match per spec
  116. // (https://drafts.csswg.org/css-transforms/#interpolation-of-transforms).
  117. EXPECT_EQ(3UL, translates.MatchingPrefixLength(translates2));
  118. EXPECT_EQ(3UL, translates.MatchingPrefixLength(none));
  119. }
  120. std::vector<std::unique_ptr<TransformOperations>> GetIdentityOperations() {
  121. std::vector<std::unique_ptr<TransformOperations>> operations;
  122. std::unique_ptr<TransformOperations> to_add(
  123. std::make_unique<TransformOperations>());
  124. operations.push_back(std::move(to_add));
  125. to_add = std::make_unique<TransformOperations>();
  126. to_add->AppendTranslate(0, 0, 0);
  127. operations.push_back(std::move(to_add));
  128. to_add = std::make_unique<TransformOperations>();
  129. to_add->AppendTranslate(0, 0, 0);
  130. to_add->AppendTranslate(0, 0, 0);
  131. operations.push_back(std::move(to_add));
  132. to_add = std::make_unique<TransformOperations>();
  133. to_add->AppendScale(1, 1, 1);
  134. operations.push_back(std::move(to_add));
  135. to_add = std::make_unique<TransformOperations>();
  136. to_add->AppendScale(1, 1, 1);
  137. to_add->AppendScale(1, 1, 1);
  138. operations.push_back(std::move(to_add));
  139. to_add = std::make_unique<TransformOperations>();
  140. to_add->AppendSkew(0, 0);
  141. operations.push_back(std::move(to_add));
  142. to_add = std::make_unique<TransformOperations>();
  143. to_add->AppendSkew(0, 0);
  144. to_add->AppendSkew(0, 0);
  145. operations.push_back(std::move(to_add));
  146. to_add = std::make_unique<TransformOperations>();
  147. to_add->AppendRotate(0, 0, 1, 0);
  148. operations.push_back(std::move(to_add));
  149. to_add = std::make_unique<TransformOperations>();
  150. to_add->AppendRotate(0, 0, 1, 0);
  151. to_add->AppendRotate(0, 0, 1, 0);
  152. operations.push_back(std::move(to_add));
  153. to_add = std::make_unique<TransformOperations>();
  154. to_add->AppendMatrix(gfx::Transform());
  155. operations.push_back(std::move(to_add));
  156. to_add = std::make_unique<TransformOperations>();
  157. to_add->AppendMatrix(gfx::Transform());
  158. to_add->AppendMatrix(gfx::Transform());
  159. operations.push_back(std::move(to_add));
  160. return operations;
  161. }
  162. TEST(TransformOperationTest, MatchingPrefixLengthOrder) {
  163. TransformOperations mix_order_identity;
  164. mix_order_identity.AppendTranslate(0, 0, 0);
  165. mix_order_identity.AppendScale(1, 1, 1);
  166. mix_order_identity.AppendTranslate(0, 0, 0);
  167. TransformOperations mix_order_one;
  168. mix_order_one.AppendTranslate(0, 1, 0);
  169. mix_order_one.AppendScale(2, 1, 3);
  170. mix_order_one.AppendTranslate(1, 0, 0);
  171. TransformOperations mix_order_two;
  172. mix_order_two.AppendTranslate(0, 1, 0);
  173. mix_order_two.AppendTranslate(1, 0, 0);
  174. mix_order_two.AppendScale(2, 1, 3);
  175. EXPECT_EQ(3UL, mix_order_identity.MatchingPrefixLength(mix_order_one));
  176. EXPECT_EQ(1UL, mix_order_identity.MatchingPrefixLength(mix_order_two));
  177. EXPECT_EQ(1UL, mix_order_one.MatchingPrefixLength(mix_order_two));
  178. }
  179. TEST(TransformOperationTest, NoneAlwaysMatches) {
  180. std::vector<std::unique_ptr<TransformOperations>> operations =
  181. GetIdentityOperations();
  182. TransformOperations none_operation;
  183. for (const auto& operation : operations) {
  184. EXPECT_EQ(operation->size(),
  185. operation->MatchingPrefixLength(none_operation));
  186. }
  187. }
  188. TEST(TransformOperationTest, ApplyTranslate) {
  189. SkScalar x = 1;
  190. SkScalar y = 2;
  191. SkScalar z = 3;
  192. TransformOperations operations;
  193. operations.AppendTranslate(x, y, z);
  194. gfx::Transform expected;
  195. expected.Translate3d(x, y, z);
  196. EXPECT_TRANSFORM_EQ(expected, operations.Apply());
  197. }
  198. TEST(TransformOperationTest, ApplyRotate) {
  199. SkScalar x = 1;
  200. SkScalar y = 2;
  201. SkScalar z = 3;
  202. SkScalar degrees = 80;
  203. TransformOperations operations;
  204. operations.AppendRotate(x, y, z, degrees);
  205. gfx::Transform expected;
  206. expected.RotateAbout(gfx::Vector3dF(x, y, z), degrees);
  207. EXPECT_TRANSFORM_EQ(expected, operations.Apply());
  208. }
  209. TEST(TransformOperationTest, ApplyScale) {
  210. SkScalar x = 1;
  211. SkScalar y = 2;
  212. SkScalar z = 3;
  213. TransformOperations operations;
  214. operations.AppendScale(x, y, z);
  215. gfx::Transform expected;
  216. expected.Scale3d(x, y, z);
  217. EXPECT_TRANSFORM_EQ(expected, operations.Apply());
  218. }
  219. TEST(TransformOperationTest, ApplySkew) {
  220. SkScalar x = 1;
  221. SkScalar y = 2;
  222. TransformOperations operations;
  223. operations.AppendSkew(x, y);
  224. gfx::Transform expected;
  225. expected.Skew(x, y);
  226. EXPECT_TRANSFORM_EQ(expected, operations.Apply());
  227. }
  228. TEST(TransformOperationTest, ApplyPerspective) {
  229. SkScalar depth = 800;
  230. TransformOperations operations;
  231. operations.AppendPerspective(depth);
  232. gfx::Transform expected;
  233. expected.ApplyPerspectiveDepth(depth);
  234. EXPECT_TRANSFORM_EQ(expected, operations.Apply());
  235. }
  236. TEST(TransformOperationTest, ApplyMatrix) {
  237. SkScalar dx = 1;
  238. SkScalar dy = 2;
  239. SkScalar dz = 3;
  240. gfx::Transform expected_matrix;
  241. expected_matrix.Translate3d(dx, dy, dz);
  242. TransformOperations matrix_transform;
  243. matrix_transform.AppendMatrix(expected_matrix);
  244. EXPECT_TRANSFORM_EQ(expected_matrix, matrix_transform.Apply());
  245. }
  246. TEST(TransformOperationTest, ApplyOrder) {
  247. SkScalar sx = 2;
  248. SkScalar sy = 4;
  249. SkScalar sz = 8;
  250. SkScalar dx = 1;
  251. SkScalar dy = 2;
  252. SkScalar dz = 3;
  253. TransformOperations operations;
  254. operations.AppendScale(sx, sy, sz);
  255. operations.AppendTranslate(dx, dy, dz);
  256. gfx::Transform expected_scale_matrix;
  257. expected_scale_matrix.Scale3d(sx, sy, sz);
  258. gfx::Transform expected_translate_matrix;
  259. expected_translate_matrix.Translate3d(dx, dy, dz);
  260. gfx::Transform expected_combined_matrix = expected_scale_matrix;
  261. expected_combined_matrix.PreconcatTransform(expected_translate_matrix);
  262. EXPECT_TRANSFORM_EQ(expected_combined_matrix, operations.Apply());
  263. }
  264. TEST(TransformOperationTest, BlendOrder) {
  265. SkScalar sx1 = 2;
  266. SkScalar sy1 = 4;
  267. SkScalar sz1 = 8;
  268. SkScalar dx1 = 1;
  269. SkScalar dy1 = 2;
  270. SkScalar dz1 = 3;
  271. SkScalar sx2 = 4;
  272. SkScalar sy2 = 8;
  273. SkScalar sz2 = 16;
  274. SkScalar dx2 = 10;
  275. SkScalar dy2 = 20;
  276. SkScalar dz2 = 30;
  277. SkScalar sx3 = 2;
  278. SkScalar sy3 = 1;
  279. SkScalar sz3 = 1;
  280. TransformOperations operations_from;
  281. operations_from.AppendScale(sx1, sy1, sz1);
  282. operations_from.AppendTranslate(dx1, dy1, dz1);
  283. TransformOperations operations_to;
  284. operations_to.AppendScale(sx2, sy2, sz2);
  285. operations_to.AppendTranslate(dx2, dy2, dz2);
  286. gfx::Transform scale_from;
  287. scale_from.Scale3d(sx1, sy1, sz1);
  288. gfx::Transform translate_from;
  289. translate_from.Translate3d(dx1, dy1, dz1);
  290. gfx::Transform scale_to;
  291. scale_to.Scale3d(sx2, sy2, sz2);
  292. gfx::Transform translate_to;
  293. translate_to.Translate3d(dx2, dy2, dz2);
  294. SkScalar progress = 0.25f;
  295. TransformOperations operations_expected;
  296. operations_expected.AppendScale(
  297. gfx::Tween::FloatValueBetween(progress, sx1, sx2),
  298. gfx::Tween::FloatValueBetween(progress, sy1, sy2),
  299. gfx::Tween::FloatValueBetween(progress, sz1, sz2));
  300. operations_expected.AppendTranslate(
  301. gfx::Tween::FloatValueBetween(progress, dx1, dx2),
  302. gfx::Tween::FloatValueBetween(progress, dy1, dy2),
  303. gfx::Tween::FloatValueBetween(progress, dz1, dz2));
  304. gfx::Transform blended_scale = scale_to;
  305. blended_scale.Blend(scale_from, progress);
  306. gfx::Transform blended_translate = translate_to;
  307. blended_translate.Blend(translate_from, progress);
  308. gfx::Transform expected = blended_scale;
  309. expected.PreconcatTransform(blended_translate);
  310. TransformOperations blended = operations_to.Blend(operations_from, progress);
  311. EXPECT_TRANSFORM_EQ(expected, blended.Apply());
  312. EXPECT_TRANSFORM_EQ(operations_expected.Apply(), blended.Apply());
  313. EXPECT_EQ(operations_expected.size(), blended.size());
  314. for (size_t i = 0; i < operations_expected.size(); ++i) {
  315. TransformOperation expected_op = operations_expected.at(i);
  316. TransformOperation blended_op = blended.at(i);
  317. SCOPED_TRACE(i);
  318. ExpectTransformOperationEqual(expected_op, blended_op);
  319. }
  320. TransformOperations base_operations_expected = operations_expected;
  321. // Create a mismatch in number of operations. Pairwise interpolation is still
  322. // used when the operations match up to the length of the shorter list.
  323. operations_to.AppendScale(sx3, sy3, sz3);
  324. gfx::Transform appended_scale;
  325. appended_scale.Scale3d(sx3, sy3, sz3);
  326. gfx::Transform blended_append_scale = appended_scale;
  327. blended_append_scale.Blend(gfx::Transform(), progress);
  328. expected.PreconcatTransform(blended_append_scale);
  329. operations_expected.AppendScale(
  330. gfx::Tween::FloatValueBetween(progress, 1, sx3),
  331. gfx::Tween::FloatValueBetween(progress, 1, sy3),
  332. gfx::Tween::FloatValueBetween(progress, 1, sz3));
  333. blended = operations_to.Blend(operations_from, progress);
  334. EXPECT_TRANSFORM_EQ(expected, blended.Apply());
  335. EXPECT_TRANSFORM_EQ(operations_expected.Apply(), blended.Apply());
  336. EXPECT_EQ(operations_expected.size(), blended.size());
  337. for (size_t i = 0; i < operations_expected.size(); ++i) {
  338. TransformOperation expected_op = operations_expected.at(i);
  339. TransformOperation blended_op = blended.at(i);
  340. SCOPED_TRACE(i);
  341. ExpectTransformOperationEqual(expected_op, blended_op);
  342. }
  343. // Create a mismatch, forcing matrix interpolation for the last operator pair.
  344. operations_from.AppendRotate(0, 0, 1, 90);
  345. blended = operations_to.Blend(operations_from, progress);
  346. gfx::Transform transform_from;
  347. transform_from.RotateAboutZAxis(90);
  348. gfx::Transform transform_to;
  349. transform_to.Scale3d(sx3, sy3, sz3);
  350. gfx::Transform blended_matrix = transform_to;
  351. blended_matrix.Blend(transform_from, progress);
  352. expected = blended_scale;
  353. expected.PreconcatTransform(blended_translate);
  354. expected.PreconcatTransform(blended_matrix);
  355. operations_expected = base_operations_expected;
  356. operations_expected.AppendMatrix(blended_matrix);
  357. EXPECT_TRANSFORM_EQ(expected, blended.Apply());
  358. EXPECT_TRANSFORM_EQ(operations_expected.Apply(), blended.Apply());
  359. EXPECT_EQ(operations_expected.size(), blended.size());
  360. for (size_t i = 0; i < operations_expected.size(); ++i) {
  361. TransformOperation expected_op = operations_expected.at(i);
  362. TransformOperation blended_op = blended.at(i);
  363. SCOPED_TRACE(i);
  364. ExpectTransformOperationEqual(expected_op, blended_op);
  365. }
  366. }
  367. static void CheckProgress(SkScalar progress,
  368. const gfx::Transform& from_matrix,
  369. const gfx::Transform& to_matrix,
  370. const TransformOperations& from_transform,
  371. const TransformOperations& to_transform) {
  372. gfx::Transform expected_matrix = to_matrix;
  373. expected_matrix.Blend(from_matrix, progress);
  374. EXPECT_TRANSFORM_EQ(expected_matrix,
  375. to_transform.Blend(from_transform, progress).Apply());
  376. }
  377. TEST(TransformOperationTest, BlendProgress) {
  378. SkScalar sx = 2;
  379. SkScalar sy = 4;
  380. SkScalar sz = 8;
  381. TransformOperations operations_from;
  382. operations_from.AppendScale(sx, sy, sz);
  383. gfx::Transform matrix_from;
  384. matrix_from.Scale3d(sx, sy, sz);
  385. sx = 4;
  386. sy = 8;
  387. sz = 16;
  388. TransformOperations operations_to;
  389. operations_to.AppendScale(sx, sy, sz);
  390. gfx::Transform matrix_to;
  391. matrix_to.Scale3d(sx, sy, sz);
  392. CheckProgress(-1, matrix_from, matrix_to, operations_from, operations_to);
  393. CheckProgress(0, matrix_from, matrix_to, operations_from, operations_to);
  394. CheckProgress(0.25f, matrix_from, matrix_to, operations_from, operations_to);
  395. CheckProgress(0.5f, matrix_from, matrix_to, operations_from, operations_to);
  396. CheckProgress(1, matrix_from, matrix_to, operations_from, operations_to);
  397. CheckProgress(2, matrix_from, matrix_to, operations_from, operations_to);
  398. }
  399. TEST(TransformOperationTest, BlendWhenTypesDoNotMatch) {
  400. SkScalar sx1 = 2;
  401. SkScalar sy1 = 4;
  402. SkScalar sz1 = 8;
  403. SkScalar dx1 = 1;
  404. SkScalar dy1 = 2;
  405. SkScalar dz1 = 3;
  406. SkScalar sx2 = 4;
  407. SkScalar sy2 = 8;
  408. SkScalar sz2 = 16;
  409. SkScalar dx2 = 10;
  410. SkScalar dy2 = 20;
  411. SkScalar dz2 = 30;
  412. TransformOperations operations_from;
  413. operations_from.AppendScale(sx1, sy1, sz1);
  414. operations_from.AppendTranslate(dx1, dy1, dz1);
  415. TransformOperations operations_to;
  416. operations_to.AppendTranslate(dx2, dy2, dz2);
  417. operations_to.AppendScale(sx2, sy2, sz2);
  418. gfx::Transform from;
  419. from.Scale3d(sx1, sy1, sz1);
  420. from.Translate3d(dx1, dy1, dz1);
  421. gfx::Transform to;
  422. to.Translate3d(dx2, dy2, dz2);
  423. to.Scale3d(sx2, sy2, sz2);
  424. SkScalar progress = 0.25f;
  425. gfx::Transform expected = to;
  426. expected.Blend(from, progress);
  427. EXPECT_TRANSFORM_EQ(expected,
  428. operations_to.Blend(operations_from, progress).Apply());
  429. }
  430. TEST(TransformOperationTest, LargeRotationsWithSameAxis) {
  431. TransformOperations operations_from;
  432. operations_from.AppendRotate(0, 0, 1, 0);
  433. TransformOperations operations_to;
  434. operations_to.AppendRotate(0, 0, 2, 360);
  435. SkScalar progress = 0.5f;
  436. gfx::Transform expected;
  437. expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 180);
  438. EXPECT_TRANSFORM_EQ(expected,
  439. operations_to.Blend(operations_from, progress).Apply());
  440. }
  441. TEST(TransformOperationTest, LargeRotationsWithSameAxisInDifferentDirection) {
  442. TransformOperations operations_from;
  443. operations_from.AppendRotate(0, 0, 1, 180);
  444. TransformOperations operations_to;
  445. operations_to.AppendRotate(0, 0, -1, 180);
  446. SkScalar progress = 0.5f;
  447. gfx::Transform expected;
  448. EXPECT_TRANSFORM_EQ(expected,
  449. operations_to.Blend(operations_from, progress).Apply());
  450. }
  451. TEST(TransformOperationTest, LargeRotationsWithDifferentAxes) {
  452. TransformOperations operations_from;
  453. operations_from.AppendRotate(0, 0, 1, 175);
  454. TransformOperations operations_to;
  455. operations_to.AppendRotate(0, 1, 0, 175);
  456. SkScalar progress = 0.5f;
  457. gfx::Transform matrix_from;
  458. matrix_from.RotateAbout(gfx::Vector3dF(0, 0, 1), 175);
  459. gfx::Transform matrix_to;
  460. matrix_to.RotateAbout(gfx::Vector3dF(0, 1, 0), 175);
  461. gfx::Transform expected = matrix_to;
  462. expected.Blend(matrix_from, progress);
  463. EXPECT_TRANSFORM_EQ(expected,
  464. operations_to.Blend(operations_from, progress).Apply());
  465. }
  466. TEST(TransformOperationTest, RotationFromZeroDegDifferentAxes) {
  467. TransformOperations operations_from;
  468. operations_from.AppendRotate(0, 0, 1, 0);
  469. TransformOperations operations_to;
  470. operations_to.AppendRotate(0, 1, 0, 450);
  471. SkScalar progress = 0.5f;
  472. gfx::Transform expected;
  473. expected.RotateAbout(gfx::Vector3dF(0, 1, 0), 225);
  474. EXPECT_TRANSFORM_EQ(expected,
  475. operations_to.Blend(operations_from, progress).Apply());
  476. }
  477. TEST(TransformOperationTest, RotationFromZeroDegSameAxes) {
  478. TransformOperations operations_from;
  479. operations_from.AppendRotate(0, 0, 1, 0);
  480. TransformOperations operations_to;
  481. operations_to.AppendRotate(0, 0, 1, 450);
  482. SkScalar progress = 0.5f;
  483. gfx::Transform expected;
  484. expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 225);
  485. EXPECT_TRANSFORM_EQ(expected,
  486. operations_to.Blend(operations_from, progress).Apply());
  487. }
  488. TEST(TransformOperationTest, RotationToZeroDegDifferentAxes) {
  489. TransformOperations operations_from;
  490. operations_from.AppendRotate(0, 1, 0, 450);
  491. TransformOperations operations_to;
  492. operations_to.AppendRotate(0, 0, 1, 0);
  493. SkScalar progress = 0.5f;
  494. gfx::Transform expected;
  495. expected.RotateAbout(gfx::Vector3dF(0, 1, 0), 225);
  496. EXPECT_TRANSFORM_EQ(expected,
  497. operations_to.Blend(operations_from, progress).Apply());
  498. }
  499. TEST(TransformOperationTest, RotationToZeroDegSameAxes) {
  500. TransformOperations operations_from;
  501. operations_from.AppendRotate(0, 0, 1, 450);
  502. TransformOperations operations_to;
  503. operations_to.AppendRotate(0, 0, 1, 0);
  504. SkScalar progress = 0.5f;
  505. gfx::Transform expected;
  506. expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 225);
  507. EXPECT_TRANSFORM_EQ(expected,
  508. operations_to.Blend(operations_from, progress).Apply());
  509. }
  510. TEST(TransformOperationTest, BlendRotationFromIdentity) {
  511. std::vector<std::unique_ptr<TransformOperations>> identity_operations =
  512. GetIdentityOperations();
  513. for (const auto& identity_operation : identity_operations) {
  514. TransformOperations operations;
  515. operations.AppendRotate(0, 0, 1, 90);
  516. SkScalar progress = 0.5f;
  517. gfx::Transform expected;
  518. expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 45);
  519. EXPECT_TRANSFORM_EQ(
  520. expected, operations.Blend(*identity_operation, progress).Apply());
  521. progress = -0.5f;
  522. expected.MakeIdentity();
  523. expected.RotateAbout(gfx::Vector3dF(0, 0, 1), -45);
  524. EXPECT_TRANSFORM_EQ(
  525. expected, operations.Blend(*identity_operation, progress).Apply());
  526. progress = 1.5f;
  527. expected.MakeIdentity();
  528. expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 135);
  529. EXPECT_TRANSFORM_EQ(
  530. expected, operations.Blend(*identity_operation, progress).Apply());
  531. }
  532. }
  533. TEST(TransformOperationTest, BlendTranslationFromIdentity) {
  534. std::vector<std::unique_ptr<TransformOperations>> identity_operations =
  535. GetIdentityOperations();
  536. for (const auto& identity_operation : identity_operations) {
  537. TransformOperations operations;
  538. operations.AppendTranslate(2, 2, 2);
  539. SkScalar progress = 0.5f;
  540. gfx::Transform expected;
  541. expected.Translate3d(1, 1, 1);
  542. EXPECT_TRANSFORM_EQ(
  543. expected, operations.Blend(*identity_operation, progress).Apply());
  544. progress = -0.5f;
  545. expected.MakeIdentity();
  546. expected.Translate3d(-1, -1, -1);
  547. EXPECT_TRANSFORM_EQ(
  548. expected, operations.Blend(*identity_operation, progress).Apply());
  549. progress = 1.5f;
  550. expected.MakeIdentity();
  551. expected.Translate3d(3, 3, 3);
  552. EXPECT_TRANSFORM_EQ(
  553. expected, operations.Blend(*identity_operation, progress).Apply());
  554. }
  555. }
  556. TEST(TransformOperationTest, BlendScaleFromIdentity) {
  557. std::vector<std::unique_ptr<TransformOperations>> identity_operations =
  558. GetIdentityOperations();
  559. for (const auto& identity_operation : identity_operations) {
  560. TransformOperations operations;
  561. operations.AppendScale(3, 3, 3);
  562. SkScalar progress = 0.5f;
  563. gfx::Transform expected;
  564. expected.Scale3d(2, 2, 2);
  565. EXPECT_TRANSFORM_EQ(
  566. expected, operations.Blend(*identity_operation, progress).Apply());
  567. progress = -0.5f;
  568. expected.MakeIdentity();
  569. expected.Scale3d(0, 0, 0);
  570. EXPECT_TRANSFORM_EQ(
  571. expected, operations.Blend(*identity_operation, progress).Apply());
  572. progress = 1.5f;
  573. expected.MakeIdentity();
  574. expected.Scale3d(4, 4, 4);
  575. EXPECT_TRANSFORM_EQ(
  576. expected, operations.Blend(*identity_operation, progress).Apply());
  577. }
  578. }
  579. TEST(TransformOperationTest, BlendSkewFromEmpty) {
  580. TransformOperations empty_operation;
  581. TransformOperations operations;
  582. operations.AppendSkew(2, 2);
  583. SkScalar progress = 0.5f;
  584. gfx::Transform expected;
  585. expected.Skew(1, 1);
  586. EXPECT_TRANSFORM_EQ(expected,
  587. operations.Blend(empty_operation, progress).Apply());
  588. progress = -0.5f;
  589. expected.MakeIdentity();
  590. expected.Skew(-1, -1);
  591. EXPECT_TRANSFORM_EQ(expected,
  592. operations.Blend(empty_operation, progress).Apply());
  593. progress = 1.5f;
  594. expected.MakeIdentity();
  595. expected.Skew(3, 3);
  596. EXPECT_TRANSFORM_EQ(expected,
  597. operations.Blend(empty_operation, progress).Apply());
  598. }
  599. TEST(TransformOperationTest, BlendPerspectiveFromIdentity) {
  600. std::vector<std::unique_ptr<TransformOperations>> identity_operations =
  601. GetIdentityOperations();
  602. for (const auto& identity_operation : identity_operations) {
  603. TransformOperations operations;
  604. operations.AppendPerspective(1000);
  605. SkScalar progress = 0.5f;
  606. gfx::Transform expected;
  607. expected.ApplyPerspectiveDepth(2000);
  608. EXPECT_TRANSFORM_EQ(
  609. expected, operations.Blend(*identity_operation, progress).Apply());
  610. }
  611. }
  612. TEST(TransformOperationTest, BlendRotationToIdentity) {
  613. std::vector<std::unique_ptr<TransformOperations>> identity_operations =
  614. GetIdentityOperations();
  615. for (const auto& identity_operation : identity_operations) {
  616. TransformOperations operations;
  617. operations.AppendRotate(0, 0, 1, 90);
  618. SkScalar progress = 0.5f;
  619. gfx::Transform expected;
  620. expected.RotateAbout(gfx::Vector3dF(0, 0, 1), 45);
  621. EXPECT_TRANSFORM_EQ(
  622. expected, identity_operation->Blend(operations, progress).Apply());
  623. }
  624. }
  625. TEST(TransformOperationTest, BlendTranslationToIdentity) {
  626. std::vector<std::unique_ptr<TransformOperations>> identity_operations =
  627. GetIdentityOperations();
  628. for (const auto& identity_operation : identity_operations) {
  629. TransformOperations operations;
  630. operations.AppendTranslate(2, 2, 2);
  631. SkScalar progress = 0.5f;
  632. gfx::Transform expected;
  633. expected.Translate3d(1, 1, 1);
  634. EXPECT_TRANSFORM_EQ(
  635. expected, identity_operation->Blend(operations, progress).Apply());
  636. }
  637. }
  638. TEST(TransformOperationTest, BlendScaleToIdentity) {
  639. std::vector<std::unique_ptr<TransformOperations>> identity_operations =
  640. GetIdentityOperations();
  641. for (const auto& identity_operation : identity_operations) {
  642. TransformOperations operations;
  643. operations.AppendScale(3, 3, 3);
  644. SkScalar progress = 0.5f;
  645. gfx::Transform expected;
  646. expected.Scale3d(2, 2, 2);
  647. EXPECT_TRANSFORM_EQ(
  648. expected, identity_operation->Blend(operations, progress).Apply());
  649. }
  650. }
  651. TEST(TransformOperationTest, BlendSkewToEmpty) {
  652. TransformOperations empty_operation;
  653. TransformOperations operations;
  654. operations.AppendSkew(2, 2);
  655. SkScalar progress = 0.5f;
  656. gfx::Transform expected;
  657. expected.Skew(1, 1);
  658. EXPECT_TRANSFORM_EQ(expected,
  659. empty_operation.Blend(operations, progress).Apply());
  660. }
  661. TEST(TransformOperationTest, BlendPerspectiveToIdentity) {
  662. std::vector<std::unique_ptr<TransformOperations>> identity_operations =
  663. GetIdentityOperations();
  664. for (const auto& identity_operation : identity_operations) {
  665. TransformOperations operations;
  666. operations.AppendPerspective(1000);
  667. SkScalar progress = 0.5f;
  668. gfx::Transform expected;
  669. expected.ApplyPerspectiveDepth(2000);
  670. EXPECT_TRANSFORM_EQ(
  671. expected, identity_operation->Blend(operations, progress).Apply());
  672. }
  673. }
  674. TEST(TransformOperationTest, ExtrapolatePerspectiveBlending) {
  675. TransformOperations operations1;
  676. operations1.AppendPerspective(1000);
  677. TransformOperations operations2;
  678. operations2.AppendPerspective(500);
  679. gfx::Transform expected;
  680. expected.ApplyPerspectiveDepth(400);
  681. EXPECT_TRANSFORM_EQ(expected, operations1.Blend(operations2, -0.5).Apply());
  682. expected.MakeIdentity();
  683. expected.ApplyPerspectiveDepth(2000);
  684. EXPECT_TRANSFORM_EQ(expected, operations1.Blend(operations2, 1.5).Apply());
  685. }
  686. TEST(TransformOperationTest, ExtrapolateMatrixBlending) {
  687. gfx::Transform transform1;
  688. transform1.Translate3d(1, 1, 1);
  689. TransformOperations operations1;
  690. operations1.AppendMatrix(transform1);
  691. gfx::Transform transform2;
  692. transform2.Translate3d(3, 3, 3);
  693. TransformOperations operations2;
  694. operations2.AppendMatrix(transform2);
  695. gfx::Transform expected;
  696. EXPECT_TRANSFORM_EQ(expected, operations1.Blend(operations2, 1.5).Apply());
  697. expected.Translate3d(4, 4, 4);
  698. EXPECT_TRANSFORM_EQ(expected, operations1.Blend(operations2, -0.5).Apply());
  699. }
  700. TEST(TransformOperationTest, NonDecomposableBlend) {
  701. TransformOperations non_decomposible_transform;
  702. gfx::Transform non_decomposible_matrix(0, 0, 0, 0, 0, 0);
  703. non_decomposible_transform.AppendMatrix(non_decomposible_matrix);
  704. TransformOperations identity_transform;
  705. gfx::Transform identity_matrix;
  706. identity_transform.AppendMatrix(identity_matrix);
  707. // Before the half-way point, we should return the 'from' matrix.
  708. EXPECT_TRANSFORM_EQ(
  709. non_decomposible_matrix,
  710. identity_transform.Blend(non_decomposible_transform, 0.0f).Apply());
  711. EXPECT_TRANSFORM_EQ(
  712. non_decomposible_matrix,
  713. identity_transform.Blend(non_decomposible_transform, 0.49f).Apply());
  714. // After the half-way point, we should return the 'to' matrix.
  715. EXPECT_TRANSFORM_EQ(
  716. identity_matrix,
  717. identity_transform.Blend(non_decomposible_transform, 0.5f).Apply());
  718. EXPECT_TRANSFORM_EQ(
  719. identity_matrix,
  720. identity_transform.Blend(non_decomposible_transform, 1.0f).Apply());
  721. }
  722. TEST(TransformOperationTest, BlendedBoundsWhenTypesDoNotMatch) {
  723. TransformOperations operations_from;
  724. operations_from.AppendScale(2.0, 4.0, 8.0);
  725. operations_from.AppendTranslate(1.0, 2.0, 3.0);
  726. TransformOperations operations_to;
  727. operations_to.AppendTranslate(10.0, 20.0, 30.0);
  728. operations_to.AppendScale(4.0, 8.0, 16.0);
  729. gfx::BoxF box(1.f, 1.f, 1.f);
  730. gfx::BoxF bounds;
  731. SkScalar min_progress = 0.f;
  732. SkScalar max_progress = 1.f;
  733. EXPECT_FALSE(operations_to.BlendedBoundsForBox(
  734. box, operations_from, min_progress, max_progress, &bounds));
  735. }
  736. TEST(TransformOperationTest, BlendedBoundsForIdentity) {
  737. TransformOperations operations_from;
  738. operations_from.AppendIdentity();
  739. TransformOperations operations_to;
  740. operations_to.AppendIdentity();
  741. gfx::BoxF box(1.f, 2.f, 3.f);
  742. gfx::BoxF bounds;
  743. SkScalar min_progress = 0.f;
  744. SkScalar max_progress = 1.f;
  745. EXPECT_TRUE(operations_to.BlendedBoundsForBox(
  746. box, operations_from, min_progress, max_progress, &bounds));
  747. EXPECT_EQ(box.ToString(), bounds.ToString());
  748. }
  749. TEST(TransformOperationTest, BlendedBoundsForTranslate) {
  750. TransformOperations operations_from;
  751. operations_from.AppendTranslate(3.0, -4.0, 2.0);
  752. TransformOperations operations_to;
  753. operations_to.AppendTranslate(7.0, 4.0, -2.0);
  754. gfx::BoxF box(1.f, 2.f, 3.f, 4.f, 4.f, 4.f);
  755. gfx::BoxF bounds;
  756. SkScalar min_progress = -0.5f;
  757. SkScalar max_progress = 1.5f;
  758. EXPECT_TRUE(operations_to.BlendedBoundsForBox(
  759. box, operations_from, min_progress, max_progress, &bounds));
  760. EXPECT_EQ(gfx::BoxF(2.f, -6.f, -1.f, 12.f, 20.f, 12.f).ToString(),
  761. bounds.ToString());
  762. min_progress = 0.f;
  763. max_progress = 1.f;
  764. EXPECT_TRUE(operations_to.BlendedBoundsForBox(
  765. box, operations_from, min_progress, max_progress, &bounds));
  766. EXPECT_EQ(gfx::BoxF(4.f, -2.f, 1.f, 8.f, 12.f, 8.f).ToString(),
  767. bounds.ToString());
  768. TransformOperations identity;
  769. EXPECT_TRUE(operations_to.BlendedBoundsForBox(box, identity, min_progress,
  770. max_progress, &bounds));
  771. EXPECT_EQ(gfx::BoxF(1.f, 2.f, 1.f, 11.f, 8.f, 6.f).ToString(),
  772. bounds.ToString());
  773. EXPECT_TRUE(identity.BlendedBoundsForBox(box, operations_from, min_progress,
  774. max_progress, &bounds));
  775. EXPECT_EQ(gfx::BoxF(1.f, -2.f, 3.f, 7.f, 8.f, 6.f).ToString(),
  776. bounds.ToString());
  777. }
  778. TEST(TransformOperationTest, BlendedBoundsForScale) {
  779. TransformOperations operations_from;
  780. operations_from.AppendScale(3.0, 0.5, 2.0);
  781. TransformOperations operations_to;
  782. operations_to.AppendScale(7.0, 4.0, -2.0);
  783. gfx::BoxF box(1.f, 2.f, 3.f, 4.f, 4.f, 4.f);
  784. gfx::BoxF bounds;
  785. SkScalar min_progress = -0.5f;
  786. SkScalar max_progress = 1.5f;
  787. EXPECT_TRUE(operations_to.BlendedBoundsForBox(
  788. box, operations_from, min_progress, max_progress, &bounds));
  789. EXPECT_EQ(gfx::BoxF(1.f, -7.5f, -28.f, 44.f, 42.f, 56.f).ToString(),
  790. bounds.ToString());
  791. min_progress = 0.f;
  792. max_progress = 1.f;
  793. EXPECT_TRUE(operations_to.BlendedBoundsForBox(
  794. box, operations_from, min_progress, max_progress, &bounds));
  795. EXPECT_EQ(gfx::BoxF(3.f, 1.f, -14.f, 32.f, 23.f, 28.f).ToString(),
  796. bounds.ToString());
  797. TransformOperations identity;
  798. EXPECT_TRUE(operations_to.BlendedBoundsForBox(box, identity, min_progress,
  799. max_progress, &bounds));
  800. EXPECT_EQ(gfx::BoxF(1.f, 2.f, -14.f, 34.f, 22.f, 21.f).ToString(),
  801. bounds.ToString());
  802. EXPECT_TRUE(identity.BlendedBoundsForBox(box, operations_from, min_progress,
  803. max_progress, &bounds));
  804. EXPECT_EQ(gfx::BoxF(1.f, 1.f, 3.f, 14.f, 5.f, 11.f).ToString(),
  805. bounds.ToString());
  806. }
  807. TEST(TransformOperationTest, BlendedBoundsWithZeroScale) {
  808. TransformOperations zero_scale;
  809. zero_scale.AppendScale(0.0, 0.0, 0.0);
  810. TransformOperations non_zero_scale;
  811. non_zero_scale.AppendScale(2.0, -4.0, 5.0);
  812. gfx::BoxF box(1.f, 2.f, 3.f, 4.f, 4.f, 4.f);
  813. gfx::BoxF bounds;
  814. SkScalar min_progress = 0.f;
  815. SkScalar max_progress = 1.f;
  816. EXPECT_TRUE(zero_scale.BlendedBoundsForBox(box, non_zero_scale, min_progress,
  817. max_progress, &bounds));
  818. EXPECT_EQ(gfx::BoxF(0.f, -24.f, 0.f, 10.f, 24.f, 35.f).ToString(),
  819. bounds.ToString());
  820. EXPECT_TRUE(non_zero_scale.BlendedBoundsForBox(box, zero_scale, min_progress,
  821. max_progress, &bounds));
  822. EXPECT_EQ(gfx::BoxF(0.f, -24.f, 0.f, 10.f, 24.f, 35.f).ToString(),
  823. bounds.ToString());
  824. EXPECT_TRUE(zero_scale.BlendedBoundsForBox(box, zero_scale, min_progress,
  825. max_progress, &bounds));
  826. EXPECT_EQ(gfx::BoxF().ToString(), bounds.ToString());
  827. }
  828. TEST(TransformOperationTest, BlendedBoundsForRotationTrivial) {
  829. TransformOperations operations_from;
  830. operations_from.AppendRotate(0.f, 0.f, 1.f, 0.f);
  831. TransformOperations operations_to;
  832. operations_to.AppendRotate(0.f, 0.f, 1.f, 360.f);
  833. float sqrt_2 = sqrt(2.f);
  834. gfx::BoxF box(-sqrt_2, -sqrt_2, 0.f, sqrt_2, sqrt_2, 0.f);
  835. gfx::BoxF bounds;
  836. // Since we're rotating 360 degrees, any box with dimensions between 0 and
  837. // 2 * sqrt(2) should give the same result.
  838. float sizes[] = {0.f, 0.1f, sqrt_2, 2.f * sqrt_2};
  839. for (float size : sizes) {
  840. box.set_size(size, size, 0.f);
  841. SkScalar min_progress = 0.f;
  842. SkScalar max_progress = 1.f;
  843. EXPECT_TRUE(operations_to.BlendedBoundsForBox(
  844. box, operations_from, min_progress, max_progress, &bounds));
  845. EXPECT_EQ(gfx::BoxF(-2.f, -2.f, 0.f, 4.f, 4.f, 0.f).ToString(),
  846. bounds.ToString());
  847. }
  848. }
  849. TEST(TransformOperationTest, BlendedBoundsForRotationAllExtrema) {
  850. // If the normal is out of the plane, we can have up to 6 extrema (a min/max
  851. // in each dimension) between the endpoints of the arc. This test ensures that
  852. // we consider all 6.
  853. TransformOperations operations_from;
  854. operations_from.AppendRotate(1.f, 1.f, 1.f, 30.f);
  855. TransformOperations operations_to;
  856. operations_to.AppendRotate(1.f, 1.f, 1.f, 390.f);
  857. gfx::BoxF box(1.f, 0.f, 0.f, 0.f, 0.f, 0.f);
  858. gfx::BoxF bounds;
  859. float min = -1.f / 3.f;
  860. float max = 1.f;
  861. float size = max - min;
  862. EXPECT_TRUE(operations_to.BlendedBoundsForBox(box, operations_from, 0.f, 1.f,
  863. &bounds));
  864. EXPECT_EQ(gfx::BoxF(min, min, min, size, size, size).ToString(),
  865. bounds.ToString());
  866. }
  867. TEST(TransformOperationTest, BlendedBoundsForRotationDifferentAxes) {
  868. // We can handle rotations about a single axis. If the axes are different,
  869. // we revert to matrix interpolation for which inflated bounds cannot be
  870. // computed.
  871. TransformOperations operations_from;
  872. operations_from.AppendRotate(1.f, 1.f, 1.f, 30.f);
  873. TransformOperations operations_to_same;
  874. operations_to_same.AppendRotate(1.f, 1.f, 1.f, 390.f);
  875. TransformOperations operations_to_opposite;
  876. operations_to_opposite.AppendRotate(-1.f, -1.f, -1.f, 390.f);
  877. TransformOperations operations_to_different;
  878. operations_to_different.AppendRotate(1.f, 3.f, 1.f, 390.f);
  879. gfx::BoxF box(1.f, 0.f, 0.f, 0.f, 0.f, 0.f);
  880. gfx::BoxF bounds;
  881. EXPECT_TRUE(operations_to_same.BlendedBoundsForBox(box, operations_from, 0.f,
  882. 1.f, &bounds));
  883. EXPECT_TRUE(operations_to_opposite.BlendedBoundsForBox(box, operations_from,
  884. 0.f, 1.f, &bounds));
  885. EXPECT_FALSE(operations_to_different.BlendedBoundsForBox(box, operations_from,
  886. 0.f, 1.f, &bounds));
  887. }
  888. TEST(TransformOperationTest, BlendedBoundsForRotationPointOnAxis) {
  889. // Checks that if the point to rotate is sitting on the axis of rotation, that
  890. // it does not get affected.
  891. TransformOperations operations_from;
  892. operations_from.AppendRotate(1.f, 1.f, 1.f, 30.f);
  893. TransformOperations operations_to;
  894. operations_to.AppendRotate(1.f, 1.f, 1.f, 390.f);
  895. gfx::BoxF box(1.f, 1.f, 1.f, 0.f, 0.f, 0.f);
  896. gfx::BoxF bounds;
  897. EXPECT_TRUE(operations_to.BlendedBoundsForBox(box, operations_from, 0.f, 1.f,
  898. &bounds));
  899. EXPECT_EQ(box.ToString(), bounds.ToString());
  900. }
  901. TEST(TransformOperationTest, BlendedBoundsForRotationProblematicAxes) {
  902. // Zeros in the components of the axis of rotation turned out to be tricky to
  903. // deal with in practice. This function tests some potentially problematic
  904. // axes to ensure sane behavior.
  905. // Some common values used in the expected boxes.
  906. float dim1 = 0.292893f;
  907. float dim2 = sqrt(2.f);
  908. float dim3 = 2.f * dim2;
  909. struct {
  910. float x;
  911. float y;
  912. float z;
  913. gfx::BoxF expected;
  914. } tests[] = {{0.f, 0.f, 0.f, gfx::BoxF(1.f, 1.f, 1.f, 0.f, 0.f, 0.f)},
  915. {1.f, 0.f, 0.f, gfx::BoxF(1.f, -dim2, -dim2, 0.f, dim3, dim3)},
  916. {0.f, 1.f, 0.f, gfx::BoxF(-dim2, 1.f, -dim2, dim3, 0.f, dim3)},
  917. {0.f, 0.f, 1.f, gfx::BoxF(-dim2, -dim2, 1.f, dim3, dim3, 0.f)},
  918. {1.f, 1.f, 0.f, gfx::BoxF(dim1, dim1, -1.f, dim2, dim2, 2.f)},
  919. {0.f, 1.f, 1.f, gfx::BoxF(-1.f, dim1, dim1, 2.f, dim2, dim2)},
  920. {1.f, 0.f, 1.f, gfx::BoxF(dim1, -1.f, dim1, dim2, 2.f, dim2)}};
  921. for (const auto& test : tests) {
  922. float x = test.x;
  923. float y = test.y;
  924. float z = test.z;
  925. TransformOperations operations_from;
  926. operations_from.AppendRotate(x, y, z, 0.f);
  927. TransformOperations operations_to;
  928. operations_to.AppendRotate(x, y, z, 360.f);
  929. gfx::BoxF box(1.f, 1.f, 1.f, 0.f, 0.f, 0.f);
  930. gfx::BoxF bounds;
  931. EXPECT_TRUE(operations_to.BlendedBoundsForBox(box, operations_from, 0.f,
  932. 1.f, &bounds));
  933. EXPECT_EQ(test.expected.ToString(), bounds.ToString());
  934. }
  935. }
  936. static void ExpectBoxesApproximatelyEqual(const gfx::BoxF& lhs,
  937. const gfx::BoxF& rhs,
  938. float tolerance) {
  939. EXPECT_NEAR(lhs.x(), rhs.x(), tolerance);
  940. EXPECT_NEAR(lhs.y(), rhs.y(), tolerance);
  941. EXPECT_NEAR(lhs.z(), rhs.z(), tolerance);
  942. EXPECT_NEAR(lhs.width(), rhs.width(), tolerance);
  943. EXPECT_NEAR(lhs.height(), rhs.height(), tolerance);
  944. EXPECT_NEAR(lhs.depth(), rhs.depth(), tolerance);
  945. }
  946. static void EmpiricallyTestBounds(const TransformOperations& from,
  947. const TransformOperations& to,
  948. SkScalar min_progress,
  949. SkScalar max_progress,
  950. bool test_containment_only) {
  951. gfx::BoxF box(200.f, 500.f, 100.f, 100.f, 300.f, 200.f);
  952. gfx::BoxF bounds;
  953. EXPECT_TRUE(
  954. to.BlendedBoundsForBox(box, from, min_progress, max_progress, &bounds));
  955. bool first_time = true;
  956. gfx::BoxF empirical_bounds;
  957. static const size_t kNumSteps = 10;
  958. for (size_t step = 0; step < kNumSteps; ++step) {
  959. float t = step / (kNumSteps - 1.f);
  960. t = gfx::Tween::FloatValueBetween(t, min_progress, max_progress);
  961. gfx::Transform partial_transform = to.Blend(from, t).Apply();
  962. gfx::BoxF transformed = box;
  963. partial_transform.TransformBox(&transformed);
  964. if (first_time) {
  965. empirical_bounds = transformed;
  966. first_time = false;
  967. } else {
  968. empirical_bounds.Union(transformed);
  969. }
  970. }
  971. if (test_containment_only) {
  972. gfx::BoxF unified_bounds = bounds;
  973. unified_bounds.Union(empirical_bounds);
  974. // Convert to the screen space rects these boxes represent.
  975. gfx::Rect bounds_rect = ToEnclosingRect(
  976. gfx::RectF(bounds.x(), bounds.y(), bounds.width(), bounds.height()));
  977. gfx::Rect unified_bounds_rect = ToEnclosingRect(
  978. gfx::RectF(unified_bounds.x(), unified_bounds.y(),
  979. unified_bounds.width(), unified_bounds.height()));
  980. EXPECT_EQ(bounds_rect.ToString(), unified_bounds_rect.ToString());
  981. } else {
  982. // Our empirical estimate will be a little rough since we're only doing
  983. // 100 samples.
  984. static const float kTolerance = 1e-2f;
  985. ExpectBoxesApproximatelyEqual(empirical_bounds, bounds, kTolerance);
  986. }
  987. }
  988. static void EmpiricallyTestBoundsEquality(const TransformOperations& from,
  989. const TransformOperations& to,
  990. SkScalar min_progress,
  991. SkScalar max_progress) {
  992. EmpiricallyTestBounds(from, to, min_progress, max_progress, false);
  993. }
  994. static void EmpiricallyTestBoundsContainment(const TransformOperations& from,
  995. const TransformOperations& to,
  996. SkScalar min_progress,
  997. SkScalar max_progress) {
  998. EmpiricallyTestBounds(from, to, min_progress, max_progress, true);
  999. }
  1000. TEST(TransformOperationTest, BlendedBoundsForRotationEmpiricalTests) {
  1001. // Sets up various axis angle combinations, computes the bounding box and
  1002. // empirically tests that the transformed bounds are indeed contained by the
  1003. // computed bounding box.
  1004. struct {
  1005. float x;
  1006. float y;
  1007. float z;
  1008. } axes[] = {{1.f, 1.f, 1.f}, {-1.f, -1.f, -1.f}, {-1.f, 2.f, 3.f},
  1009. {1.f, -2.f, 3.f}, {1.f, 2.f, -3.f}, {0.f, 0.f, 0.f},
  1010. {1.f, 0.f, 0.f}, {0.f, 1.f, 0.f}, {0.f, 0.f, 1.f},
  1011. {1.f, 1.f, 0.f}, {0.f, 1.f, 1.f}, {1.f, 0.f, 1.f},
  1012. {-1.f, 0.f, 0.f}, {0.f, -1.f, 0.f}, {0.f, 0.f, -1.f},
  1013. {-1.f, -1.f, 0.f}, {0.f, -1.f, -1.f}, {-1.f, 0.f, -1.f}};
  1014. struct {
  1015. float theta_from;
  1016. float theta_to;
  1017. } angles[] = {{5.f, 10.f}, {10.f, 5.f}, {0.f, 360.f}, {20.f, 180.f},
  1018. {-20.f, -180.f}, {180.f, -220.f}, {220.f, 320.f}};
  1019. // We can go beyond the range [0, 1] (the bezier might slide out of this range
  1020. // at either end), but since the first and last knots are at (0, 0) and (1, 1)
  1021. // we will never go within it, so these tests are sufficient.
  1022. struct {
  1023. float min_progress;
  1024. float max_progress;
  1025. } progresses[] = {
  1026. {0.f, 1.f},
  1027. {-.25f, 1.25f},
  1028. };
  1029. for (const auto& axis : axes) {
  1030. for (const auto& angle : angles) {
  1031. for (const auto& progress : progresses) {
  1032. float x = axis.x;
  1033. float y = axis.y;
  1034. float z = axis.z;
  1035. TransformOperations operations_from;
  1036. operations_from.AppendRotate(x, y, z, angle.theta_from);
  1037. TransformOperations operations_to;
  1038. operations_to.AppendRotate(x, y, z, angle.theta_to);
  1039. EmpiricallyTestBoundsContainment(operations_from, operations_to,
  1040. progress.min_progress,
  1041. progress.max_progress);
  1042. }
  1043. }
  1044. }
  1045. }
  1046. TEST(TransformOperationTest, PerspectiveMatrixAndTransformBlendingEquivalency) {
  1047. TransformOperations from_operations;
  1048. from_operations.AppendPerspective(200);
  1049. TransformOperations to_operations;
  1050. to_operations.AppendPerspective(1000);
  1051. gfx::Transform from_transform;
  1052. from_transform.ApplyPerspectiveDepth(200);
  1053. gfx::Transform to_transform;
  1054. to_transform.ApplyPerspectiveDepth(1000);
  1055. static const int steps = 20;
  1056. for (int i = 0; i < steps; ++i) {
  1057. double progress = static_cast<double>(i) / (steps - 1);
  1058. gfx::Transform blended_matrix = to_transform;
  1059. EXPECT_TRUE(blended_matrix.Blend(from_transform, progress));
  1060. gfx::Transform blended_transform =
  1061. to_operations.Blend(from_operations, progress).Apply();
  1062. EXPECT_TRANSFORM_EQ(blended_matrix, blended_transform);
  1063. }
  1064. }
  1065. TEST(TransformOperationTest, BlendedBoundsForPerspective) {
  1066. struct {
  1067. float from_depth;
  1068. float to_depth;
  1069. } perspective_depths[] = {
  1070. {600.f, 400.f},
  1071. {800.f, 1000.f},
  1072. {800.f, std::numeric_limits<float>::infinity()},
  1073. };
  1074. struct {
  1075. float min_progress;
  1076. float max_progress;
  1077. } progresses[] = {
  1078. {0.f, 1.f},
  1079. {-0.1f, 1.1f},
  1080. };
  1081. for (const auto& perspective_depth : perspective_depths) {
  1082. for (const auto& progress : progresses) {
  1083. TransformOperations operations_from;
  1084. operations_from.AppendPerspective(perspective_depth.from_depth);
  1085. TransformOperations operations_to;
  1086. operations_to.AppendPerspective(perspective_depth.to_depth);
  1087. EmpiricallyTestBoundsEquality(operations_from, operations_to,
  1088. progress.min_progress,
  1089. progress.max_progress);
  1090. }
  1091. }
  1092. }
  1093. TEST(TransformOperationTest, BlendedBoundsForSkew) {
  1094. struct {
  1095. float from_x;
  1096. float from_y;
  1097. float to_x;
  1098. float to_y;
  1099. } skews[] = {
  1100. {1.f, 0.5f, 0.5f, 1.f},
  1101. {2.f, 1.f, 0.5f, 0.5f},
  1102. };
  1103. struct {
  1104. float min_progress;
  1105. float max_progress;
  1106. } progresses[] = {
  1107. {0.f, 1.f},
  1108. {-0.1f, 1.1f},
  1109. };
  1110. for (const auto& skew : skews) {
  1111. for (const auto& progress : progresses) {
  1112. TransformOperations operations_from;
  1113. operations_from.AppendSkew(skew.from_x, skew.from_y);
  1114. TransformOperations operations_to;
  1115. operations_to.AppendSkew(skew.to_x, skew.to_y);
  1116. EmpiricallyTestBoundsEquality(operations_from, operations_to,
  1117. progress.min_progress,
  1118. progress.max_progress);
  1119. }
  1120. }
  1121. }
  1122. TEST(TransformOperationTest, NonCommutativeRotations) {
  1123. TransformOperations operations_from;
  1124. operations_from.AppendRotate(1.0, 0.0, 0.0, 0.0);
  1125. operations_from.AppendRotate(0.0, 1.0, 0.0, 0.0);
  1126. TransformOperations operations_to;
  1127. operations_to.AppendRotate(1.0, 0.0, 0.0, 45.0);
  1128. operations_to.AppendRotate(0.0, 1.0, 0.0, 135.0);
  1129. gfx::BoxF box(0, 0, 0, 1, 1, 1);
  1130. gfx::BoxF bounds;
  1131. SkScalar min_progress = 0.0f;
  1132. SkScalar max_progress = 1.0f;
  1133. EXPECT_TRUE(operations_to.BlendedBoundsForBox(
  1134. box, operations_from, min_progress, max_progress, &bounds));
  1135. gfx::Transform blended_transform =
  1136. operations_to.Blend(operations_from, max_progress).Apply();
  1137. gfx::Point3F blended_point(0.9f, 0.9f, 0.0f);
  1138. blended_transform.TransformPoint(&blended_point);
  1139. gfx::BoxF expanded_bounds = bounds;
  1140. expanded_bounds.ExpandTo(blended_point);
  1141. EXPECT_EQ(bounds.ToString(), expanded_bounds.ToString());
  1142. }
  1143. TEST(TransformOperationTest, BlendedBoundsForSequence) {
  1144. TransformOperations operations_from;
  1145. operations_from.AppendTranslate(1.0, -5.0, 1.0);
  1146. operations_from.AppendScale(-1.0, 2.0, 3.0);
  1147. operations_from.AppendTranslate(2.0, 4.0, -1.0);
  1148. TransformOperations operations_to;
  1149. operations_to.AppendTranslate(13.0, -1.0, 5.0);
  1150. operations_to.AppendScale(-3.0, -2.0, 5.0);
  1151. operations_to.AppendTranslate(6.0, -2.0, 3.0);
  1152. gfx::BoxF box(1.f, 2.f, 3.f, 4.f, 4.f, 4.f);
  1153. gfx::BoxF bounds;
  1154. SkScalar min_progress = -0.5f;
  1155. SkScalar max_progress = 1.5f;
  1156. EXPECT_TRUE(operations_to.BlendedBoundsForBox(
  1157. box, operations_from, min_progress, max_progress, &bounds));
  1158. EXPECT_EQ(gfx::BoxF(-57.f, -59.f, -1.f, 76.f, 112.f, 80.f).ToString(),
  1159. bounds.ToString());
  1160. min_progress = 0.f;
  1161. max_progress = 1.f;
  1162. EXPECT_TRUE(operations_to.BlendedBoundsForBox(
  1163. box, operations_from, min_progress, max_progress, &bounds));
  1164. EXPECT_EQ(gfx::BoxF(-32.f, -25.f, 7.f, 42.f, 44.f, 48.f).ToString(),
  1165. bounds.ToString());
  1166. TransformOperations identity;
  1167. EXPECT_TRUE(operations_to.BlendedBoundsForBox(box, identity, min_progress,
  1168. max_progress, &bounds));
  1169. EXPECT_EQ(gfx::BoxF(-33.f, -13.f, 3.f, 57.f, 19.f, 52.f).ToString(),
  1170. bounds.ToString());
  1171. EXPECT_TRUE(identity.BlendedBoundsForBox(box, operations_from, min_progress,
  1172. max_progress, &bounds));
  1173. EXPECT_EQ(gfx::BoxF(-7.f, -3.f, 2.f, 15.f, 23.f, 20.f).ToString(),
  1174. bounds.ToString());
  1175. }
  1176. TEST(TransformOperationTest, IsTranslationWithSingleOperation) {
  1177. TransformOperations empty_operations;
  1178. EXPECT_TRUE(empty_operations.IsTranslation());
  1179. TransformOperations identity;
  1180. identity.AppendIdentity();
  1181. EXPECT_TRUE(identity.IsTranslation());
  1182. TransformOperations translate;
  1183. translate.AppendTranslate(1.f, 2.f, 3.f);
  1184. EXPECT_TRUE(translate.IsTranslation());
  1185. TransformOperations rotate;
  1186. rotate.AppendRotate(1.f, 2.f, 3.f, 4.f);
  1187. EXPECT_FALSE(rotate.IsTranslation());
  1188. TransformOperations scale;
  1189. scale.AppendScale(1.f, 2.f, 3.f);
  1190. EXPECT_FALSE(scale.IsTranslation());
  1191. TransformOperations skew;
  1192. skew.AppendSkew(1.f, 2.f);
  1193. EXPECT_FALSE(skew.IsTranslation());
  1194. TransformOperations perspective;
  1195. perspective.AppendPerspective(1.f);
  1196. EXPECT_FALSE(perspective.IsTranslation());
  1197. TransformOperations identity_matrix;
  1198. identity_matrix.AppendMatrix(gfx::Transform());
  1199. EXPECT_TRUE(identity_matrix.IsTranslation());
  1200. TransformOperations translation_matrix;
  1201. gfx::Transform translation_transform;
  1202. translation_transform.Translate3d(1.f, 2.f, 3.f);
  1203. translation_matrix.AppendMatrix(translation_transform);
  1204. EXPECT_TRUE(translation_matrix.IsTranslation());
  1205. TransformOperations scaling_matrix;
  1206. gfx::Transform scaling_transform;
  1207. scaling_transform.Scale(2.f, 2.f);
  1208. scaling_matrix.AppendMatrix(scaling_transform);
  1209. EXPECT_FALSE(scaling_matrix.IsTranslation());
  1210. }
  1211. TEST(TransformOperationTest, IsTranslationWithMultipleOperations) {
  1212. TransformOperations operations1;
  1213. operations1.AppendSkew(1.f, 2.f);
  1214. operations1.AppendTranslate(1.f, 2.f, 3.f);
  1215. operations1.AppendIdentity();
  1216. EXPECT_FALSE(operations1.IsTranslation());
  1217. TransformOperations operations2;
  1218. operations2.AppendIdentity();
  1219. operations2.AppendTranslate(3.f, 2.f, 1.f);
  1220. gfx::Transform translation_transform;
  1221. translation_transform.Translate3d(1.f, 2.f, 3.f);
  1222. operations2.AppendMatrix(translation_transform);
  1223. EXPECT_TRUE(operations2.IsTranslation());
  1224. }
  1225. TEST(TransformOperationTest, ScaleComponent) {
  1226. SkScalar scale;
  1227. // Scale.
  1228. TransformOperations operations1;
  1229. operations1.AppendScale(-3.f, 2.f, 5.f);
  1230. EXPECT_TRUE(operations1.ScaleComponent(&scale));
  1231. EXPECT_EQ(5.f, scale);
  1232. // Translate.
  1233. TransformOperations operations2;
  1234. operations2.AppendTranslate(1.f, 2.f, 3.f);
  1235. EXPECT_TRUE(operations2.ScaleComponent(&scale));
  1236. EXPECT_EQ(1.f, scale);
  1237. // Rotate.
  1238. TransformOperations operations3;
  1239. operations3.AppendRotate(1.f, 2.f, 3.f, 4.f);
  1240. EXPECT_TRUE(operations3.ScaleComponent(&scale));
  1241. EXPECT_EQ(1.f, scale);
  1242. // Matrix that's only a translation.
  1243. TransformOperations operations4;
  1244. gfx::Transform translation_transform;
  1245. translation_transform.Translate3d(1.f, 2.f, 3.f);
  1246. operations4.AppendMatrix(translation_transform);
  1247. EXPECT_TRUE(operations4.ScaleComponent(&scale));
  1248. EXPECT_EQ(1.f, scale);
  1249. // Matrix that includes scale.
  1250. TransformOperations operations5;
  1251. gfx::Transform matrix;
  1252. matrix.RotateAboutZAxis(30.0);
  1253. matrix.Scale(-7.f, 6.f);
  1254. matrix.Translate3d(gfx::Vector3dF(3.f, 7.f, 1.f));
  1255. operations5.AppendMatrix(matrix);
  1256. EXPECT_TRUE(operations5.ScaleComponent(&scale));
  1257. EXPECT_EQ(7.f, scale);
  1258. // Matrix with perspective.
  1259. TransformOperations operations6;
  1260. matrix.ApplyPerspectiveDepth(2000.f);
  1261. operations6.AppendMatrix(matrix);
  1262. EXPECT_FALSE(operations6.ScaleComponent(&scale));
  1263. // Skew.
  1264. TransformOperations operations7;
  1265. operations7.AppendSkew(30.f, 60.f);
  1266. EXPECT_TRUE(operations7.ScaleComponent(&scale));
  1267. EXPECT_EQ(2.f, scale);
  1268. // Perspective.
  1269. TransformOperations operations8;
  1270. operations8.AppendPerspective(500.f);
  1271. EXPECT_FALSE(operations8.ScaleComponent(&scale));
  1272. // Translate + Scale.
  1273. TransformOperations operations9;
  1274. operations9.AppendTranslate(1.f, 2.f, 3.f);
  1275. operations9.AppendScale(2.f, 5.f, 4.f);
  1276. EXPECT_TRUE(operations9.ScaleComponent(&scale));
  1277. EXPECT_EQ(5.f, scale);
  1278. // Translate + Scale + Matrix with translate.
  1279. operations9.AppendMatrix(translation_transform);
  1280. EXPECT_TRUE(operations9.ScaleComponent(&scale));
  1281. EXPECT_EQ(5.f, scale);
  1282. // Scale + translate.
  1283. TransformOperations operations10;
  1284. operations10.AppendScale(2.f, 3.f, 2.f);
  1285. operations10.AppendTranslate(1.f, 2.f, 3.f);
  1286. EXPECT_TRUE(operations10.ScaleComponent(&scale));
  1287. EXPECT_EQ(3.f, scale);
  1288. // Two Scales.
  1289. TransformOperations operations11;
  1290. operations11.AppendScale(2.f, 3.f, 2.f);
  1291. operations11.AppendScale(-3.f, -2.f, -3.f);
  1292. EXPECT_TRUE(operations11.ScaleComponent(&scale));
  1293. EXPECT_EQ(9.f, scale);
  1294. // Scale + Matrix.
  1295. TransformOperations operations12;
  1296. operations12.AppendScale(2.f, 2.f, 2.f);
  1297. gfx::Transform scaling_transform;
  1298. scaling_transform.Scale(2.f, 2.f);
  1299. operations12.AppendMatrix(scaling_transform);
  1300. EXPECT_TRUE(operations12.ScaleComponent(&scale));
  1301. EXPECT_EQ(4.f, scale);
  1302. // Scale + Rotate.
  1303. TransformOperations operations13;
  1304. operations13.AppendScale(2.f, 2.f, 2.f);
  1305. operations13.AppendRotate(1.f, 2.f, 3.f, 4.f);
  1306. EXPECT_TRUE(operations13.ScaleComponent(&scale));
  1307. EXPECT_EQ(2.f, scale);
  1308. // Scale + Skew.
  1309. TransformOperations operations14;
  1310. operations14.AppendScale(2.f, 2.f, 2.f);
  1311. operations14.AppendSkew(60.f, 45.f);
  1312. EXPECT_TRUE(operations14.ScaleComponent(&scale));
  1313. EXPECT_EQ(4.f, scale);
  1314. // Scale + Perspective.
  1315. TransformOperations operations15;
  1316. operations15.AppendScale(2.f, 2.f, 2.f);
  1317. operations15.AppendPerspective(1.f);
  1318. EXPECT_FALSE(operations15.ScaleComponent(&scale));
  1319. // Matrix with skew.
  1320. TransformOperations operations16;
  1321. gfx::Transform skew_transform;
  1322. skew_transform.Skew(50.f, 60.f);
  1323. operations16.AppendMatrix(skew_transform);
  1324. EXPECT_TRUE(operations16.ScaleComponent(&scale));
  1325. EXPECT_EQ(2.f, scale);
  1326. }
  1327. TEST(TransformOperationsTest, ApproximateEquality) {
  1328. float noise = 1e-7f;
  1329. float tolerance = 1e-5f;
  1330. TransformOperations lhs;
  1331. TransformOperations rhs;
  1332. // Empty lists of operations are trivially equal.
  1333. EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
  1334. rhs.AppendIdentity();
  1335. rhs.AppendTranslate(0, 0, 0);
  1336. rhs.AppendRotate(1, 0, 0, 0);
  1337. rhs.AppendScale(1, 1, 1);
  1338. rhs.AppendSkew(0, 0);
  1339. rhs.AppendMatrix(gfx::Transform());
  1340. // Even though both lists operations are effectively the identity matrix, rhs
  1341. // has a different number of operations and is therefore different.
  1342. EXPECT_FALSE(lhs.ApproximatelyEqual(rhs, tolerance));
  1343. rhs.AppendPerspective(800);
  1344. // Assignment should produce equal lists of operations.
  1345. lhs = rhs;
  1346. EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
  1347. // Cannot affect identity operations.
  1348. lhs.at(0).translate.x = 1;
  1349. EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
  1350. lhs.at(1).translate.x += noise;
  1351. EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
  1352. lhs.at(1).translate.x += 1;
  1353. EXPECT_FALSE(lhs.ApproximatelyEqual(rhs, tolerance));
  1354. lhs = rhs;
  1355. lhs.at(2).rotate.angle += noise;
  1356. EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
  1357. lhs.at(2).rotate.angle = 1;
  1358. EXPECT_FALSE(lhs.ApproximatelyEqual(rhs, tolerance));
  1359. lhs = rhs;
  1360. lhs.at(3).scale.x += noise;
  1361. EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
  1362. lhs.at(3).scale.x += 1;
  1363. EXPECT_FALSE(lhs.ApproximatelyEqual(rhs, tolerance));
  1364. lhs = rhs;
  1365. lhs.at(4).skew.x += noise;
  1366. EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
  1367. lhs.at(4).skew.x = 2;
  1368. EXPECT_FALSE(lhs.ApproximatelyEqual(rhs, tolerance));
  1369. lhs = rhs;
  1370. lhs.at(5).matrix.Translate3d(noise, 0, 0);
  1371. EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
  1372. lhs.at(5).matrix.Translate3d(1, 1, 1);
  1373. EXPECT_FALSE(lhs.ApproximatelyEqual(rhs, tolerance));
  1374. lhs = rhs;
  1375. lhs.at(6).perspective_m43 += noise;
  1376. EXPECT_TRUE(lhs.ApproximatelyEqual(rhs, tolerance));
  1377. lhs.at(6).perspective_m43 = -1.0f / 810;
  1378. EXPECT_FALSE(lhs.ApproximatelyEqual(rhs, tolerance));
  1379. }
  1380. } // namespace
  1381. // This test is intentionally outside the anonymous namespace for visibility as
  1382. // it needs to be friend of TransformOperations.
  1383. TEST(TransformOperationsTest, TestDecompositionCache) {
  1384. TransformOperations transforms;
  1385. EXPECT_EQ(0UL, transforms.decomposed_transforms_.size());
  1386. EXPECT_TRUE(transforms.ComputeDecomposedTransform(0));
  1387. EXPECT_EQ(1UL, transforms.decomposed_transforms_.size());
  1388. // Reset cache when appending a scale transform.
  1389. transforms.AppendScale(2.f, 2.f, 2.f);
  1390. EXPECT_EQ(0UL, transforms.decomposed_transforms_.size());
  1391. EXPECT_TRUE(transforms.ComputeDecomposedTransform(1));
  1392. EXPECT_EQ(1UL, transforms.decomposed_transforms_.size());
  1393. EXPECT_TRUE(transforms.ComputeDecomposedTransform(1));
  1394. EXPECT_EQ(1UL, transforms.decomposed_transforms_.size());
  1395. EXPECT_TRUE(transforms.ComputeDecomposedTransform(0));
  1396. EXPECT_EQ(2UL, transforms.decomposed_transforms_.size());
  1397. // Reset cache when appending a rotation transform.
  1398. transforms.AppendRotate(1, 0, 0, 45);
  1399. EXPECT_EQ(0UL, transforms.decomposed_transforms_.size());
  1400. EXPECT_TRUE(transforms.ComputeDecomposedTransform(0));
  1401. EXPECT_EQ(1UL, transforms.decomposed_transforms_.size());
  1402. // Reset cache when appending a translation transform.
  1403. transforms.AppendTranslate(1, 1, 1);
  1404. EXPECT_EQ(0UL, transforms.decomposed_transforms_.size());
  1405. EXPECT_TRUE(transforms.ComputeDecomposedTransform(0));
  1406. EXPECT_EQ(1UL, transforms.decomposed_transforms_.size());
  1407. // Reset cache when appending a skew transform.
  1408. transforms.AppendSkew(1, 0);
  1409. EXPECT_EQ(0UL, transforms.decomposed_transforms_.size());
  1410. EXPECT_TRUE(transforms.ComputeDecomposedTransform(0));
  1411. EXPECT_EQ(1UL, transforms.decomposed_transforms_.size());
  1412. // Reset cache when appending a perspective transform.
  1413. transforms.AppendPerspective(800);
  1414. EXPECT_EQ(0UL, transforms.decomposed_transforms_.size());
  1415. EXPECT_TRUE(transforms.ComputeDecomposedTransform(0));
  1416. EXPECT_EQ(1UL, transforms.decomposed_transforms_.size());
  1417. // Reset cache when appending a matrix transform.
  1418. transforms.AppendMatrix(gfx::Transform());
  1419. EXPECT_EQ(0UL, transforms.decomposed_transforms_.size());
  1420. EXPECT_TRUE(transforms.ComputeDecomposedTransform(0));
  1421. EXPECT_EQ(1UL, transforms.decomposed_transforms_.size());
  1422. // Reset cache when appending a generic transform operation.
  1423. transforms.Append(TransformOperation());
  1424. EXPECT_EQ(0UL, transforms.decomposed_transforms_.size());
  1425. EXPECT_TRUE(transforms.ComputeDecomposedTransform(0));
  1426. EXPECT_EQ(1UL, transforms.decomposed_transforms_.size());
  1427. }
  1428. TEST(TransformOperationTest, BlendSkewMismatch) {
  1429. TransformOperations from_ops, to_ops, expected_ops;
  1430. from_ops.AppendSkewX(0);
  1431. from_ops.AppendRotate(0, 0, 1, 0);
  1432. to_ops.AppendSkewY(0);
  1433. to_ops.AppendRotate(0, 0, 1, 360);
  1434. // Skew types do not match so use matrix interpolation
  1435. expected_ops.AppendMatrix(gfx::Transform());
  1436. TransformOperations blended_ops = to_ops.Blend(from_ops, 0.5);
  1437. ASSERT_EQ(blended_ops.size(), 1u);
  1438. ExpectTransformOperationEqual(blended_ops.at(0), expected_ops.at(0));
  1439. }
  1440. TEST(TransformOperationTest, BlendSkewMatch) {
  1441. TransformOperations from_ops, to_ops, expected_ops;
  1442. from_ops.AppendSkew(30, 0);
  1443. from_ops.AppendRotate(0, 0, 1, 0);
  1444. to_ops.AppendSkew(0, 30);
  1445. to_ops.AppendRotate(0, 0, 1, 360);
  1446. // Skew types match so interpolate as a function.
  1447. expected_ops.AppendSkew(15, 15);
  1448. expected_ops.AppendRotate(0, 0, 1, 180);
  1449. TransformOperations blended_ops = to_ops.Blend(from_ops, 0.5);
  1450. ASSERT_EQ(blended_ops.size(), 2u);
  1451. ExpectTransformOperationEqual(blended_ops.at(0), expected_ops.at(0));
  1452. ExpectTransformOperationEqual(blended_ops.at(1), expected_ops.at(1));
  1453. }
  1454. } // namespace gfx