Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / skia / ext / analysis_canvas_unittest.cc
bloba8a9d0dd611f478aec6b295f2d51f266db8263b2
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.
5 #include "base/compiler_specific.h"
6 #include "skia/ext/analysis_canvas.h"
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "third_party/skia/include/core/SkShader.h"
10 namespace {
12 void solidColorFill(skia::AnalysisCanvas& canvas) {
13 canvas.clear(SkColorSetARGB(255, 255, 255, 255));
16 void transparentFill(skia::AnalysisCanvas& canvas) {
17 canvas.clear(SkColorSetARGB(0, 0, 0, 0));
20 } // namespace
21 namespace skia {
23 class TestPixelRef : public SkPixelRef {
24 public:
25 // Pure virtual implementation.
26 virtual SkFlattenable::Factory getFactory() OVERRIDE { return NULL; }
27 virtual void* onLockPixels(SkColorTable**) OVERRIDE { return NULL; }
28 virtual void onUnlockPixels() OVERRIDE {}
31 class TestLazyPixelRef : public LazyPixelRef {
32 public:
33 // Pure virtual implementation.
34 virtual SkFlattenable::Factory getFactory() OVERRIDE { return NULL; }
35 virtual void* onLockPixels(SkColorTable**) OVERRIDE { return NULL; }
36 virtual void onUnlockPixels() OVERRIDE {}
37 virtual bool PrepareToDecode(const PrepareParams& params) OVERRIDE {
38 return true;
40 virtual void Decode() OVERRIDE {}
43 class TestShader : public SkShader {
44 public:
45 TestShader(SkBitmap* bitmap)
46 : bitmap_(bitmap) {
49 virtual SkShader::BitmapType asABitmap(
50 SkBitmap* bitmap,
51 SkMatrix*,
52 TileMode xy[2]) const OVERRIDE {
53 if (bitmap)
54 *bitmap = *bitmap_;
55 return SkShader::kDefault_BitmapType;
58 // Pure virtual implementation.
59 virtual void shadeSpan(int x, int y, SkPMColor[], int count) OVERRIDE {}
60 virtual SkFlattenable::Factory getFactory() OVERRIDE { return NULL; }
62 private:
64 SkBitmap* bitmap_;
67 TEST(AnalysisCanvasTest, EmptyCanvas) {
68 SkBitmap emptyBitmap;
69 emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
70 skia::AnalysisDevice device(emptyBitmap);
71 skia::AnalysisCanvas canvas(&device);
73 SkColor color;
74 EXPECT_FALSE(canvas.getColorIfSolid(&color));
75 EXPECT_FALSE(canvas.isTransparent());
76 EXPECT_TRUE(canvas.isCheap());
79 TEST(AnalysisCanvasTest, ClearCanvas) {
80 SkBitmap emptyBitmap;
81 emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
82 skia::AnalysisDevice device(emptyBitmap);
83 skia::AnalysisCanvas canvas(&device);
85 // Transparent color
86 SkColor color = SkColorSetARGB(0, 12, 34, 56);
87 canvas.clear(color);
89 SkColor outputColor;
90 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
91 EXPECT_TRUE(canvas.isTransparent());
92 EXPECT_TRUE(canvas.isCheap());
94 // Solid color
95 color = SkColorSetARGB(255, 65, 43, 21);
96 canvas.clear(color);
98 EXPECT_TRUE(canvas.getColorIfSolid(&outputColor));
99 EXPECT_FALSE(canvas.isTransparent());
100 EXPECT_FALSE(canvas.isCheap());
101 EXPECT_EQ(outputColor, color);
103 // Translucent color
104 color = SkColorSetARGB(128, 11, 22, 33);
105 canvas.clear(color);
107 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
108 EXPECT_FALSE(canvas.isTransparent());
109 EXPECT_FALSE(canvas.isCheap());
111 // Test helper methods
112 solidColorFill(canvas);
113 EXPECT_TRUE(canvas.getColorIfSolid(&outputColor));
114 EXPECT_FALSE(canvas.isTransparent());
116 transparentFill(canvas);
117 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
118 EXPECT_TRUE(canvas.isTransparent());
121 TEST(AnalysisCanvasTest, ComplexActions) {
122 SkBitmap emptyBitmap;
123 emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
124 skia::AnalysisDevice device(emptyBitmap);
125 skia::AnalysisCanvas canvas(&device);
127 // Draw paint test.
128 SkColor color = SkColorSetARGB(255, 11, 22, 33);
129 SkPaint paint;
130 paint.setColor(color);
132 canvas.drawPaint(paint);
134 SkColor outputColor;
135 //TODO(vmpstr): This should return true. (crbug.com/180597)
136 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
137 EXPECT_FALSE(canvas.isTransparent());
138 EXPECT_TRUE(canvas.isCheap());
140 // Draw points test.
141 SkPoint points[4] = {
142 SkPoint::Make(0, 0),
143 SkPoint::Make(255, 0),
144 SkPoint::Make(255, 255),
145 SkPoint::Make(0, 255)
148 solidColorFill(canvas);
149 canvas.drawPoints(SkCanvas::kLines_PointMode, 4, points, paint);
151 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
152 EXPECT_FALSE(canvas.isTransparent());
153 EXPECT_FALSE(canvas.isCheap());
155 // Draw oval test.
156 solidColorFill(canvas);
157 canvas.drawOval(SkRect::MakeWH(255, 255), paint);
159 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
160 EXPECT_FALSE(canvas.isTransparent());
161 EXPECT_FALSE(canvas.isCheap());
163 // Draw bitmap test.
164 solidColorFill(canvas);
165 SkBitmap secondBitmap;
166 secondBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
167 canvas.drawBitmap(secondBitmap, 0, 0);
169 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
170 EXPECT_FALSE(canvas.isTransparent());
171 EXPECT_FALSE(canvas.isCheap());
174 TEST(AnalysisCanvasTest, SimpleDrawRect) {
175 SkBitmap emptyBitmap;
176 emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
177 skia::AnalysisDevice device(emptyBitmap);
178 skia::AnalysisCanvas canvas(&device);
180 SkColor color = SkColorSetARGB(255, 11, 22, 33);
181 SkPaint paint;
182 paint.setColor(color);
183 canvas.clipRect(SkRect::MakeWH(255, 255));
184 canvas.drawRect(SkRect::MakeWH(255, 255), paint);
186 SkColor outputColor;
187 EXPECT_TRUE(canvas.getColorIfSolid(&outputColor));
188 EXPECT_FALSE(canvas.isTransparent());
189 EXPECT_TRUE(canvas.isCheap());
190 EXPECT_EQ(color, outputColor);
192 color = SkColorSetARGB(255, 22, 33, 44);
193 paint.setColor(color);
194 canvas.translate(-128, -128);
195 canvas.drawRect(SkRect::MakeWH(382, 382), paint);
197 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
198 EXPECT_FALSE(canvas.isTransparent());
199 EXPECT_TRUE(canvas.isCheap());
201 color = SkColorSetARGB(255, 33, 44, 55);
202 paint.setColor(color);
203 canvas.drawRect(SkRect::MakeWH(383, 383), paint);
205 EXPECT_TRUE(canvas.getColorIfSolid(&outputColor));
206 EXPECT_FALSE(canvas.isTransparent());
207 EXPECT_TRUE(canvas.isCheap());
208 EXPECT_EQ(color, outputColor);
210 color = SkColorSetARGB(0, 0, 0, 0);
211 paint.setColor(color);
212 canvas.drawRect(SkRect::MakeWH(383, 383), paint);
214 EXPECT_TRUE(canvas.getColorIfSolid(&outputColor));
215 EXPECT_FALSE(canvas.isTransparent());
216 EXPECT_TRUE(canvas.isCheap());
217 EXPECT_EQ(outputColor, SkColorSetARGB(255, 33, 44, 55));
219 color = SkColorSetARGB(128, 128, 128, 128);
220 paint.setColor(color);
221 canvas.drawRect(SkRect::MakeWH(383, 383), paint);
223 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
224 EXPECT_FALSE(canvas.isTransparent());
225 EXPECT_TRUE(canvas.isCheap());
227 paint.setXfermodeMode(SkXfermode::kClear_Mode);
228 canvas.drawRect(SkRect::MakeWH(382, 382), paint);
230 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
231 EXPECT_FALSE(canvas.isTransparent());
232 EXPECT_TRUE(canvas.isCheap());
234 canvas.drawRect(SkRect::MakeWH(383, 383), paint);
236 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
237 EXPECT_TRUE(canvas.isTransparent());
238 EXPECT_TRUE(canvas.isCheap());
240 canvas.translate(128, 128);
241 color = SkColorSetARGB(255, 11, 22, 33);
242 paint.setColor(color);
243 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
244 canvas.drawRect(SkRect::MakeWH(255, 255), paint);
246 EXPECT_TRUE(canvas.getColorIfSolid(&outputColor));
247 EXPECT_FALSE(canvas.isTransparent());
248 EXPECT_TRUE(canvas.isCheap());
249 EXPECT_EQ(color, outputColor);
251 canvas.rotate(50);
252 canvas.drawRect(SkRect::MakeWH(255, 255), paint);
254 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
255 EXPECT_FALSE(canvas.isTransparent());
256 EXPECT_TRUE(canvas.isCheap());
259 TEST(AnalysisCanvasTest, ClipPath) {
260 SkBitmap emptyBitmap;
261 emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
262 skia::AnalysisDevice device(emptyBitmap);
263 skia::AnalysisCanvas canvas(&device);
265 SkPath path;
266 path.moveTo(0, 0);
267 path.lineTo(255, 0);
268 path.lineTo(255, 255);
269 path.lineTo(0, 255);
271 SkColor outputColor;
272 solidColorFill(canvas);
273 canvas.clipPath(path);
274 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
276 canvas.save();
277 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
279 canvas.clipPath(path);
280 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
282 canvas.restore();
283 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
285 solidColorFill(canvas);
286 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
289 TEST(AnalysisCanvasTest, SaveLayerRestore) {
290 SkBitmap emptyBitmap;
291 emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
292 skia::AnalysisDevice device(emptyBitmap);
293 skia::AnalysisCanvas canvas(&device);
295 SkColor outputColor;
296 solidColorFill(canvas);
297 EXPECT_TRUE(canvas.getColorIfSolid(&outputColor));
299 SkRect bounds = SkRect::MakeWH(255, 255);
300 SkPaint paint;
301 paint.setColor(SkColorSetARGB(255, 255, 255, 255));
302 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
304 // This should force non-transparency
305 canvas.saveLayer(&bounds, &paint, SkCanvas::kMatrix_SaveFlag);
306 EXPECT_TRUE(canvas.getColorIfSolid(&outputColor));
307 EXPECT_FALSE(canvas.isTransparent());
309 transparentFill(canvas);
310 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
311 EXPECT_FALSE(canvas.isTransparent());
313 solidColorFill(canvas);
314 EXPECT_TRUE(canvas.getColorIfSolid(&outputColor));
315 EXPECT_FALSE(canvas.isTransparent());
317 paint.setXfermodeMode(SkXfermode::kDst_Mode);
319 // This should force non-solid color
320 canvas.saveLayer(&bounds, &paint, SkCanvas::kMatrix_SaveFlag);
321 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
322 EXPECT_FALSE(canvas.isTransparent());
324 transparentFill(canvas);
325 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
326 EXPECT_FALSE(canvas.isTransparent());
328 solidColorFill(canvas);
329 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
330 EXPECT_FALSE(canvas.isTransparent());
332 canvas.restore();
333 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
334 EXPECT_FALSE(canvas.isTransparent());
336 transparentFill(canvas);
337 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
338 EXPECT_FALSE(canvas.isTransparent());
340 solidColorFill(canvas);
341 EXPECT_TRUE(canvas.getColorIfSolid(&outputColor));
342 EXPECT_FALSE(canvas.isTransparent());
344 canvas.restore();
345 EXPECT_TRUE(canvas.getColorIfSolid(&outputColor));
346 EXPECT_FALSE(canvas.isTransparent());
348 transparentFill(canvas);
349 EXPECT_FALSE(canvas.getColorIfSolid(&outputColor));
350 EXPECT_TRUE(canvas.isTransparent());
352 solidColorFill(canvas);
353 EXPECT_TRUE(canvas.getColorIfSolid(&outputColor));
354 EXPECT_FALSE(canvas.isTransparent());
357 TEST(AnalysisCanvasTest, LazyPixelRefs) {
358 // Set up two lazy and two non-lazy pixel refs and the corresponding bitmaps.
359 TestLazyPixelRef firstLazyPixelRef;
360 firstLazyPixelRef.setURI("lazy");
361 TestLazyPixelRef secondLazyPixelRef;
362 secondLazyPixelRef.setURI("lazy");
364 TestPixelRef firstNonLazyPixelRef;
365 TestPixelRef secondNonLazyPixelRef;
366 secondNonLazyPixelRef.setURI("notsolazy");
368 SkBitmap firstLazyBitmap;
369 firstLazyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
370 firstLazyBitmap.setPixelRef(&firstLazyPixelRef);
371 SkBitmap secondLazyBitmap;
372 secondLazyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
373 secondLazyBitmap.setPixelRef(&secondLazyPixelRef);
375 SkBitmap firstNonLazyBitmap;
376 firstNonLazyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
377 SkBitmap secondNonLazyBitmap;
378 secondNonLazyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
379 secondNonLazyBitmap.setPixelRef(&secondNonLazyPixelRef);
381 // The testcase starts here.
382 SkBitmap emptyBitmap;
383 emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
384 skia::AnalysisDevice device(emptyBitmap);
385 skia::AnalysisCanvas canvas(&device);
387 // This should be the first ref.
388 canvas.drawBitmap(firstLazyBitmap, 0, 0);
389 // The following will be ignored (non-lazy).
390 canvas.drawBitmap(firstNonLazyBitmap, 0, 0);
391 canvas.drawBitmap(firstNonLazyBitmap, 0, 0);
392 canvas.drawBitmap(secondNonLazyBitmap, 0, 0);
393 canvas.drawBitmap(secondNonLazyBitmap, 0, 0);
394 // This one will be ignored (already exists).
395 canvas.drawBitmap(firstLazyBitmap, 0, 0);
396 // This should be the second ref.
397 canvas.drawBitmap(secondLazyBitmap, 0, 0);
399 std::list<skia::LazyPixelRef*> pixelRefs;
400 canvas.consumeLazyPixelRefs(&pixelRefs);
402 // We expect to get only lazy pixel refs and only unique results.
403 EXPECT_EQ(pixelRefs.size(), 2u);
404 if (!pixelRefs.empty()) {
405 EXPECT_EQ(pixelRefs.front(),
406 static_cast<LazyPixelRef*>(&firstLazyPixelRef));
407 EXPECT_EQ(pixelRefs.back(),
408 static_cast<LazyPixelRef*>(&secondLazyPixelRef));
412 TEST(AnalysisCanvasTest, PixelRefsFromPaint) {
413 TestLazyPixelRef lazyPixelRef;
414 lazyPixelRef.setURI("lazy");
416 TestPixelRef nonLazyPixelRef;
417 nonLazyPixelRef.setURI("notsolazy");
419 SkBitmap lazyBitmap;
420 lazyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
421 lazyBitmap.setPixelRef(&lazyPixelRef);
423 SkBitmap nonLazyBitmap;
424 nonLazyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
425 nonLazyBitmap.setPixelRef(&nonLazyPixelRef);
427 TestShader lazyShader(&lazyBitmap);
428 TestShader nonLazyShader(&nonLazyBitmap);
430 SkPaint lazyPaint;
431 lazyPaint.setShader(&lazyShader);
432 SkPaint nonLazyPaint;
433 nonLazyPaint.setShader(&nonLazyShader);
435 SkBitmap emptyBitmap;
436 emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255);
437 skia::AnalysisDevice device(emptyBitmap);
438 skia::AnalysisCanvas canvas(&device);
440 canvas.drawRect(SkRect::MakeWH(255, 255), lazyPaint);
441 canvas.drawRect(SkRect::MakeWH(255, 255), lazyPaint);
442 canvas.drawRect(SkRect::MakeWH(255, 255), lazyPaint);
443 canvas.drawRect(SkRect::MakeWH(255, 255), nonLazyPaint);
444 canvas.drawRect(SkRect::MakeWH(255, 255), nonLazyPaint);
445 canvas.drawRect(SkRect::MakeWH(255, 255), nonLazyPaint);
447 std::list<skia::LazyPixelRef*> pixelRefs;
448 canvas.consumeLazyPixelRefs(&pixelRefs);
450 // We expect to get only lazy pixel refs and only unique results.
451 EXPECT_EQ(pixelRefs.size(), 1u);
452 if (!pixelRefs.empty()) {
453 EXPECT_EQ(pixelRefs.front(), static_cast<LazyPixelRef*>(&lazyPixelRef));
457 TEST(AnalysisCanvasTest, HasText) {
458 int width = 200;
459 int height = 100;
461 SkBitmap bitmap;
462 bitmap.setConfig(SkBitmap::kNo_Config, width, height);
464 const char* text = "A";
465 size_t byteLength = 1;
467 SkPoint point = SkPoint::Make(SkIntToScalar(25), SkIntToScalar(25));
468 SkPath path;
469 path.moveTo(point);
470 path.lineTo(SkIntToScalar(75), SkIntToScalar(75));
472 SkPaint paint;
473 paint.setColor(SK_ColorGRAY);
474 paint.setTextSize(SkIntToScalar(10));
477 skia::AnalysisDevice device(bitmap);
478 skia::AnalysisCanvas canvas(&device);
479 // Test after initialization.
480 EXPECT_FALSE(canvas.hasText());
481 // Test drawing anything other than text.
482 canvas.drawRect(SkRect::MakeWH(width/2, height), paint);
483 EXPECT_FALSE(canvas.hasText());
486 // Test SkCanvas::drawText.
487 skia::AnalysisDevice device(bitmap);
488 skia::AnalysisCanvas canvas(&device);
489 canvas.drawText(text, byteLength, point.fX, point.fY, paint);
490 EXPECT_TRUE(canvas.hasText());
493 // Test SkCanvas::drawPosText.
494 skia::AnalysisDevice device(bitmap);
495 skia::AnalysisCanvas canvas(&device);
496 canvas.drawPosText(text, byteLength, &point, paint);
497 EXPECT_TRUE(canvas.hasText());
500 // Test SkCanvas::drawPosTextH.
501 skia::AnalysisDevice device(bitmap);
502 skia::AnalysisCanvas canvas(&device);
503 canvas.drawPosTextH(text, byteLength, &point.fX, point.fY, paint);
504 EXPECT_TRUE(canvas.hasText());
507 // Test SkCanvas::drawTextOnPathHV.
508 skia::AnalysisDevice device(bitmap);
509 skia::AnalysisCanvas canvas(&device);
510 canvas.drawTextOnPathHV(text, byteLength, path, point.fX, point.fY, paint);
511 EXPECT_TRUE(canvas.hasText());
514 // Test SkCanvas::drawTextOnPath.
515 skia::AnalysisDevice device(bitmap);
516 skia::AnalysisCanvas canvas(&device);
517 canvas.drawTextOnPath(text, byteLength, path, NULL, paint);
518 EXPECT_TRUE(canvas.hasText());
521 // Text under opaque rect.
522 skia::AnalysisDevice device(bitmap);
523 skia::AnalysisCanvas canvas(&device);
524 canvas.drawText(text, byteLength, point.fX, point.fY, paint);
525 EXPECT_TRUE(canvas.hasText());
526 canvas.drawRect(SkRect::MakeWH(width, height), paint);
527 EXPECT_FALSE(canvas.hasText());
530 // Text under translucent rect.
531 skia::AnalysisDevice device(bitmap);
532 skia::AnalysisCanvas canvas(&device);
533 canvas.drawText(text, byteLength, point.fX, point.fY, paint);
534 EXPECT_TRUE(canvas.hasText());
535 SkPaint translucentPaint;
536 translucentPaint.setColor(0x88FFFFFF);
537 canvas.drawRect(SkRect::MakeWH(width, height), translucentPaint);
538 EXPECT_TRUE(canvas.hasText());
541 // Text under rect in clear mode.
542 skia::AnalysisDevice device(bitmap);
543 skia::AnalysisCanvas canvas(&device);
544 canvas.drawText(text, byteLength, point.fX, point.fY, paint);
545 EXPECT_TRUE(canvas.hasText());
546 SkPaint clearModePaint;
547 clearModePaint.setXfermodeMode(SkXfermode::kClear_Mode);
548 canvas.drawRect(SkRect::MakeWH(width, height), clearModePaint);
549 EXPECT_FALSE(canvas.hasText());
552 // Clear.
553 skia::AnalysisDevice device(bitmap);
554 skia::AnalysisCanvas canvas(&device);
555 canvas.drawText(text, byteLength, point.fX, point.fY, paint);
556 EXPECT_TRUE(canvas.hasText());
557 canvas.clear(SK_ColorGRAY);
558 EXPECT_FALSE(canvas.hasText());
561 // Text inside clip region.
562 skia::AnalysisDevice device(bitmap);
563 skia::AnalysisCanvas canvas(&device);
564 canvas.clipRect(SkRect::MakeWH(100, 100));
565 canvas.drawText(text, byteLength, point.fX, point.fY, paint);
566 EXPECT_TRUE(canvas.hasText());
569 // Text outside clip region.
570 skia::AnalysisDevice device(bitmap);
571 skia::AnalysisCanvas canvas(&device);
572 canvas.clipRect(SkRect::MakeXYWH(100, 0, 100, 100));
573 canvas.drawText(text, byteLength, point.fX, point.fY, paint);
574 // Analysis device does not do any clipping.
575 // So even when text is outside the clip region,
576 // it is marked as having the text.
577 // TODO(alokp): We may be able to do some trivial rejection.
578 EXPECT_TRUE(canvas.hasText());
582 } // namespace skia