Home | History | Annotate | Download | only in gm
      1 /*
      2  * Copyright 2014 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 "gm.h"
      9 #include "sk_tool_utils.h"
     10 
     11 #include "SkBitmap.h"
     12 #include "SkPaint.h"
     13 #include "SkPicture.h"
     14 #include "SkPictureRecorder.h"
     15 #include "SkShader.h"
     16 
     17 static struct {
     18     SkShader::TileMode tmx;
     19     SkShader::TileMode tmy;
     20 } kTileConfigs[] = {
     21     { SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode },
     22     { SkShader::kRepeat_TileMode, SkShader::kClamp_TileMode  },
     23     { SkShader::kMirror_TileMode, SkShader::kRepeat_TileMode },
     24 };
     25 
     26 class PictureShaderGM : public skiagm::GM {
     27 public:
     28     PictureShaderGM(SkScalar tileSize, SkScalar sceneSize, bool useLocalMatrixWrapper = false)
     29         : fTileSize(tileSize)
     30         , fSceneSize(sceneSize)
     31         , fUseLocalMatrixWrapper(useLocalMatrixWrapper) {}
     32 
     33  protected:
     34     void onOnceBeforeDraw() override {
     35        // Build the picture.
     36         SkPictureRecorder recorder;
     37         SkCanvas* pictureCanvas = recorder.beginRecording(fTileSize, fTileSize, nullptr, 0);
     38         this->drawTile(pictureCanvas);
     39         fPicture = recorder.finishRecordingAsPicture();
     40 
     41         // Build a reference bitmap.
     42         fBitmap.allocN32Pixels(SkScalarCeilToInt(fTileSize), SkScalarCeilToInt(fTileSize));
     43         fBitmap.eraseColor(SK_ColorTRANSPARENT);
     44         SkCanvas bitmapCanvas(fBitmap);
     45         this->drawTile(&bitmapCanvas);
     46     }
     47 
     48 
     49     SkString onShortName() override {
     50         return SkStringPrintf("pictureshader%s", fUseLocalMatrixWrapper ? "_localwrapper" : "");
     51     }
     52 
     53     SkISize onISize() override {
     54         return SkISize::Make(1400, 1450);
     55     }
     56 
     57     void onDraw(SkCanvas* canvas) override {
     58         this->drawSceneColumn(canvas, SkPoint::Make(0, 0), 1, 1, 0);
     59         this->drawSceneColumn(canvas, SkPoint::Make(0, fSceneSize * 6.4f), 1, 2, 0);
     60         this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 2.4f, 0), 1, 1, 1);
     61         this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 2.4f, fSceneSize * 6.4f), 1, 1, 2);
     62         this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 4.8f, 0), 2, 1, 0);
     63         this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 9.6f, 0), 2, 2, 0);
     64 
     65         // One last custom row to exercise negative scaling
     66         SkMatrix ctm, localMatrix;
     67         ctm.setTranslate(fSceneSize * 2.1f, fSceneSize * 13.8f);
     68         ctm.preScale(-1, -1);
     69         localMatrix.setScale(2, 2);
     70         this->drawScene(canvas, ctm, localMatrix, 0);
     71 
     72         ctm.setTranslate(fSceneSize * 2.4f, fSceneSize * 12.8f);
     73         localMatrix.setScale(-1, -1);
     74         this->drawScene(canvas, ctm, localMatrix, 0);
     75 
     76         ctm.setTranslate(fSceneSize * 4.8f, fSceneSize * 12.3f);
     77         ctm.preScale(2, 2);
     78         this->drawScene(canvas, ctm, localMatrix, 0);
     79 
     80         ctm.setTranslate(fSceneSize * 13.8f, fSceneSize * 14.3f);
     81         ctm.preScale(-2, -2);
     82         localMatrix.setTranslate(fTileSize / 4, fTileSize / 4);
     83         localMatrix.preRotate(45);
     84         localMatrix.preScale(-2, -2);
     85         this->drawScene(canvas, ctm, localMatrix, 0);
     86     }
     87 
     88 private:
     89     void drawSceneColumn(SkCanvas* canvas, const SkPoint& pos, SkScalar scale, SkScalar localScale,
     90                          unsigned tileMode) {
     91         SkMatrix ctm, localMatrix;
     92 
     93         ctm.setTranslate(pos.x(), pos.y());
     94         ctm.preScale(scale, scale);
     95         localMatrix.setScale(localScale, localScale);
     96         this->drawScene(canvas, ctm, localMatrix, tileMode);
     97 
     98         ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 1.2f * scale);
     99         ctm.preScale(scale, scale);
    100         localMatrix.setTranslate(fTileSize / 4, fTileSize / 4);
    101         localMatrix.preScale(localScale, localScale);
    102         this->drawScene(canvas, ctm, localMatrix, tileMode);
    103 
    104         ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 2.4f * scale);
    105         ctm.preScale(scale, scale);
    106         localMatrix.setRotate(45);
    107         localMatrix.preScale(localScale, localScale);
    108         this->drawScene(canvas, ctm, localMatrix, tileMode);
    109 
    110         ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 3.6f * scale);
    111         ctm.preScale(scale, scale);
    112         localMatrix.setSkew(1, 0);
    113         localMatrix.preScale(localScale, localScale);
    114         this->drawScene(canvas, ctm, localMatrix, tileMode);
    115 
    116         ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 4.8f * scale);
    117         ctm.preScale(scale, scale);
    118         localMatrix.setTranslate(fTileSize / 4, fTileSize / 4);
    119         localMatrix.preRotate(45);
    120         localMatrix.preScale(localScale, localScale);
    121         this->drawScene(canvas, ctm, localMatrix, tileMode);
    122     }
    123 
    124     void drawTile(SkCanvas* canvas) {
    125         SkPaint paint;
    126         paint.setColor(SK_ColorGREEN);
    127         paint.setStyle(SkPaint::kFill_Style);
    128         paint.setAntiAlias(true);
    129 
    130         canvas->drawCircle(fTileSize / 4, fTileSize / 4, fTileSize / 4, paint);
    131         canvas->drawRect(SkRect::MakeXYWH(fTileSize / 2, fTileSize / 2,
    132                                           fTileSize / 2, fTileSize / 2), paint);
    133 
    134         paint.setColor(SK_ColorRED);
    135         canvas->drawLine(fTileSize / 2, fTileSize * 1 / 3,
    136                          fTileSize / 2, fTileSize * 2 / 3, paint);
    137         canvas->drawLine(fTileSize * 1 / 3, fTileSize / 2,
    138                          fTileSize * 2 / 3, fTileSize / 2, paint);
    139     }
    140 
    141     void drawScene(SkCanvas* canvas, const SkMatrix& matrix, const SkMatrix& localMatrix,
    142                    unsigned tileMode) {
    143         SkASSERT(tileMode < SK_ARRAY_COUNT(kTileConfigs));
    144 
    145         SkPaint paint;
    146         paint.setStyle(SkPaint::kFill_Style);
    147         paint.setColor(SK_ColorLTGRAY);
    148 
    149         canvas->save();
    150         canvas->concat(matrix);
    151         canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
    152         canvas->drawRect(SkRect::MakeXYWH(fSceneSize * 1.1f, 0, fSceneSize, fSceneSize), paint);
    153 
    154         auto pictureShader = SkShader::MakePictureShader(fPicture, kTileConfigs[tileMode].tmx,
    155                                                          kTileConfigs[tileMode].tmy,
    156                                                          fUseLocalMatrixWrapper
    157                                                             ? nullptr : &localMatrix,
    158                                                          nullptr);
    159         paint.setShader(fUseLocalMatrixWrapper
    160                             ? pictureShader->makeWithLocalMatrix(localMatrix)
    161                             : pictureShader);
    162         canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
    163 
    164         canvas->translate(fSceneSize * 1.1f, 0);
    165 
    166         auto bitmapShader = SkShader::MakeBitmapShader(fBitmap,
    167                                                        kTileConfigs[tileMode].tmx,
    168                                                        kTileConfigs[tileMode].tmy,
    169                                                        fUseLocalMatrixWrapper
    170                                                            ? nullptr : &localMatrix);
    171         paint.setShader(fUseLocalMatrixWrapper
    172                             ? bitmapShader->makeWithLocalMatrix(localMatrix)
    173                             : bitmapShader);
    174         canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
    175 
    176         canvas->restore();
    177     }
    178 
    179     sk_sp<SkPicture> fPicture;
    180     SkBitmap fBitmap;
    181 
    182     SkScalar    fTileSize;
    183     SkScalar    fSceneSize;
    184     bool        fUseLocalMatrixWrapper;
    185 
    186     typedef GM INHERITED;
    187 };
    188 
    189 DEF_GM(return new PictureShaderGM(50, 100);)
    190 DEF_GM(return new PictureShaderGM(50, 100, true);)
    191 
    192 DEF_SIMPLE_GM(tiled_picture_shader, canvas, 400, 400) {
    193     // https://code.google.com/p/skia/issues/detail?id=3398
    194     SkRect tile = SkRect::MakeWH(100, 100);
    195 
    196     SkPictureRecorder recorder;
    197     SkCanvas* c = recorder.beginRecording(tile);
    198 
    199     SkRect r = tile;
    200     r.inset(4, 4);
    201     SkPaint p;
    202     p.setColor(sk_tool_utils::color_to_565(0xFF303F9F));  // dark blue
    203     c->drawRect(r, p);
    204     p.setColor(sk_tool_utils::color_to_565(0xFFC5CAE9));  // light blue
    205     p.setStrokeWidth(10);
    206     c->drawLine(20, 20, 80, 80, p);
    207 
    208     sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
    209 
    210     p.setColor(sk_tool_utils::color_to_565(0xFF8BC34A));  // green
    211     canvas->drawPaint(p);
    212 
    213     canvas->clipRect(SkRect::MakeXYWH(0, 0, 400, 350));
    214     p.setColor(0xFFB6B6B6);  // gray
    215     canvas->drawPaint(p);
    216 
    217     p.setShader(SkShader::MakePictureShader(std::move(picture), SkShader::kRepeat_TileMode,
    218                                             SkShader::kRepeat_TileMode,
    219                                             nullptr, nullptr));
    220     canvas->drawPaint(p);
    221 }
    222