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)
     29         : fTileSize(tileSize)
     30         , fSceneSize(sceneSize) {
     31     }
     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 SkString("pictureshader");
     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_tool_utils::color_to_565(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         paint.setShader(SkShader::MakePictureShader(fPicture, kTileConfigs[tileMode].tmx,
    155                                                     kTileConfigs[tileMode].tmy, &localMatrix,
    156                                                     nullptr));
    157         canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
    158 
    159         canvas->translate(fSceneSize * 1.1f, 0);
    160 
    161         paint.setShader(SkShader::MakeBitmapShader(fBitmap,
    162                                                    kTileConfigs[tileMode].tmx,
    163                                                    kTileConfigs[tileMode].tmy,
    164                                                    &localMatrix));
    165         canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint);
    166 
    167         canvas->restore();
    168     }
    169 
    170     SkScalar    fTileSize;
    171     SkScalar    fSceneSize;
    172 
    173     sk_sp<SkPicture> fPicture;
    174     SkBitmap fBitmap;
    175 
    176     typedef GM INHERITED;
    177 };
    178 
    179 DEF_GM(return new PictureShaderGM(50, 100);)
    180 
    181 DEF_SIMPLE_GM(tiled_picture_shader, canvas, 400, 400) {
    182     // https://code.google.com/p/skia/issues/detail?id=3398
    183     SkRect tile = SkRect::MakeWH(100, 100);
    184 
    185     SkPictureRecorder recorder;
    186     SkCanvas* c = recorder.beginRecording(tile);
    187 
    188     SkRect r = tile;
    189     r.inset(4, 4);
    190     SkPaint p;
    191     p.setColor(sk_tool_utils::color_to_565(0xFF303F9F));  // dark blue
    192     c->drawRect(r, p);
    193     p.setColor(sk_tool_utils::color_to_565(0xFFC5CAE9));  // light blue
    194     p.setStrokeWidth(10);
    195     c->drawLine(20, 20, 80, 80, p);
    196 
    197     sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
    198 
    199     p.setColor(sk_tool_utils::color_to_565(0xFF8BC34A));  // green
    200     canvas->drawPaint(p);
    201 
    202     canvas->clipRect(SkRect::MakeXYWH(0, 0, 400, 350));
    203     p.setColor(sk_tool_utils::color_to_565(0xFFB6B6B6));  // gray
    204     canvas->drawPaint(p);
    205 
    206     p.setShader(SkShader::MakePictureShader(std::move(picture), SkShader::kRepeat_TileMode,
    207                                             SkShader::kRepeat_TileMode,
    208                                             nullptr, nullptr));
    209     canvas->drawPaint(p);
    210 }
    211