display_item_list_unittest.cc 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202
  1. // Copyright 2014 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 "cc/paint/display_item_list.h"
  5. #include <stddef.h>
  6. #include <vector>
  7. #include "base/logging.h"
  8. #include "base/trace_event/traced_value.h"
  9. #include "base/values.h"
  10. #include "cc/paint/filter_operation.h"
  11. #include "cc/paint/filter_operations.h"
  12. #include "cc/paint/paint_canvas.h"
  13. #include "cc/paint/paint_flags.h"
  14. #include "cc/paint/paint_image_builder.h"
  15. #include "cc/paint/paint_record.h"
  16. #include "cc/paint/render_surface_filters.h"
  17. #include "cc/paint/skia_paint_canvas.h"
  18. #include "cc/test/pixel_test_utils.h"
  19. #include "cc/test/skia_common.h"
  20. #include "cc/test/test_skcanvas.h"
  21. #include "testing/gmock/include/gmock/gmock.h"
  22. #include "testing/gtest/include/gtest/gtest.h"
  23. #include "third_party/skia/include/core/SkBitmap.h"
  24. #include "third_party/skia/include/core/SkColor.h"
  25. #include "third_party/skia/include/core/SkSurface.h"
  26. #include "third_party/skia/include/core/SkTextBlob.h"
  27. #include "ui/gfx/geometry/rect.h"
  28. #include "ui/gfx/geometry/rect_conversions.h"
  29. #include "ui/gfx/geometry/skia_conversions.h"
  30. #include "ui/gfx/geometry/transform.h"
  31. namespace cc {
  32. namespace {
  33. bool CompareN32Pixels(void* actual_pixels,
  34. void* expected_pixels,
  35. int width,
  36. int height) {
  37. if (memcmp(actual_pixels, expected_pixels, 4 * width * height) == 0)
  38. return true;
  39. SkImageInfo actual_info = SkImageInfo::MakeN32Premul(width, height);
  40. SkBitmap actual_bitmap;
  41. actual_bitmap.installPixels(actual_info, actual_pixels,
  42. actual_info.minRowBytes());
  43. SkImageInfo expected_info = SkImageInfo::MakeN32Premul(width, height);
  44. SkBitmap expected_bitmap;
  45. expected_bitmap.installPixels(expected_info, expected_pixels,
  46. expected_info.minRowBytes());
  47. std::string gen_bmp_data_url = GetPNGDataUrl(actual_bitmap);
  48. std::string ref_bmp_data_url = GetPNGDataUrl(expected_bitmap);
  49. LOG(ERROR) << "Pixels do not match!";
  50. LOG(ERROR) << "Actual: " << gen_bmp_data_url;
  51. LOG(ERROR) << "Expected: " << ref_bmp_data_url;
  52. return false;
  53. }
  54. } // namespace
  55. class DisplayItemListTest : public testing::Test {
  56. protected:
  57. std::unique_ptr<base::Value> ToBaseValue(const DisplayItemList* list,
  58. bool include_items) {
  59. base::trace_event::TracedValueJSON value;
  60. list->AddToValue(&value, include_items);
  61. return value.ToBaseValue();
  62. }
  63. };
  64. #define EXPECT_TRACED_RECT(x, y, width, height, rect_list) \
  65. do { \
  66. ASSERT_EQ(4u, rect_list->size()); \
  67. EXPECT_EQ(x, (*rect_list)[0].GetIfDouble()); \
  68. EXPECT_EQ(y, (*rect_list)[1].GetIfDouble()); \
  69. EXPECT_EQ(width, (*rect_list)[2].GetIfDouble()); \
  70. EXPECT_EQ(height, (*rect_list)[3].GetIfDouble()); \
  71. } while (false)
  72. // AddToValue should not crash if there are different numbers of visual_rect
  73. // are paint_op
  74. TEST_F(DisplayItemListTest, TraceEmptyVisualRect) {
  75. PaintFlags red_paint;
  76. red_paint.setColor(SK_ColorRED);
  77. auto list = base::MakeRefCounted<DisplayItemList>();
  78. gfx::Point offset(8, 9);
  79. list->StartPaint();
  80. list->push<DrawRectOp>(SkRect::MakeEmpty(), red_paint);
  81. // The rect is empty to cause rtree generation to skip it.
  82. list->EndPaintOfUnpaired(gfx::Rect(offset, gfx::Size(0, 10)));
  83. list->StartPaint();
  84. list->push<DrawRectOp>(SkRect::MakeXYWH(0, 0, 10, 10), red_paint);
  85. // This rect is not empty.
  86. list->EndPaintOfUnpaired(gfx::Rect(offset, gfx::Size(10, 10)));
  87. list->Finalize();
  88. // Pass: we don't crash
  89. std::unique_ptr<base::Value> root = ToBaseValue(list.get(), true);
  90. const base::Value::Dict* root_dict = root->GetIfDict();
  91. ASSERT_NE(nullptr, root_dict);
  92. const base::Value::Dict* params_dict = root_dict->FindDict("params");
  93. ASSERT_NE(nullptr, params_dict);
  94. const base::Value::List* items = params_dict->FindList("items");
  95. ASSERT_NE(nullptr, items);
  96. ASSERT_EQ(2u, items->size());
  97. const base::Value::Dict* item_dict;
  98. const base::Value::List* visual_rect;
  99. const std::string* name;
  100. item_dict = ((*items)[0]).GetIfDict();
  101. ASSERT_NE(nullptr, item_dict);
  102. visual_rect = item_dict->FindList("visual_rect");
  103. ASSERT_NE(nullptr, visual_rect);
  104. EXPECT_TRACED_RECT(0, 0, 0, 0, visual_rect);
  105. name = item_dict->FindString("name");
  106. ASSERT_NE(nullptr, name);
  107. EXPECT_EQ("DrawRect", *name);
  108. item_dict = ((*items)[1]).GetIfDict();
  109. ASSERT_NE(nullptr, item_dict);
  110. visual_rect = item_dict->FindList("visual_rect");
  111. ASSERT_NE(nullptr, visual_rect);
  112. EXPECT_TRACED_RECT(8, 9, 10, 10, visual_rect);
  113. name = item_dict->FindString("name");
  114. ASSERT_NE(nullptr, name);
  115. EXPECT_EQ("DrawRect", *name);
  116. }
  117. TEST_F(DisplayItemListTest, SingleUnpairedRange) {
  118. gfx::Rect layer_rect(100, 100);
  119. PaintFlags blue_flags;
  120. blue_flags.setColor(SK_ColorBLUE);
  121. PaintFlags red_paint;
  122. red_paint.setColor(SK_ColorRED);
  123. unsigned char pixels[4 * 100 * 100] = {0};
  124. auto list = base::MakeRefCounted<DisplayItemList>();
  125. gfx::Point offset(8, 9);
  126. list->StartPaint();
  127. list->push<SaveOp>();
  128. list->push<TranslateOp>(static_cast<float>(offset.x()),
  129. static_cast<float>(offset.y()));
  130. list->push<DrawRectOp>(SkRect::MakeLTRB(0.f, 0.f, 60.f, 60.f), red_paint);
  131. list->push<DrawRectOp>(SkRect::MakeLTRB(50.f, 50.f, 75.f, 75.f), blue_flags);
  132. list->push<RestoreOp>();
  133. list->EndPaintOfUnpaired(gfx::Rect(offset, layer_rect.size()));
  134. list->Finalize();
  135. DrawDisplayList(pixels, layer_rect, list);
  136. SkBitmap expected_bitmap;
  137. unsigned char expected_pixels[4 * 100 * 100] = {0};
  138. SkImageInfo info =
  139. SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height());
  140. expected_bitmap.installPixels(info, expected_pixels, info.minRowBytes());
  141. SkiaPaintCanvas expected_canvas(expected_bitmap);
  142. expected_canvas.clipRect(gfx::RectToSkRect(layer_rect));
  143. expected_canvas.drawRect(
  144. SkRect::MakeLTRB(0.f + offset.x(), 0.f + offset.y(), 60.f + offset.x(),
  145. 60.f + offset.y()),
  146. red_paint);
  147. expected_canvas.drawRect(
  148. SkRect::MakeLTRB(50.f + offset.x(), 50.f + offset.y(), 75.f + offset.x(),
  149. 75.f + offset.y()),
  150. blue_flags);
  151. EXPECT_TRUE(CompareN32Pixels(pixels, expected_pixels, 100, 100));
  152. }
  153. TEST_F(DisplayItemListTest, EmptyUnpairedRangeDoesNotAddVisualRect) {
  154. gfx::Rect layer_rect(100, 100);
  155. auto list = base::MakeRefCounted<DisplayItemList>();
  156. {
  157. list->StartPaint();
  158. list->EndPaintOfUnpaired(layer_rect);
  159. }
  160. // No ops.
  161. EXPECT_EQ(0u, list->TotalOpCount());
  162. {
  163. list->StartPaint();
  164. list->push<SaveOp>();
  165. list->push<RestoreOp>();
  166. list->EndPaintOfUnpaired(layer_rect);
  167. }
  168. // Two ops.
  169. EXPECT_EQ(2u, list->TotalOpCount());
  170. }
  171. TEST_F(DisplayItemListTest, ClipPairedRange) {
  172. gfx::Rect layer_rect(100, 100);
  173. PaintFlags blue_flags;
  174. blue_flags.setColor(SK_ColorBLUE);
  175. PaintFlags red_paint;
  176. red_paint.setColor(SK_ColorRED);
  177. unsigned char pixels[4 * 100 * 100] = {0};
  178. auto list = base::MakeRefCounted<DisplayItemList>();
  179. gfx::Point first_offset(8, 9);
  180. gfx::Rect first_recording_rect(first_offset, layer_rect.size());
  181. {
  182. list->StartPaint();
  183. list->push<SaveOp>();
  184. list->push<TranslateOp>(static_cast<float>(first_offset.x()),
  185. static_cast<float>(first_offset.y()));
  186. list->push<DrawRectOp>(SkRect::MakeWH(60, 60), red_paint);
  187. list->push<RestoreOp>();
  188. list->EndPaintOfUnpaired(first_recording_rect);
  189. }
  190. gfx::Rect clip_rect(60, 60, 10, 10);
  191. {
  192. list->StartPaint();
  193. list->push<SaveOp>();
  194. list->push<ClipRectOp>(gfx::RectToSkRect(clip_rect), SkClipOp::kIntersect,
  195. true);
  196. list->EndPaintOfPairedBegin();
  197. }
  198. gfx::Point second_offset(2, 3);
  199. gfx::Rect second_recording_rect(second_offset, layer_rect.size());
  200. {
  201. list->StartPaint();
  202. list->push<SaveOp>();
  203. list->push<TranslateOp>(static_cast<float>(second_offset.x()),
  204. static_cast<float>(second_offset.y()));
  205. list->push<DrawRectOp>(SkRect::MakeLTRB(50.f, 50.f, 75.f, 75.f),
  206. blue_flags);
  207. list->push<RestoreOp>();
  208. list->EndPaintOfUnpaired(second_recording_rect);
  209. }
  210. {
  211. list->StartPaint();
  212. list->push<RestoreOp>();
  213. list->EndPaintOfPairedEnd();
  214. }
  215. list->Finalize();
  216. DrawDisplayList(pixels, layer_rect, list);
  217. SkBitmap expected_bitmap;
  218. unsigned char expected_pixels[4 * 100 * 100] = {0};
  219. SkImageInfo info =
  220. SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height());
  221. expected_bitmap.installPixels(info, expected_pixels, info.minRowBytes());
  222. SkiaPaintCanvas expected_canvas(expected_bitmap);
  223. expected_canvas.clipRect(gfx::RectToSkRect(layer_rect));
  224. expected_canvas.drawRect(
  225. SkRect::MakeLTRB(0.f + first_offset.x(), 0.f + first_offset.y(),
  226. 60.f + first_offset.x(), 60.f + first_offset.y()),
  227. red_paint);
  228. expected_canvas.clipRect(gfx::RectToSkRect(clip_rect));
  229. expected_canvas.drawRect(
  230. SkRect::MakeLTRB(50.f + second_offset.x(), 50.f + second_offset.y(),
  231. 75.f + second_offset.x(), 75.f + second_offset.y()),
  232. blue_flags);
  233. EXPECT_TRUE(CompareN32Pixels(pixels, expected_pixels, 100, 100));
  234. }
  235. TEST_F(DisplayItemListTest, TransformPairedRange) {
  236. gfx::Rect layer_rect(100, 100);
  237. PaintFlags blue_flags;
  238. blue_flags.setColor(SK_ColorBLUE);
  239. PaintFlags red_paint;
  240. red_paint.setColor(SK_ColorRED);
  241. unsigned char pixels[4 * 100 * 100] = {0};
  242. auto list = base::MakeRefCounted<DisplayItemList>();
  243. gfx::Point first_offset(8, 9);
  244. gfx::Rect first_recording_rect(first_offset, layer_rect.size());
  245. {
  246. list->StartPaint();
  247. list->push<SaveOp>();
  248. list->push<TranslateOp>(static_cast<float>(first_offset.x()),
  249. static_cast<float>(first_offset.y()));
  250. list->push<DrawRectOp>(SkRect::MakeWH(60, 60), red_paint);
  251. list->push<RestoreOp>();
  252. list->EndPaintOfUnpaired(first_recording_rect);
  253. }
  254. gfx::Transform transform;
  255. transform.Rotate(45.0);
  256. {
  257. list->StartPaint();
  258. list->push<SaveOp>();
  259. list->push<ConcatOp>(transform.GetMatrixAsSkM44());
  260. list->EndPaintOfPairedBegin();
  261. }
  262. gfx::Point second_offset(2, 3);
  263. gfx::Rect second_recording_rect(second_offset, layer_rect.size());
  264. {
  265. list->StartPaint();
  266. list->push<SaveOp>();
  267. list->push<TranslateOp>(static_cast<float>(second_offset.x()),
  268. static_cast<float>(second_offset.y()));
  269. list->push<DrawRectOp>(SkRect::MakeLTRB(50.f, 50.f, 75.f, 75.f),
  270. blue_flags);
  271. list->push<RestoreOp>();
  272. list->EndPaintOfUnpaired(second_recording_rect);
  273. }
  274. {
  275. list->StartPaint();
  276. list->push<RestoreOp>();
  277. list->EndPaintOfPairedEnd();
  278. }
  279. list->Finalize();
  280. DrawDisplayList(pixels, layer_rect, list);
  281. SkBitmap expected_bitmap;
  282. unsigned char expected_pixels[4 * 100 * 100] = {0};
  283. SkImageInfo info =
  284. SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height());
  285. expected_bitmap.installPixels(info, expected_pixels, info.minRowBytes());
  286. SkiaPaintCanvas expected_canvas(expected_bitmap);
  287. expected_canvas.clipRect(gfx::RectToSkRect(layer_rect));
  288. expected_canvas.drawRect(
  289. SkRect::MakeLTRB(0.f + first_offset.x(), 0.f + first_offset.y(),
  290. 60.f + first_offset.x(), 60.f + first_offset.y()),
  291. red_paint);
  292. expected_canvas.setMatrix(transform.matrix().asM33());
  293. expected_canvas.drawRect(
  294. SkRect::MakeLTRB(50.f + second_offset.x(), 50.f + second_offset.y(),
  295. 75.f + second_offset.x(), 75.f + second_offset.y()),
  296. blue_flags);
  297. EXPECT_TRUE(CompareN32Pixels(pixels, expected_pixels, 100, 100));
  298. }
  299. TEST_F(DisplayItemListTest, FilterPairedRange) {
  300. gfx::Rect layer_rect(100, 100);
  301. FilterOperations filters;
  302. unsigned char pixels[4 * 100 * 100] = {0};
  303. auto list = base::MakeRefCounted<DisplayItemList>();
  304. sk_sp<SkSurface> source_surface = SkSurface::MakeRasterN32Premul(50, 50);
  305. SkCanvas* source_canvas = source_surface->getCanvas();
  306. source_canvas->clear(SkColorSetRGB(128, 128, 128));
  307. PaintImage source_image = PaintImageBuilder::WithDefault()
  308. .set_id(PaintImage::GetNextId())
  309. .set_image(source_surface->makeImageSnapshot(),
  310. PaintImage::GetNextContentId())
  311. .TakePaintImage();
  312. // For most SkImageFilters, the |dst| bounds computed by computeFastBounds are
  313. // dependent on the provided |src| bounds. This means, for example, that
  314. // translating |src| results in a corresponding translation of |dst|. But this
  315. // is not the case for all SkImageFilters; for some of them (e.g.
  316. // SkImageSource), the computation of |dst| in computeFastBounds doesn't
  317. // involve |src| at all. Incorrectly assuming such a relationship (e.g. by
  318. // translating |dst| after it is computed by computeFastBounds, rather than
  319. // translating |src| before it provided to computedFastBounds) can cause
  320. // incorrect clipping of filter output. To test for this, we include an
  321. // SkImageSource filter in |filters|. Here, |src| is |filter_bounds|, defined
  322. // below.
  323. SkRect rect = SkRect::MakeWH(source_image.width(), source_image.height());
  324. sk_sp<PaintFilter> image_filter = sk_make_sp<ImagePaintFilter>(
  325. source_image, rect, rect, PaintFlags::FilterQuality::kHigh);
  326. filters.Append(FilterOperation::CreateReferenceFilter(image_filter));
  327. filters.Append(FilterOperation::CreateBrightnessFilter(0.5f));
  328. gfx::RectF filter_bounds(10.f, 10.f, 50.f, 50.f);
  329. {
  330. list->StartPaint();
  331. list->push<SaveOp>();
  332. list->push<TranslateOp>(filter_bounds.x(), filter_bounds.y());
  333. PaintFlags flags;
  334. flags.setImageFilter(
  335. RenderSurfaceFilters::BuildImageFilter(filters, filter_bounds.size()));
  336. SkRect layer_bounds = gfx::RectFToSkRect(filter_bounds);
  337. layer_bounds.offset(-filter_bounds.x(), -filter_bounds.y());
  338. list->push<SaveLayerOp>(&layer_bounds, &flags);
  339. list->push<TranslateOp>(-filter_bounds.x(), -filter_bounds.y());
  340. list->EndPaintOfPairedBegin();
  341. }
  342. // Include a rect drawing so that filter is actually applied to something.
  343. {
  344. list->StartPaint();
  345. PaintFlags red_flags;
  346. red_flags.setColor(SK_ColorRED);
  347. list->push<DrawRectOp>(
  348. SkRect::MakeLTRB(filter_bounds.x(), filter_bounds.y(),
  349. filter_bounds.right(), filter_bounds.bottom()),
  350. red_flags);
  351. list->EndPaintOfUnpaired(ToEnclosingRect(filter_bounds));
  352. }
  353. {
  354. list->StartPaint();
  355. list->push<RestoreOp>(); // For SaveLayerOp.
  356. list->push<RestoreOp>(); // For SaveOp.
  357. list->EndPaintOfPairedEnd();
  358. }
  359. list->Finalize();
  360. DrawDisplayList(pixels, layer_rect, list);
  361. SkBitmap expected_bitmap;
  362. unsigned char expected_pixels[4 * 100 * 100] = {0};
  363. PaintFlags paint;
  364. paint.setColor(SkColorSetRGB(64, 64, 64));
  365. SkImageInfo info =
  366. SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height());
  367. expected_bitmap.installPixels(info, expected_pixels, info.minRowBytes());
  368. SkiaPaintCanvas expected_canvas(expected_bitmap);
  369. expected_canvas.drawRect(RectFToSkRect(filter_bounds), paint);
  370. EXPECT_TRUE(CompareN32Pixels(pixels, expected_pixels, 100, 100));
  371. }
  372. TEST_F(DisplayItemListTest, BytesUsed) {
  373. const int kNumPaintOps = 1000;
  374. size_t memory_usage;
  375. auto list = base::MakeRefCounted<DisplayItemList>();
  376. gfx::Rect layer_rect(100, 100);
  377. PaintFlags blue_flags;
  378. blue_flags.setColor(SK_ColorBLUE);
  379. {
  380. list->StartPaint();
  381. for (int i = 0; i < kNumPaintOps; i++)
  382. list->push<DrawRectOp>(SkRect::MakeWH(1, 1), blue_flags);
  383. list->EndPaintOfUnpaired(layer_rect);
  384. }
  385. memory_usage = list->BytesUsed();
  386. EXPECT_GE(memory_usage, sizeof(DrawRectOp) * kNumPaintOps);
  387. EXPECT_LE(memory_usage, 2 * sizeof(DrawRectOp) * kNumPaintOps);
  388. }
  389. TEST_F(DisplayItemListTest, AsValueWithNoOps) {
  390. auto list = base::MakeRefCounted<DisplayItemList>();
  391. list->Finalize();
  392. // Pass |true| to ask for PaintOps even though there are none.
  393. std::unique_ptr<base::Value> root = ToBaseValue(list.get(), true);
  394. const base::Value::Dict* root_dict = root->GetIfDict();
  395. ASSERT_NE(nullptr, root_dict);
  396. // The traced value has a params dictionary as its root.
  397. {
  398. const base::Value::Dict* params_dict = root_dict->FindDict("params");
  399. ASSERT_NE(nullptr, params_dict);
  400. // The real contents of the traced value is in here.
  401. {
  402. const base::Value::List* params_list;
  403. // The layer_rect field is present by empty.
  404. params_list = params_dict->FindList("layer_rect");
  405. ASSERT_NE(nullptr, params_list);
  406. EXPECT_TRACED_RECT(0, 0, 0, 0, params_list);
  407. // The items list is there but empty.
  408. params_list = params_dict->FindList("items");
  409. ASSERT_NE(nullptr, params_list);
  410. EXPECT_EQ(0u, params_list->size());
  411. }
  412. }
  413. // Pass |false| to not include PaintOps.
  414. root = ToBaseValue(list.get(), false);
  415. root_dict = root->GetIfDict();
  416. ASSERT_NE(nullptr, root_dict);
  417. // The traced value has a params dictionary as its root.
  418. {
  419. const base::Value::Dict* params_dict = root_dict->FindDict("params");
  420. ASSERT_NE(nullptr, params_dict);
  421. // The real contents of the traced value is in here.
  422. {
  423. const base::Value::List* params_list;
  424. // The layer_rect field is present by empty.
  425. params_list = params_dict->FindList("layer_rect");
  426. ASSERT_NE(nullptr, params_list);
  427. EXPECT_TRACED_RECT(0, 0, 0, 0, params_list);
  428. // The items list is not there since we asked for no ops.
  429. params_list = params_dict->FindList("items");
  430. ASSERT_EQ(nullptr, params_list);
  431. }
  432. }
  433. }
  434. TEST_F(DisplayItemListTest, AsValueWithOps) {
  435. gfx::Rect layer_rect = gfx::Rect(1, 2, 8, 9);
  436. auto list = base::MakeRefCounted<DisplayItemList>();
  437. gfx::Transform transform;
  438. transform.Translate(6.f, 7.f);
  439. {
  440. list->StartPaint();
  441. list->push<SaveOp>();
  442. list->push<ConcatOp>(transform.GetMatrixAsSkM44());
  443. list->EndPaintOfPairedBegin();
  444. }
  445. gfx::Point offset(2, 3);
  446. gfx::Rect bounds(offset, layer_rect.size());
  447. {
  448. list->StartPaint();
  449. PaintFlags red_paint;
  450. red_paint.setColor(SK_ColorRED);
  451. list->push<SaveLayerOp>(nullptr, &red_paint);
  452. list->push<TranslateOp>(static_cast<float>(offset.x()),
  453. static_cast<float>(offset.y()));
  454. list->push<DrawRectOp>(SkRect::MakeWH(4, 4), red_paint);
  455. list->push<RestoreOp>();
  456. list->EndPaintOfUnpaired(bounds);
  457. }
  458. {
  459. list->StartPaint();
  460. list->push<RestoreOp>();
  461. list->EndPaintOfPairedEnd();
  462. }
  463. list->Finalize();
  464. // Pass |true| to ask for PaintOps to be included.
  465. std::unique_ptr<base::Value> root = ToBaseValue(list.get(), true);
  466. const base::Value::Dict* root_dict = root->GetIfDict();
  467. ASSERT_NE(nullptr, root_dict);
  468. // The traced value has a params dictionary as its root.
  469. {
  470. const base::Value::Dict* params_dict = root_dict->FindDict("params");
  471. ASSERT_NE(nullptr, params_dict);
  472. // The real contents of the traced value is in here.
  473. {
  474. const base::Value::List* layer_rect_list =
  475. params_dict->FindList("layer_rect");
  476. // The layer_rect field is present and has the bounds of the rtree.
  477. ASSERT_NE(nullptr, layer_rect_list);
  478. EXPECT_TRACED_RECT(2, 3, 8, 9, layer_rect_list);
  479. // The items list has 3 things in it since we built 3 visual rects.
  480. const base::Value::List* items = params_dict->FindList("items");
  481. ASSERT_NE(nullptr, items);
  482. ASSERT_EQ(7u, items->size());
  483. const char* expected_names[] = {"Save", "Concat", "SaveLayer",
  484. "Translate", "DrawRect", "Restore",
  485. "Restore"};
  486. bool expected_has_skp[] = {false, true, true, true, true, false, false};
  487. for (int i = 0; i < 7; ++i) {
  488. const base::Value& item_value = (*items)[i];
  489. ASSERT_TRUE(item_value.is_dict());
  490. const base::Value::Dict& item_dict = item_value.GetDict();
  491. const base::Value::List* visual_rect =
  492. item_dict.FindList("visual_rect");
  493. ASSERT_NE(nullptr, visual_rect);
  494. EXPECT_TRACED_RECT(2, 3, 8, 9, visual_rect);
  495. const std::string* name = item_dict.FindString("name");
  496. EXPECT_NE(nullptr, name);
  497. EXPECT_EQ(expected_names[i], *name);
  498. EXPECT_EQ(expected_has_skp[i],
  499. item_dict.FindString("skp64") != nullptr);
  500. }
  501. }
  502. }
  503. // Pass |false| to not include PaintOps.
  504. root = ToBaseValue(list.get(), false);
  505. root_dict = root->GetIfDict();
  506. ASSERT_NE(nullptr, root_dict);
  507. // The traced value has a params dictionary as its root.
  508. {
  509. const base::Value::Dict* params_dict = root_dict->FindDict("params");
  510. ASSERT_NE(nullptr, params_dict);
  511. // The real contents of the traced value is in here.
  512. {
  513. const base::Value::List* params_list;
  514. // The layer_rect field is present and has the bounds of the rtree.
  515. params_list = params_dict->FindList("layer_rect");
  516. ASSERT_NE(nullptr, params_list);
  517. EXPECT_TRACED_RECT(2, 3, 8, 9, params_list);
  518. // The items list is not present since we asked for no ops.
  519. params_list = params_dict->FindList("items");
  520. ASSERT_EQ(nullptr, params_list);
  521. }
  522. }
  523. }
  524. TEST_F(DisplayItemListTest, SizeEmpty) {
  525. auto list = base::MakeRefCounted<DisplayItemList>();
  526. EXPECT_EQ(0u, list->TotalOpCount());
  527. }
  528. TEST_F(DisplayItemListTest, SizeOne) {
  529. auto list = base::MakeRefCounted<DisplayItemList>();
  530. gfx::Rect drawing_bounds(5, 6, 1, 1);
  531. {
  532. list->StartPaint();
  533. list->push<DrawRectOp>(gfx::RectToSkRect(drawing_bounds), PaintFlags());
  534. list->EndPaintOfUnpaired(drawing_bounds);
  535. }
  536. EXPECT_EQ(1u, list->TotalOpCount());
  537. }
  538. TEST_F(DisplayItemListTest, SizeMultiple) {
  539. auto list = base::MakeRefCounted<DisplayItemList>();
  540. gfx::Rect clip_bounds(5, 6, 7, 8);
  541. {
  542. list->StartPaint();
  543. list->push<SaveOp>();
  544. list->push<ClipRectOp>(gfx::RectToSkRect(clip_bounds), SkClipOp::kIntersect,
  545. false);
  546. list->EndPaintOfPairedBegin();
  547. }
  548. {
  549. list->StartPaint();
  550. list->push<RestoreOp>();
  551. list->EndPaintOfPairedEnd();
  552. }
  553. EXPECT_EQ(3u, list->TotalOpCount());
  554. }
  555. TEST_F(DisplayItemListTest, AppendVisualRectSimple) {
  556. auto list = base::MakeRefCounted<DisplayItemList>();
  557. // One drawing: D.
  558. gfx::Rect drawing_bounds(5, 6, 7, 8);
  559. {
  560. list->StartPaint();
  561. list->push<DrawRectOp>(gfx::RectToSkRect(drawing_bounds), PaintFlags());
  562. list->EndPaintOfUnpaired(drawing_bounds);
  563. }
  564. EXPECT_EQ(1u, list->TotalOpCount());
  565. EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(0));
  566. }
  567. TEST_F(DisplayItemListTest, AppendVisualRectEmptyBlock) {
  568. auto list = base::MakeRefCounted<DisplayItemList>();
  569. // One block: B1, E1.
  570. gfx::Rect clip_bounds(5, 6, 7, 8);
  571. {
  572. list->StartPaint();
  573. list->push<SaveOp>();
  574. list->push<ClipRectOp>(gfx::RectToSkRect(clip_bounds), SkClipOp::kIntersect,
  575. false);
  576. list->EndPaintOfPairedBegin();
  577. }
  578. {
  579. list->StartPaint();
  580. list->push<RestoreOp>();
  581. list->EndPaintOfPairedEnd();
  582. }
  583. EXPECT_EQ(3u, list->TotalOpCount());
  584. EXPECT_EQ(gfx::Rect(), list->VisualRectForTesting(0));
  585. EXPECT_EQ(gfx::Rect(), list->VisualRectForTesting(1));
  586. EXPECT_EQ(gfx::Rect(), list->VisualRectForTesting(2));
  587. }
  588. TEST_F(DisplayItemListTest, AppendVisualRectEmptyBlockContainingEmptyBlock) {
  589. auto list = base::MakeRefCounted<DisplayItemList>();
  590. // Two nested blocks: B1, B2, E2, E1.
  591. gfx::Rect clip_bounds(5, 6, 7, 8);
  592. {
  593. list->StartPaint();
  594. list->push<SaveOp>();
  595. list->push<ClipRectOp>(gfx::RectToSkRect(clip_bounds), SkClipOp::kIntersect,
  596. false);
  597. list->EndPaintOfPairedBegin();
  598. }
  599. {
  600. list->StartPaint();
  601. list->push<SaveOp>();
  602. list->EndPaintOfPairedBegin();
  603. }
  604. {
  605. list->StartPaint();
  606. list->push<RestoreOp>();
  607. list->EndPaintOfPairedEnd();
  608. }
  609. {
  610. list->StartPaint();
  611. list->push<RestoreOp>();
  612. list->EndPaintOfPairedEnd();
  613. }
  614. EXPECT_EQ(5u, list->TotalOpCount());
  615. EXPECT_EQ(gfx::Rect(), list->VisualRectForTesting(0));
  616. EXPECT_EQ(gfx::Rect(), list->VisualRectForTesting(1));
  617. EXPECT_EQ(gfx::Rect(), list->VisualRectForTesting(2));
  618. EXPECT_EQ(gfx::Rect(), list->VisualRectForTesting(3));
  619. EXPECT_EQ(gfx::Rect(), list->VisualRectForTesting(4));
  620. }
  621. TEST_F(DisplayItemListTest, AppendVisualRectBlockContainingDrawing) {
  622. auto list = base::MakeRefCounted<DisplayItemList>();
  623. // One block with one drawing: B1, Da, E1.
  624. gfx::Rect clip_bounds(5, 6, 7, 8);
  625. {
  626. list->StartPaint();
  627. list->push<SaveOp>();
  628. list->push<ClipRectOp>(gfx::RectToSkRect(clip_bounds), SkClipOp::kIntersect,
  629. false);
  630. list->EndPaintOfPairedBegin();
  631. }
  632. gfx::Rect drawing_bounds(5, 6, 1, 1);
  633. {
  634. list->StartPaint();
  635. list->push<DrawRectOp>(gfx::RectToSkRect(drawing_bounds), PaintFlags());
  636. list->EndPaintOfUnpaired(drawing_bounds);
  637. }
  638. {
  639. list->StartPaint();
  640. list->push<RestoreOp>();
  641. list->EndPaintOfPairedEnd();
  642. }
  643. EXPECT_EQ(4u, list->TotalOpCount());
  644. EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(0));
  645. EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(1));
  646. EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(2));
  647. EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(3));
  648. }
  649. TEST_F(DisplayItemListTest, AppendVisualRectBlockContainingEscapedDrawing) {
  650. auto list = base::MakeRefCounted<DisplayItemList>();
  651. // One block with one drawing: B1, Da (escapes), E1.
  652. gfx::Rect clip_bounds(5, 6, 7, 8);
  653. {
  654. list->StartPaint();
  655. list->push<SaveOp>();
  656. list->push<ClipRectOp>(gfx::RectToSkRect(clip_bounds), SkClipOp::kIntersect,
  657. false);
  658. list->EndPaintOfPairedBegin();
  659. }
  660. gfx::Rect drawing_bounds(1, 2, 3, 4);
  661. {
  662. list->StartPaint();
  663. list->push<DrawRectOp>(gfx::RectToSkRect(drawing_bounds), PaintFlags());
  664. list->EndPaintOfUnpaired(drawing_bounds);
  665. }
  666. {
  667. list->StartPaint();
  668. list->push<RestoreOp>();
  669. list->EndPaintOfPairedEnd();
  670. }
  671. EXPECT_EQ(4u, list->TotalOpCount());
  672. EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(0));
  673. EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(1));
  674. EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(2));
  675. EXPECT_EQ(drawing_bounds, list->VisualRectForTesting(3));
  676. }
  677. TEST_F(DisplayItemListTest,
  678. AppendVisualRectDrawingFollowedByBlockContainingEscapedDrawing) {
  679. auto list = base::MakeRefCounted<DisplayItemList>();
  680. // One drawing followed by one block with one drawing: Da, B1, Db (escapes),
  681. // E1.
  682. gfx::Rect drawing_a_bounds(1, 2, 3, 4);
  683. {
  684. list->StartPaint();
  685. list->push<DrawRectOp>(gfx::RectToSkRect(drawing_a_bounds), PaintFlags());
  686. list->EndPaintOfUnpaired(drawing_a_bounds);
  687. }
  688. gfx::Rect clip_bounds(5, 6, 7, 8);
  689. {
  690. list->StartPaint();
  691. list->push<SaveOp>();
  692. list->push<ClipRectOp>(gfx::RectToSkRect(clip_bounds), SkClipOp::kIntersect,
  693. false);
  694. list->EndPaintOfPairedBegin();
  695. }
  696. gfx::Rect drawing_b_bounds(13, 14, 1, 1);
  697. {
  698. list->StartPaint();
  699. list->push<DrawRectOp>(gfx::RectToSkRect(drawing_b_bounds), PaintFlags());
  700. list->EndPaintOfUnpaired(drawing_b_bounds);
  701. }
  702. {
  703. list->StartPaint();
  704. list->push<RestoreOp>();
  705. list->EndPaintOfPairedEnd();
  706. }
  707. EXPECT_EQ(5u, list->TotalOpCount());
  708. EXPECT_EQ(drawing_a_bounds, list->VisualRectForTesting(0));
  709. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(1));
  710. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(2));
  711. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(3));
  712. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(4));
  713. }
  714. TEST_F(DisplayItemListTest, AppendVisualRectTwoBlocksTwoDrawings) {
  715. auto list = base::MakeRefCounted<DisplayItemList>();
  716. // Multiple nested blocks with drawings amidst: B1, Da, B2, Db, E2, E1.
  717. gfx::Rect clip_bounds(5, 6, 7, 8);
  718. {
  719. list->StartPaint();
  720. list->push<SaveOp>();
  721. list->push<ClipRectOp>(gfx::RectToSkRect(clip_bounds), SkClipOp::kIntersect,
  722. false);
  723. list->EndPaintOfPairedBegin();
  724. }
  725. gfx::Rect drawing_a_bounds(5, 6, 1, 1);
  726. {
  727. list->StartPaint();
  728. list->push<DrawRectOp>(gfx::RectToSkRect(drawing_a_bounds), PaintFlags());
  729. list->EndPaintOfUnpaired(drawing_a_bounds);
  730. }
  731. {
  732. list->StartPaint();
  733. list->push<SaveOp>();
  734. list->push<ConcatOp>(SkM44());
  735. list->EndPaintOfPairedBegin();
  736. }
  737. gfx::Rect drawing_b_bounds(7, 8, 1, 1);
  738. {
  739. list->StartPaint();
  740. list->push<DrawRectOp>(gfx::RectToSkRect(drawing_b_bounds), PaintFlags());
  741. list->EndPaintOfUnpaired(drawing_b_bounds);
  742. }
  743. // End transform.
  744. {
  745. list->StartPaint();
  746. list->push<RestoreOp>();
  747. list->EndPaintOfPairedEnd();
  748. }
  749. // End clip.
  750. {
  751. list->StartPaint();
  752. list->push<RestoreOp>();
  753. list->EndPaintOfPairedEnd();
  754. }
  755. EXPECT_EQ(8u, list->TotalOpCount());
  756. gfx::Rect merged_drawing_bounds = gfx::Rect(drawing_a_bounds);
  757. merged_drawing_bounds.Union(drawing_b_bounds);
  758. EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(0));
  759. EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(1));
  760. EXPECT_EQ(drawing_a_bounds, list->VisualRectForTesting(2));
  761. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(3));
  762. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(4));
  763. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(5));
  764. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(6));
  765. EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(7));
  766. }
  767. TEST_F(DisplayItemListTest,
  768. AppendVisualRectTwoBlocksTwoDrawingsInnerDrawingEscaped) {
  769. auto list = base::MakeRefCounted<DisplayItemList>();
  770. // Multiple nested blocks with drawings amidst: B1, Da, B2, Db (escapes), E2,
  771. // E1.
  772. gfx::Rect clip_bounds(5, 6, 7, 8);
  773. {
  774. list->StartPaint();
  775. list->push<SaveOp>();
  776. list->push<ClipRectOp>(gfx::RectToSkRect(clip_bounds), SkClipOp::kIntersect,
  777. false);
  778. list->EndPaintOfPairedBegin();
  779. }
  780. gfx::Rect drawing_a_bounds(5, 6, 1, 1);
  781. {
  782. list->StartPaint();
  783. list->push<DrawRectOp>(gfx::RectToSkRect(drawing_a_bounds), PaintFlags());
  784. list->EndPaintOfUnpaired(drawing_a_bounds);
  785. }
  786. {
  787. list->StartPaint();
  788. list->push<SaveOp>();
  789. list->push<ConcatOp>(SkM44());
  790. list->EndPaintOfPairedBegin();
  791. }
  792. gfx::Rect drawing_b_bounds(1, 2, 3, 4);
  793. {
  794. list->StartPaint();
  795. list->push<DrawRectOp>(gfx::RectToSkRect(drawing_b_bounds), PaintFlags());
  796. list->EndPaintOfUnpaired(drawing_b_bounds);
  797. }
  798. // End transform.
  799. {
  800. list->StartPaint();
  801. list->push<RestoreOp>();
  802. list->EndPaintOfPairedEnd();
  803. }
  804. // End clip.
  805. {
  806. list->StartPaint();
  807. list->push<RestoreOp>();
  808. list->EndPaintOfPairedEnd();
  809. }
  810. EXPECT_EQ(8u, list->TotalOpCount());
  811. gfx::Rect merged_drawing_bounds = gfx::Rect(drawing_a_bounds);
  812. merged_drawing_bounds.Union(drawing_b_bounds);
  813. EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(0));
  814. EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(1));
  815. EXPECT_EQ(drawing_a_bounds, list->VisualRectForTesting(2));
  816. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(3));
  817. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(4));
  818. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(5));
  819. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(6));
  820. EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(7));
  821. }
  822. TEST_F(DisplayItemListTest,
  823. AppendVisualRectTwoBlocksTwoDrawingsOuterDrawingEscaped) {
  824. auto list = base::MakeRefCounted<DisplayItemList>();
  825. // Multiple nested blocks with drawings amidst: B1, Da (escapes), B2, Db, E2,
  826. // E1.
  827. gfx::Rect clip_bounds(5, 6, 7, 8);
  828. {
  829. list->StartPaint();
  830. list->push<SaveOp>();
  831. list->push<ClipRectOp>(gfx::RectToSkRect(clip_bounds), SkClipOp::kIntersect,
  832. false);
  833. list->EndPaintOfPairedBegin();
  834. }
  835. gfx::Rect drawing_a_bounds(1, 2, 3, 4);
  836. {
  837. list->StartPaint();
  838. list->push<DrawRectOp>(gfx::RectToSkRect(drawing_a_bounds), PaintFlags());
  839. list->EndPaintOfUnpaired(drawing_a_bounds);
  840. }
  841. {
  842. list->StartPaint();
  843. list->push<SaveOp>();
  844. list->push<ConcatOp>(SkM44());
  845. list->EndPaintOfPairedBegin();
  846. }
  847. gfx::Rect drawing_b_bounds(7, 8, 1, 1);
  848. {
  849. list->StartPaint();
  850. list->push<DrawRectOp>(gfx::RectToSkRect(drawing_b_bounds), PaintFlags());
  851. list->EndPaintOfUnpaired(drawing_b_bounds);
  852. }
  853. // End transform.
  854. {
  855. list->StartPaint();
  856. list->push<RestoreOp>();
  857. list->EndPaintOfPairedEnd();
  858. }
  859. // End clip.
  860. {
  861. list->StartPaint();
  862. list->push<RestoreOp>();
  863. list->EndPaintOfPairedEnd();
  864. }
  865. EXPECT_EQ(8u, list->TotalOpCount());
  866. gfx::Rect merged_drawing_bounds = gfx::Rect(drawing_a_bounds);
  867. merged_drawing_bounds.Union(drawing_b_bounds);
  868. EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(0));
  869. EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(1));
  870. EXPECT_EQ(drawing_a_bounds, list->VisualRectForTesting(2));
  871. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(3));
  872. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(4));
  873. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(5));
  874. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(6));
  875. EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(7));
  876. }
  877. TEST_F(DisplayItemListTest,
  878. AppendVisualRectTwoBlocksTwoDrawingsBothDrawingsEscaped) {
  879. auto list = base::MakeRefCounted<DisplayItemList>();
  880. // Multiple nested blocks with drawings amidst:
  881. // B1, Da (escapes to the right), B2, Db (escapes to the left), E2, E1.
  882. gfx::Rect clip_bounds(5, 6, 7, 8);
  883. {
  884. list->StartPaint();
  885. list->push<SaveOp>();
  886. list->push<ClipRectOp>(gfx::RectToSkRect(clip_bounds), SkClipOp::kIntersect,
  887. false);
  888. list->EndPaintOfPairedBegin();
  889. }
  890. gfx::Rect drawing_a_bounds(13, 14, 1, 1);
  891. {
  892. list->StartPaint();
  893. list->push<DrawRectOp>(gfx::RectToSkRect(drawing_a_bounds), PaintFlags());
  894. list->EndPaintOfUnpaired(drawing_a_bounds);
  895. }
  896. {
  897. list->StartPaint();
  898. list->push<SaveOp>();
  899. list->push<ConcatOp>(SkM44());
  900. list->EndPaintOfPairedBegin();
  901. }
  902. gfx::Rect drawing_b_bounds(1, 2, 3, 4);
  903. {
  904. list->StartPaint();
  905. list->push<DrawRectOp>(gfx::RectToSkRect(drawing_b_bounds), PaintFlags());
  906. list->EndPaintOfUnpaired(drawing_b_bounds);
  907. }
  908. // End transform.
  909. {
  910. list->StartPaint();
  911. list->push<RestoreOp>();
  912. list->EndPaintOfPairedEnd();
  913. }
  914. // End clip.
  915. {
  916. list->StartPaint();
  917. list->push<RestoreOp>();
  918. list->EndPaintOfPairedEnd();
  919. }
  920. EXPECT_EQ(8u, list->TotalOpCount());
  921. gfx::Rect merged_drawing_bounds = gfx::Rect(drawing_a_bounds);
  922. merged_drawing_bounds.Union(drawing_b_bounds);
  923. EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(0));
  924. EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(1));
  925. EXPECT_EQ(drawing_a_bounds, list->VisualRectForTesting(2));
  926. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(3));
  927. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(4));
  928. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(5));
  929. EXPECT_EQ(drawing_b_bounds, list->VisualRectForTesting(6));
  930. EXPECT_EQ(merged_drawing_bounds, list->VisualRectForTesting(7));
  931. }
  932. TEST_F(DisplayItemListTest, VisualRectForPairsEnclosingEmptyPainting) {
  933. auto list = base::MakeRefCounted<DisplayItemList>();
  934. // Some paired operations have drawing effect (e.g. some image filters),
  935. // so we should not ignore visual rect for empty painting.
  936. gfx::Rect visual_rect(11, 22, 33, 44);
  937. {
  938. list->StartPaint();
  939. list->push<SaveOp>();
  940. list->push<TranslateOp>(10.f, 20.f);
  941. list->EndPaintOfPairedBegin();
  942. }
  943. {
  944. list->StartPaint();
  945. list->EndPaintOfUnpaired(visual_rect);
  946. }
  947. {
  948. list->StartPaint();
  949. list->push<RestoreOp>();
  950. list->EndPaintOfPairedEnd();
  951. }
  952. EXPECT_EQ(3u, list->TotalOpCount());
  953. EXPECT_EQ(visual_rect, list->VisualRectForTesting(0));
  954. EXPECT_EQ(visual_rect, list->VisualRectForTesting(1));
  955. EXPECT_EQ(visual_rect, list->VisualRectForTesting(2));
  956. }
  957. TEST_F(DisplayItemListTest, TotalOpCount) {
  958. auto list = base::MakeRefCounted<DisplayItemList>();
  959. auto sub_list = base::MakeRefCounted<DisplayItemList>();
  960. sub_list->StartPaint();
  961. sub_list->push<SaveOp>();
  962. sub_list->push<TranslateOp>(10.f, 20.f);
  963. sub_list->push<DrawRectOp>(SkRect::MakeWH(10, 20), PaintFlags());
  964. sub_list->push<RestoreOp>();
  965. sub_list->EndPaintOfUnpaired(gfx::Rect());
  966. EXPECT_EQ(4u, sub_list->TotalOpCount());
  967. list->StartPaint();
  968. list->push<SaveOp>();
  969. list->push<TranslateOp>(10.f, 20.f);
  970. list->push<DrawRecordOp>(sub_list->ReleaseAsRecord());
  971. list->push<RestoreOp>();
  972. list->EndPaintOfUnpaired(gfx::Rect());
  973. EXPECT_EQ(8u, list->TotalOpCount());
  974. }
  975. TEST_F(DisplayItemListTest, AreaOfDrawText) {
  976. auto list = base::MakeRefCounted<DisplayItemList>();
  977. auto sub_list = base::MakeRefCounted<DisplayItemList>();
  978. auto text_blob1 = SkTextBlob::MakeFromString("ABCD", SkFont());
  979. gfx::Size text_blob1_size(ceilf(text_blob1->bounds().width()),
  980. ceilf(text_blob1->bounds().height()));
  981. auto text_blob1_area = text_blob1_size.width() * text_blob1_size.height();
  982. auto text_blob2 = SkTextBlob::MakeFromString("EFG", SkFont());
  983. gfx::Size text_blob2_size(ceilf(text_blob2->bounds().width()),
  984. ceilf(text_blob2->bounds().height()));
  985. auto text_blob2_area = text_blob2_size.width() * text_blob2_size.height();
  986. sub_list->StartPaint();
  987. sub_list->push<DrawTextBlobOp>(text_blob1, 0.0f, 0.0f, PaintFlags());
  988. sub_list->EndPaintOfUnpaired(gfx::Rect());
  989. auto record = sub_list->ReleaseAsRecord();
  990. list->StartPaint();
  991. list->push<SaveOp>();
  992. list->push<TranslateOp>(100.0f, 100.0f);
  993. list->push<DrawRecordOp>(record);
  994. list->push<RestoreOp>();
  995. list->EndPaintOfUnpaired(gfx::Rect(gfx::Point(100, 100), text_blob1_size));
  996. list->StartPaint();
  997. list->push<SaveOp>();
  998. list->push<TranslateOp>(100.0f, 400.0f);
  999. list->push<DrawRecordOp>(record);
  1000. list->push<RestoreOp>();
  1001. list->EndPaintOfUnpaired(gfx::Rect(gfx::Point(100, 400), text_blob1_size));
  1002. list->StartPaint();
  1003. list->push<DrawTextBlobOp>(text_blob2, 10.0f, 20.0f, PaintFlags());
  1004. list->EndPaintOfUnpaired(gfx::Rect(text_blob2_size));
  1005. list->StartPaint();
  1006. list->push<DrawTextBlobOp>(text_blob2, 400.0f, 100.0f, PaintFlags());
  1007. list->EndPaintOfUnpaired(gfx::Rect(gfx::Point(400, 100), text_blob2_size));
  1008. list->StartPaint();
  1009. list->push<DrawRectOp>(SkRect::MakeXYWH(400, 100, 100, 100), PaintFlags());
  1010. list->EndPaintOfUnpaired(gfx::Rect(400, 100, 100, 100));
  1011. list->Finalize();
  1012. // This includes the DrawTextBlobOp in the first DrawRecordOp the the first
  1013. // direct DrawTextBlobOp.
  1014. EXPECT_EQ(static_cast<int>(text_blob1_area + text_blob2_area),
  1015. static_cast<int>(list->AreaOfDrawText(gfx::Rect(200, 200))));
  1016. // This includes all DrawTextBlobOps.
  1017. EXPECT_EQ(static_cast<int>(text_blob1_area * 2 + text_blob2_area * 2),
  1018. static_cast<int>(list->AreaOfDrawText(gfx::Rect(500, 500))));
  1019. }
  1020. } // namespace cc