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 "SkCanvas.h"
10#include "SkRSXform.h"
11#include "SkSurface.h"
12
13// Create a square atlas of:
14//   opaque white  |     opaque red
15//  ------------------------------------
16//   opaque green  |  transparent black
17//
18static SkImage* make_atlas(SkCanvas* caller, int atlasSize) {
19    const int kBlockSize = atlasSize/2;
20
21    SkImageInfo info = SkImageInfo::MakeN32Premul(atlasSize, atlasSize);
22    SkAutoTUnref<SkSurface> surface(caller->newSurface(info));
23    if (nullptr == surface) {
24        surface.reset(SkSurface::NewRaster(info));
25    }
26    SkCanvas* canvas = surface->getCanvas();
27
28    SkPaint paint;
29    paint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode));
30
31    paint.setColor(SK_ColorWHITE);
32    SkRect r = SkRect::MakeXYWH(0, 0,
33                                SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
34    canvas->drawRect(r, paint);
35
36    paint.setColor(SK_ColorRED);
37    r = SkRect::MakeXYWH(SkIntToScalar(kBlockSize), 0,
38                         SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
39    canvas->drawRect(r, paint);
40
41    paint.setColor(SK_ColorGREEN);
42    r = SkRect::MakeXYWH(0, SkIntToScalar(kBlockSize),
43                         SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
44    canvas->drawRect(r, paint);
45
46    paint.setColor(SK_ColorTRANSPARENT);
47    r = SkRect::MakeXYWH(SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize),
48                         SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
49    canvas->drawRect(r, paint);
50
51    return surface->newImageSnapshot();
52}
53
54// This GM tests the drawAtlas API with colors, different xfer modes
55// and transparency in the atlas image
56class DrawAtlasColorsGM : public skiagm::GM {
57public:
58    DrawAtlasColorsGM() {
59        this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
60    }
61
62protected:
63    SkString onShortName() override {
64        return SkString("draw-atlas-colors");
65    }
66
67    SkISize onISize() override {
68        return SkISize::Make(kNumXferModes * (kAtlasSize + kPad) + kPad,
69                             2 * kNumColors * (kAtlasSize + kPad) + kTextPad + kPad);
70    }
71
72    void onDraw(SkCanvas* canvas) override {
73        const SkRect target = SkRect::MakeWH(SkIntToScalar(kAtlasSize), SkIntToScalar(kAtlasSize));
74
75        if (nullptr == fAtlas) {
76            fAtlas.reset(make_atlas(canvas, kAtlasSize));
77        }
78
79        const struct {
80            SkXfermode::Mode fMode;
81            const char*      fLabel;
82        } gModes[] = {
83            { SkXfermode::kClear_Mode,      "Clear"     },
84            { SkXfermode::kSrc_Mode,        "Src"       },
85            { SkXfermode::kDst_Mode,        "Dst"       },
86            { SkXfermode::kSrcOver_Mode,    "SrcOver"   },
87            { SkXfermode::kDstOver_Mode,    "DstOver"   },
88            { SkXfermode::kSrcIn_Mode,      "SrcIn"     },
89            { SkXfermode::kDstIn_Mode,      "DstIn"     },
90            { SkXfermode::kSrcOut_Mode,     "SrcOut"    },
91            { SkXfermode::kDstOut_Mode,     "DstOut"    },
92            { SkXfermode::kSrcATop_Mode,    "SrcATop"   },
93            { SkXfermode::kDstATop_Mode,    "DstATop"   },
94            { SkXfermode::kXor_Mode,        "Xor"       },
95            { SkXfermode::kPlus_Mode,       "Plus"      },
96            { SkXfermode::kModulate_Mode,   "Mod"       },
97            { SkXfermode::kScreen_Mode,     "Screen"    },
98            { SkXfermode::kOverlay_Mode,    "Overlay"   },
99            { SkXfermode::kDarken_Mode,     "Darken"    },
100            { SkXfermode::kLighten_Mode,    "Lighten"   },
101            { SkXfermode::kColorDodge_Mode, "Dodge"     },
102            { SkXfermode::kColorBurn_Mode,  "Burn"      },
103            { SkXfermode::kHardLight_Mode,  "Hard"      },
104            { SkXfermode::kSoftLight_Mode,  "Soft"      },
105            { SkXfermode::kDifference_Mode, "Diff"      },
106            { SkXfermode::kExclusion_Mode,  "Exclusion" },
107            { SkXfermode::kMultiply_Mode,   "Multiply"  },
108            { SkXfermode::kHue_Mode,        "Hue"       },
109            { SkXfermode::kSaturation_Mode, "Sat"       },
110            { SkXfermode::kColor_Mode,      "Color"     },
111            { SkXfermode::kLuminosity_Mode, "Luminosity"},
112        };
113
114        SkColor gColors[] = {
115            SK_ColorWHITE,
116            SK_ColorRED,
117            0x88888888,         // transparent grey
118            0x88000088          // transparent blue
119        };
120
121        const int numModes = SK_ARRAY_COUNT(gModes);
122        SkASSERT(numModes == kNumXferModes);
123        const int numColors = SK_ARRAY_COUNT(gColors);
124        SkASSERT(numColors == kNumColors);
125        SkRSXform xforms[numColors];
126        SkRect rects[numColors];
127        SkColor quadColors[numColors];
128
129        SkPaint paint;
130        paint.setAntiAlias(true);
131
132        for (int i = 0; i < numColors; ++i) {
133            xforms[i].set(1.0f, 0.0f, SkIntToScalar(kPad), i*(target.width()+kPad));
134            rects[i] = target;
135            quadColors[i] = gColors[i];
136        }
137
138        SkPaint textP;
139        textP.setTextSize(SkIntToScalar(kTextPad));
140        textP.setAntiAlias(true);
141        sk_tool_utils::set_portable_typeface(&textP, nullptr);
142
143        for (int i = 0; i < numModes; ++i) {
144            canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel),
145                             i*(target.width()+kPad)+kPad, SkIntToScalar(kTextPad),
146                             textP);
147        }
148
149        for (int i = 0; i < numModes; ++i) {
150            canvas->save();
151            canvas->translate(SkIntToScalar(i*(target.height()+kPad)),
152                              SkIntToScalar(kTextPad+kPad));
153            // w/o a paint
154            canvas->drawAtlas(fAtlas, xforms, rects, quadColors, numColors,
155                              gModes[i].fMode, nullptr, nullptr);
156            canvas->translate(0.0f, numColors*(target.height()+kPad));
157            // w a paint
158            canvas->drawAtlas(fAtlas, xforms, rects, quadColors, numColors,
159                              gModes[i].fMode, nullptr, &paint);
160            canvas->restore();
161        }
162    }
163
164private:
165    static const int kNumXferModes = 29;
166    static const int kNumColors = 4;
167    static const int kAtlasSize = 30;
168    static const int kPad = 2;
169    static const int kTextPad = 8;
170
171
172    SkAutoTUnref<SkImage> fAtlas;
173
174    typedef GM INHERITED;
175};
176DEF_GM( return new DrawAtlasColorsGM; )
177
178