Home | History | Annotate | Download | only in ext
      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 
      5 #include "base/compiler_specific.h"
      6 #include "skia/ext/analysis_canvas.h"
      7 #include "skia/ext/refptr.h"
      8 #include "testing/gtest/include/gtest/gtest.h"
      9 #include "third_party/skia/include/core/SkPicture.h"
     10 #include "third_party/skia/include/core/SkPictureRecorder.h"
     11 #include "third_party/skia/include/core/SkShader.h"
     12 #include "third_party/skia/include/effects/SkOffsetImageFilter.h"
     13 
     14 namespace {
     15 
     16 void SolidColorFill(skia::AnalysisCanvas& canvas) {
     17   canvas.clear(SkColorSetARGB(255, 255, 255, 255));
     18 }
     19 
     20 void TransparentFill(skia::AnalysisCanvas& canvas) {
     21   canvas.clear(SkColorSetARGB(0, 0, 0, 0));
     22 }
     23 
     24 } // namespace
     25 namespace skia {
     26 
     27 TEST(AnalysisCanvasTest, EmptyCanvas) {
     28   skia::AnalysisCanvas canvas(255, 255);
     29 
     30   SkColor color;
     31   EXPECT_TRUE(canvas.GetColorIfSolid(&color));
     32   EXPECT_EQ(color, SkColorSetARGB(0, 0, 0, 0));
     33 }
     34 
     35 TEST(AnalysisCanvasTest, ClearCanvas) {
     36   skia::AnalysisCanvas canvas(255, 255);
     37 
     38   // Transparent color
     39   SkColor color = SkColorSetARGB(0, 12, 34, 56);
     40   canvas.clear(color);
     41 
     42   SkColor outputColor;
     43   EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
     44   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
     45 
     46   // Solid color
     47   color = SkColorSetARGB(255, 65, 43, 21);
     48   canvas.clear(color);
     49 
     50   EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
     51   EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
     52   EXPECT_EQ(outputColor, color);
     53 
     54   // Translucent color
     55   color = SkColorSetARGB(128, 11, 22, 33);
     56   canvas.clear(color);
     57 
     58   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
     59 
     60   // Test helper methods
     61   SolidColorFill(canvas);
     62   EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
     63   EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
     64 
     65   TransparentFill(canvas);
     66   EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
     67   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
     68 }
     69 
     70 TEST(AnalysisCanvasTest, ComplexActions) {
     71   skia::AnalysisCanvas canvas(255, 255);
     72 
     73   // Draw paint test.
     74   SkColor color = SkColorSetARGB(255, 11, 22, 33);
     75   SkPaint paint;
     76   paint.setColor(color);
     77 
     78   canvas.drawPaint(paint);
     79 
     80   SkColor outputColor;
     81   //TODO(vmpstr): This should return true. (crbug.com/180597)
     82   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
     83 
     84   // Draw points test.
     85   SkPoint points[4] = {
     86     SkPoint::Make(0, 0),
     87     SkPoint::Make(255, 0),
     88     SkPoint::Make(255, 255),
     89     SkPoint::Make(0, 255)
     90   };
     91 
     92   SolidColorFill(canvas);
     93   canvas.drawPoints(SkCanvas::kLines_PointMode, 4, points, paint);
     94 
     95   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
     96 
     97   // Draw oval test.
     98   SolidColorFill(canvas);
     99   canvas.drawOval(SkRect::MakeWH(255, 255), paint);
    100 
    101   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    102 
    103   // Draw bitmap test.
    104   SolidColorFill(canvas);
    105   SkBitmap secondBitmap;
    106   secondBitmap.allocN32Pixels(255, 255);
    107   canvas.drawBitmap(secondBitmap, 0, 0);
    108 
    109   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    110 }
    111 
    112 TEST(AnalysisCanvasTest, SimpleDrawRect) {
    113   skia::AnalysisCanvas canvas(255, 255);
    114 
    115   SkColor color = SkColorSetARGB(255, 11, 22, 33);
    116   SkPaint paint;
    117   paint.setColor(color);
    118   canvas.clipRect(SkRect::MakeWH(255, 255));
    119   canvas.drawRect(SkRect::MakeWH(255, 255), paint);
    120 
    121   SkColor outputColor;
    122   EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
    123   EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
    124   EXPECT_EQ(color, outputColor);
    125 
    126   color = SkColorSetARGB(255, 22, 33, 44);
    127   paint.setColor(color);
    128   canvas.translate(-128, -128);
    129   canvas.drawRect(SkRect::MakeWH(382, 382), paint);
    130 
    131   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    132 
    133   color = SkColorSetARGB(255, 33, 44, 55);
    134   paint.setColor(color);
    135   canvas.drawRect(SkRect::MakeWH(383, 383), paint);
    136 
    137   EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
    138   EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
    139   EXPECT_EQ(color, outputColor);
    140 
    141   color = SkColorSetARGB(0, 0, 0, 0);
    142   paint.setColor(color);
    143   canvas.drawRect(SkRect::MakeWH(383, 383), paint);
    144 
    145   // This test relies on canvas treating a paint with 0-color as a no-op
    146   // thus not changing its "is_solid" status.
    147   EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
    148   EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
    149   EXPECT_EQ(outputColor, SkColorSetARGB(255, 33, 44, 55));
    150 
    151   color = SkColorSetARGB(128, 128, 128, 128);
    152   paint.setColor(color);
    153   canvas.drawRect(SkRect::MakeWH(383, 383), paint);
    154 
    155   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    156 
    157   paint.setXfermodeMode(SkXfermode::kClear_Mode);
    158   canvas.drawRect(SkRect::MakeWH(382, 382), paint);
    159 
    160   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    161 
    162   canvas.drawRect(SkRect::MakeWH(383, 383), paint);
    163 
    164   EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
    165   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
    166 
    167   canvas.translate(128, 128);
    168   color = SkColorSetARGB(255, 11, 22, 33);
    169   paint.setColor(color);
    170   paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
    171   canvas.drawRect(SkRect::MakeWH(255, 255), paint);
    172 
    173   EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
    174   EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
    175   EXPECT_EQ(color, outputColor);
    176 
    177   canvas.rotate(50);
    178   canvas.drawRect(SkRect::MakeWH(255, 255), paint);
    179 
    180   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    181 }
    182 
    183 TEST(AnalysisCanvasTest, FilterPaint) {
    184   skia::AnalysisCanvas canvas(255, 255);
    185   SkPaint paint;
    186 
    187   skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(SkOffsetImageFilter::Create(10, 10));
    188   paint.setImageFilter(filter.get());
    189   canvas.drawRect(SkRect::MakeWH(255, 255), paint);
    190 
    191   SkColor outputColor;
    192   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    193 }
    194 
    195 TEST(AnalysisCanvasTest, ClipPath) {
    196   skia::AnalysisCanvas canvas(255, 255);
    197 
    198   // Skia will look for paths that are actually rects and treat
    199   // them as such. We add a divot to the following path to prevent
    200   // this optimization and truly test clipPath's behavior.
    201   SkPath path;
    202   path.moveTo(0, 0);
    203   path.lineTo(128, 50);
    204   path.lineTo(255, 0);
    205   path.lineTo(255, 255);
    206   path.lineTo(0, 255);
    207 
    208   SkColor outputColor;
    209   SolidColorFill(canvas);
    210   canvas.clipPath(path);
    211   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    212 
    213   canvas.save();
    214   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    215 
    216   canvas.clipPath(path);
    217   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    218 
    219   canvas.restore();
    220   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    221 
    222   SolidColorFill(canvas);
    223   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    224 }
    225 
    226 TEST(AnalysisCanvasTest, SaveLayerRestore) {
    227   skia::AnalysisCanvas canvas(255, 255);
    228 
    229   SkColor outputColor;
    230   SolidColorFill(canvas);
    231   EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
    232 
    233   SkRect bounds = SkRect::MakeWH(255, 255);
    234   SkPaint paint;
    235   paint.setColor(SkColorSetARGB(255, 255, 255, 255));
    236   paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
    237 
    238   // This should force non-transparency
    239   canvas.saveLayer(&bounds, &paint);
    240   EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
    241   EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
    242 
    243   TransparentFill(canvas);
    244   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    245 
    246   SolidColorFill(canvas);
    247   EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
    248   EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
    249 
    250   paint.setXfermodeMode(SkXfermode::kDst_Mode);
    251 
    252   // This should force non-solid color
    253   canvas.saveLayer(&bounds, &paint);
    254   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    255 
    256   TransparentFill(canvas);
    257   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    258 
    259   SolidColorFill(canvas);
    260   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    261 
    262   canvas.restore();
    263   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    264 
    265   TransparentFill(canvas);
    266   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    267 
    268   SolidColorFill(canvas);
    269   EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
    270   EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
    271 
    272   canvas.restore();
    273   EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
    274   EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
    275 
    276   TransparentFill(canvas);
    277   EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
    278   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
    279 
    280   SolidColorFill(canvas);
    281   EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
    282   EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
    283 }
    284 
    285 TEST(AnalysisCanvasTest, EarlyOutNotSolid) {
    286   SkTileGridFactory::TileGridInfo tile_grid_info;
    287   tile_grid_info.fTileInterval.set(256, 256);
    288   tile_grid_info.fOffset.setZero();
    289   tile_grid_info.fMargin.setEmpty();
    290   SkTileGridFactory factory(tile_grid_info);
    291   SkPictureRecorder recorder;
    292 
    293   // Create a picture with 3 commands, last of which is non-solid.
    294   skia::RefPtr<SkCanvas> record_canvas =
    295       skia::SharePtr(recorder.beginRecording(256, 256, &factory));
    296 
    297   std::string text = "text";
    298   SkPoint point = SkPoint::Make(SkIntToScalar(25), SkIntToScalar(25));
    299 
    300   SkPaint paint;
    301   paint.setColor(SkColorSetARGB(255, 255, 255, 255));
    302   paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
    303 
    304   record_canvas->drawRect(SkRect::MakeWH(256, 256), paint);
    305   record_canvas->drawRect(SkRect::MakeWH(256, 256), paint);
    306   record_canvas->drawText(
    307       text.c_str(), text.length(), point.fX, point.fY, paint);
    308 
    309   skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording());
    310 
    311   // Draw the picture into the analysis canvas, using the canvas as a callback
    312   // as well.
    313   skia::AnalysisCanvas canvas(256, 256);
    314   picture->draw(&canvas, &canvas);
    315 
    316   // Ensure that canvas is not solid.
    317   SkColor output_color;
    318   EXPECT_FALSE(canvas.GetColorIfSolid(&output_color));
    319 
    320   // Verify that we aborted drawing.
    321   EXPECT_TRUE(canvas.abortDrawing());
    322 
    323 }
    324 
    325 TEST(AnalysisCanvasTest, ClipComplexRegion) {
    326   skia::AnalysisCanvas canvas(255, 255);
    327 
    328   SkPath path;
    329   path.moveTo(0, 0);
    330   path.lineTo(128, 50);
    331   path.lineTo(255, 0);
    332   path.lineTo(255, 255);
    333   path.lineTo(0, 255);
    334   SkIRect pathBounds = path.getBounds().round();
    335   SkRegion region;
    336   region.setPath(path, SkRegion(pathBounds));
    337 
    338   SkColor outputColor;
    339   SolidColorFill(canvas);
    340   canvas.clipRegion(region);
    341   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    342 
    343   canvas.save();
    344   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    345 
    346   canvas.clipRegion(region);
    347   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    348 
    349   canvas.restore();
    350   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    351 
    352   SolidColorFill(canvas);
    353   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
    354 }
    355 
    356 }  // namespace skia
    357