1/*
2 * Copyright 2015 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#include "SkCanvas.h"
11#include "SkRSXform.h"
12#include "SkSurface.h"
13
14// Create a square atlas of:
15//   opaque white  |     opaque red
16//  ------------------------------------
17//   opaque green  |  transparent black
18//
19static sk_sp<SkImage> make_atlas(SkCanvas* caller, int atlasSize) {
20    const int kBlockSize = atlasSize/2;
21
22    SkImageInfo info = SkImageInfo::MakeN32Premul(atlasSize, atlasSize);
23    auto surface(sk_tool_utils::makeSurface(caller, info));
24    SkCanvas* canvas = surface->getCanvas();
25
26    SkPaint paint;
27    paint.setBlendMode(SkBlendMode::kSrc);
28
29    paint.setColor(SK_ColorWHITE);
30    SkRect r = SkRect::MakeXYWH(0, 0,
31                                SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
32    canvas->drawRect(r, paint);
33
34    paint.setColor(SK_ColorRED);
35    r = SkRect::MakeXYWH(SkIntToScalar(kBlockSize), 0,
36                         SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
37    canvas->drawRect(r, paint);
38
39    paint.setColor(SK_ColorGREEN);
40    r = SkRect::MakeXYWH(0, SkIntToScalar(kBlockSize),
41                         SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
42    canvas->drawRect(r, paint);
43
44    paint.setColor(SK_ColorTRANSPARENT);
45    r = SkRect::MakeXYWH(SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize),
46                         SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
47    canvas->drawRect(r, paint);
48
49    return surface->makeImageSnapshot();
50}
51
52// This GM tests the drawAtlas API with colors, different xfer modes
53// and transparency in the atlas image
54class DrawAtlasColorsGM : public skiagm::GM {
55public:
56    DrawAtlasColorsGM() {
57        this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
58    }
59
60protected:
61    SkString onShortName() override {
62        return SkString("draw-atlas-colors");
63    }
64
65    SkISize onISize() override {
66        return SkISize::Make(kNumXferModes * (kAtlasSize + kPad) + kPad,
67                             2 * kNumColors * (kAtlasSize + kPad) + kTextPad + kPad);
68    }
69
70    void onDraw(SkCanvas* canvas) override {
71        const SkRect target = SkRect::MakeWH(SkIntToScalar(kAtlasSize), SkIntToScalar(kAtlasSize));
72
73        auto atlas = make_atlas(canvas, kAtlasSize);
74
75        const SkBlendMode gModes[] = {
76            SkBlendMode::kClear,
77            SkBlendMode::kSrc,
78            SkBlendMode::kDst,
79            SkBlendMode::kSrcOver,
80            SkBlendMode::kDstOver,
81            SkBlendMode::kSrcIn,
82            SkBlendMode::kDstIn,
83            SkBlendMode::kSrcOut,
84            SkBlendMode::kDstOut,
85            SkBlendMode::kSrcATop,
86            SkBlendMode::kDstATop,
87            SkBlendMode::kXor,
88            SkBlendMode::kPlus,
89            SkBlendMode::kModulate,
90            SkBlendMode::kScreen,
91            SkBlendMode::kOverlay,
92            SkBlendMode::kDarken,
93            SkBlendMode::kLighten,
94            SkBlendMode::kColorDodge,
95            SkBlendMode::kColorBurn,
96            SkBlendMode::kHardLight,
97            SkBlendMode::kSoftLight,
98            SkBlendMode::kDifference,
99            SkBlendMode::kExclusion,
100            SkBlendMode::kMultiply,
101            SkBlendMode::kHue,
102            SkBlendMode::kSaturation,
103            SkBlendMode::kColor,
104            SkBlendMode::kLuminosity,
105        };
106
107        SkColor gColors[] = {
108            SK_ColorWHITE,
109            SK_ColorRED,
110            0x88888888,         // transparent grey
111            0x88000088          // transparent blue
112        };
113
114        const int numModes = SK_ARRAY_COUNT(gModes);
115        SkASSERT(numModes == kNumXferModes);
116        const int numColors = SK_ARRAY_COUNT(gColors);
117        SkASSERT(numColors == kNumColors);
118        SkRSXform xforms[numColors];
119        SkRect rects[numColors];
120        SkColor quadColors[numColors];
121
122        SkPaint paint;
123        paint.setAntiAlias(true);
124
125        for (int i = 0; i < numColors; ++i) {
126            xforms[i].set(1.0f, 0.0f, SkIntToScalar(kPad), i*(target.width()+kPad));
127            rects[i] = target;
128            quadColors[i] = gColors[i];
129        }
130
131        SkPaint textP;
132        textP.setTextSize(SkIntToScalar(kTextPad));
133        textP.setAntiAlias(true);
134        sk_tool_utils::set_portable_typeface(&textP, nullptr);
135
136        for (int i = 0; i < numModes; ++i) {
137            const char* label = SkBlendMode_Name(gModes[i]);
138            canvas->drawString(label,
139                             i*(target.width()+kPad)+kPad, SkIntToScalar(kTextPad),
140                             textP);
141        }
142
143        for (int i = 0; i < numModes; ++i) {
144            canvas->save();
145            canvas->translate(SkIntToScalar(i*(target.height()+kPad)),
146                              SkIntToScalar(kTextPad+kPad));
147            // w/o a paint
148            canvas->drawAtlas(atlas.get(), xforms, rects, quadColors, numColors,
149                              gModes[i], nullptr, nullptr);
150            canvas->translate(0.0f, numColors*(target.height()+kPad));
151            // w a paint
152            canvas->drawAtlas(atlas.get(), xforms, rects, quadColors, numColors,
153                              gModes[i], nullptr, &paint);
154            canvas->restore();
155        }
156    }
157
158private:
159    static constexpr int kNumXferModes = 29;
160    static constexpr int kNumColors = 4;
161    static constexpr int kAtlasSize = 30;
162    static constexpr int kPad = 2;
163    static constexpr int kTextPad = 8;
164
165    typedef GM INHERITED;
166};
167DEF_GM( return new DrawAtlasColorsGM; )
168