Home | History | Annotate | Download | only in tests
      1 
      2 /*
      3  * Copyright 2013 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include "Test.h"
     10 #include "SkCanvas.h"
     11 #include "SkCanvasStateUtils.h"
     12 #include "SkDevice.h"
     13 #include "SkDrawFilter.h"
     14 #include "SkPaint.h"
     15 #include "SkRect.h"
     16 #include "SkRRect.h"
     17 
     18 static void test_complex_layers(skiatest::Reporter* reporter) {
     19     const int WIDTH = 400;
     20     const int HEIGHT = 400;
     21     const int SPACER = 10;
     22 
     23     SkRect rect = SkRect::MakeXYWH(SPACER, SPACER, WIDTH-(2*SPACER), (HEIGHT-(2*SPACER)) / 7);
     24 
     25     const SkBitmap::Config configs[] = { SkBitmap::kRGB_565_Config,
     26                                          SkBitmap::kARGB_8888_Config
     27     };
     28     const int configCount = sizeof(configs) / sizeof(SkBitmap::Config);
     29 
     30     const int layerAlpha[] = { 255, 255, 0 };
     31     const SkCanvas::SaveFlags flags[] = { SkCanvas::kARGB_NoClipLayer_SaveFlag,
     32                                           SkCanvas::kARGB_ClipLayer_SaveFlag,
     33                                           SkCanvas::kARGB_NoClipLayer_SaveFlag
     34     };
     35     REPORTER_ASSERT(reporter, sizeof(layerAlpha) == sizeof(flags));
     36     const int layerCombinations = sizeof(layerAlpha) / sizeof(int);
     37 
     38     for (int i = 0; i < configCount; ++i) {
     39         SkBitmap bitmaps[2];
     40         for (int j = 0; j < 2; ++j) {
     41             bitmaps[j].setConfig(configs[i], WIDTH, HEIGHT);
     42             bitmaps[j].allocPixels();
     43 
     44             SkCanvas canvas(bitmaps[j]);
     45 
     46             canvas.drawColor(SK_ColorRED);
     47 
     48             for (int k = 0; k < layerCombinations; ++k) {
     49                 // draw a rect within the layer's bounds and again outside the layer's bounds
     50                 canvas.saveLayerAlpha(&rect, layerAlpha[k], flags[k]);
     51 
     52                 SkCanvasState* state = NULL;
     53                 SkCanvas* tmpCanvas = NULL;
     54                 if (j) {
     55                     state = SkCanvasStateUtils::CaptureCanvasState(&canvas);
     56                     REPORTER_ASSERT(reporter, state);
     57                     tmpCanvas = SkCanvasStateUtils::CreateFromCanvasState(state);
     58                     REPORTER_ASSERT(reporter, tmpCanvas);
     59                 } else {
     60                     tmpCanvas = SkRef(&canvas);
     61                 }
     62 
     63                 SkPaint bluePaint;
     64                 bluePaint.setColor(SK_ColorBLUE);
     65                 bluePaint.setStyle(SkPaint::kFill_Style);
     66 
     67                 tmpCanvas->drawRect(rect, bluePaint);
     68                 tmpCanvas->translate(0, rect.height() + SPACER);
     69                 tmpCanvas->drawRect(rect, bluePaint);
     70 
     71                 tmpCanvas->unref();
     72                 SkCanvasStateUtils::ReleaseCanvasState(state);
     73 
     74                 canvas.restore();
     75 
     76                 // translate the canvas for the next iteration
     77                 canvas.translate(0, 2*(rect.height() + SPACER));
     78             }
     79         }
     80 
     81         // now we memcmp the two bitmaps
     82         REPORTER_ASSERT(reporter, bitmaps[0].getSize() == bitmaps[1].getSize());
     83         REPORTER_ASSERT(reporter, !memcmp(bitmaps[0].getPixels(),
     84                                           bitmaps[1].getPixels(),
     85                                           bitmaps[0].getSize()));
     86     }
     87 }
     88 
     89 ////////////////////////////////////////////////////////////////////////////////
     90 
     91 static void test_complex_clips(skiatest::Reporter* reporter) {
     92 
     93     const int WIDTH = 400;
     94     const int HEIGHT = 400;
     95     const SkScalar SPACER = SkIntToScalar(10);
     96 
     97     SkRect layerRect = SkRect::MakeWH(SkIntToScalar(WIDTH), SkIntToScalar(HEIGHT / 4));
     98     layerRect.inset(2*SPACER, 2*SPACER);
     99 
    100     SkRect clipRect = layerRect;
    101     clipRect.fRight = clipRect.fLeft + (clipRect.width() / 2) - (2*SPACER);
    102     clipRect.outset(SPACER, SPACER);
    103 
    104     SkIRect regionBounds;
    105     clipRect.roundIn(&regionBounds);
    106     regionBounds.offset(clipRect.width() + (2*SPACER), 0);
    107 
    108     SkIRect regionInterior = regionBounds;
    109     regionInterior.inset(SPACER*3, SPACER*3);
    110 
    111     SkRegion clipRegion;
    112     clipRegion.setRect(regionBounds);
    113     clipRegion.op(regionInterior, SkRegion::kDifference_Op);
    114 
    115 
    116     const SkRegion::Op clipOps[] = { SkRegion::kIntersect_Op,
    117                                      SkRegion::kIntersect_Op,
    118                                      SkRegion::kReplace_Op,
    119     };
    120     const SkCanvas::SaveFlags flags[] = { SkCanvas::kARGB_NoClipLayer_SaveFlag,
    121                                           SkCanvas::kARGB_ClipLayer_SaveFlag,
    122                                           SkCanvas::kARGB_NoClipLayer_SaveFlag,
    123     };
    124     REPORTER_ASSERT(reporter, sizeof(clipOps) == sizeof(flags));
    125     const int layerCombinations = sizeof(flags) / sizeof(SkCanvas::SaveFlags);
    126 
    127     SkBitmap bitmaps[2];
    128     for (int i = 0; i < 2; ++i) {
    129         bitmaps[i].setConfig(SkBitmap::kARGB_8888_Config, WIDTH, HEIGHT);
    130         bitmaps[i].allocPixels();
    131 
    132         SkCanvas canvas(bitmaps[i]);
    133 
    134         canvas.drawColor(SK_ColorRED);
    135 
    136         SkRegion localRegion = clipRegion;
    137 
    138         for (int j = 0; j < layerCombinations; ++j) {
    139             canvas.saveLayerAlpha(&layerRect, 128, flags[j]);
    140 
    141             SkCanvasState* state = NULL;
    142             SkCanvas* tmpCanvas = NULL;
    143             if (i) {
    144                 state = SkCanvasStateUtils::CaptureCanvasState(&canvas);
    145                 REPORTER_ASSERT(reporter, state);
    146                 tmpCanvas = SkCanvasStateUtils::CreateFromCanvasState(state);
    147                 REPORTER_ASSERT(reporter, tmpCanvas);
    148             } else {
    149                 tmpCanvas = SkRef(&canvas);
    150             }
    151 
    152             tmpCanvas->save();
    153             tmpCanvas->clipRect(clipRect, clipOps[j]);
    154             tmpCanvas->drawColor(SK_ColorBLUE);
    155             tmpCanvas->restore();
    156 
    157             tmpCanvas->clipRegion(localRegion, clipOps[j]);
    158             tmpCanvas->drawColor(SK_ColorBLUE);
    159 
    160             tmpCanvas->unref();
    161             SkCanvasStateUtils::ReleaseCanvasState(state);
    162 
    163             canvas.restore();
    164 
    165             // translate the canvas and region for the next iteration
    166             canvas.translate(0, 2*(layerRect.height() + SPACER));
    167             localRegion.translate(0, 2*(layerRect.height() + SPACER));
    168         }
    169     }
    170 
    171     // now we memcmp the two bitmaps
    172     REPORTER_ASSERT(reporter, bitmaps[0].getSize() == bitmaps[1].getSize());
    173     REPORTER_ASSERT(reporter, !memcmp(bitmaps[0].getPixels(),
    174                                       bitmaps[1].getPixels(),
    175                                       bitmaps[0].getSize()));
    176 }
    177 
    178 ////////////////////////////////////////////////////////////////////////////////
    179 
    180 class TestDrawFilter : public SkDrawFilter {
    181 public:
    182     virtual bool filter(SkPaint*, Type) SK_OVERRIDE { return true; }
    183 };
    184 
    185 static void test_draw_filters(skiatest::Reporter* reporter) {
    186     TestDrawFilter drawFilter;
    187     SkDevice device(SkBitmap::kARGB_8888_Config, 10, 10);
    188     SkCanvas canvas(&device);
    189 
    190     canvas.setDrawFilter(&drawFilter);
    191 
    192     SkCanvasState* state = SkCanvasStateUtils::CaptureCanvasState(&canvas);
    193     REPORTER_ASSERT(reporter, state);
    194     SkCanvas* tmpCanvas = SkCanvasStateUtils::CreateFromCanvasState(state);
    195     REPORTER_ASSERT(reporter, tmpCanvas);
    196 
    197     REPORTER_ASSERT(reporter, NULL != canvas.getDrawFilter());
    198     REPORTER_ASSERT(reporter, NULL == tmpCanvas->getDrawFilter());
    199 
    200     tmpCanvas->unref();
    201     SkCanvasStateUtils::ReleaseCanvasState(state);
    202 }
    203 
    204 ////////////////////////////////////////////////////////////////////////////////
    205 
    206 static void test_soft_clips(skiatest::Reporter* reporter) {
    207     SkDevice device(SkBitmap::kARGB_8888_Config, 10, 10);
    208     SkCanvas canvas(&device);
    209 
    210     SkRRect roundRect;
    211     roundRect.setOval(SkRect::MakeWH(5, 5));
    212 
    213     canvas.clipRRect(roundRect, SkRegion::kIntersect_Op, true);
    214 
    215     SkCanvasState* state = SkCanvasStateUtils::CaptureCanvasState(&canvas);
    216     REPORTER_ASSERT(reporter, !state);
    217 }
    218 
    219 ////////////////////////////////////////////////////////////////////////////////
    220 
    221 static void test_canvas_state_utils(skiatest::Reporter* reporter) {
    222     test_complex_layers(reporter);
    223     test_complex_clips(reporter);
    224     test_draw_filters(reporter);
    225     test_soft_clips(reporter);
    226 }
    227 
    228 #include "TestClassDef.h"
    229 DEFINE_TESTCLASS("CanvasState", TestCanvasStateClass, test_canvas_state_utils)
    230