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