1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#include "gm.h"
9#include "SkCanvas.h"
10#include "SkGradientShader.h"
11#include "SkGraphics.h"
12#include "SkPath.h"
13#include "SkRegion.h"
14#include "SkShader.h"
15
16static void make_bitmap(SkBitmap* bitmap) {
17    bitmap->allocN32Pixels(64, 64);
18
19    SkCanvas canvas(*bitmap);
20
21    canvas.drawColor(SK_ColorRED);
22    SkPaint paint;
23    paint.setAntiAlias(true);
24    const SkPoint pts[] = { { 0, 0 }, { 64, 64 } };
25    const SkColor colors[] = { SK_ColorWHITE, SK_ColorBLUE };
26    paint.setShader(SkGradientShader::CreateLinear(pts, colors, NULL, 2,
27                                                   SkShader::kClamp_TileMode))->unref();
28    canvas.drawCircle(32, 32, 32, paint);
29}
30
31class DrawBitmapRect2 : public skiagm::GM {
32    bool fUseIRect;
33public:
34    DrawBitmapRect2(bool useIRect) : fUseIRect(useIRect) {
35    }
36
37protected:
38    virtual SkString onShortName() SK_OVERRIDE {
39        SkString str;
40        str.printf("bitmaprect_%s", fUseIRect ? "i" : "s");
41        return str;
42    }
43
44    virtual SkISize onISize() SK_OVERRIDE {
45        return SkISize::Make(640, 480);
46    }
47
48#ifdef SK_CPU_ARM64
49    // Skip tiled drawing on 64-bit ARM until https://skbug.com/2908 is fixed.
50    virtual uint32_t onGetFlags() const SK_OVERRIDE {
51        return kSkipTiled_Flag;
52    }
53#endif
54
55    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
56        canvas->drawColor(0xFFCCCCCC);
57
58        const SkIRect src[] = {
59            { 0, 0, 32, 32 },
60            { 0, 0, 80, 80 },
61            { 32, 32, 96, 96 },
62            { -32, -32, 32, 32, }
63        };
64
65        SkPaint paint;
66        paint.setStyle(SkPaint::kStroke_Style);
67
68        SkBitmap bitmap;
69        make_bitmap(&bitmap);
70
71        SkRect dstR = { 0, 200, 128, 380 };
72
73        canvas->translate(16, 40);
74        for (size_t i = 0; i < SK_ARRAY_COUNT(src); i++) {
75            SkRect srcR;
76            srcR.set(src[i]);
77
78            canvas->drawBitmap(bitmap, 0, 0, &paint);
79            if (!fUseIRect) {
80                canvas->drawBitmapRectToRect(bitmap, &srcR, dstR, &paint);
81            } else {
82                canvas->drawBitmapRect(bitmap, &src[i], dstR, &paint);
83            }
84
85            canvas->drawRect(dstR, paint);
86            canvas->drawRect(srcR, paint);
87
88            canvas->translate(160, 0);
89        }
90    }
91
92private:
93    typedef skiagm::GM INHERITED;
94};
95
96//////////////////////////////////////////////////////////////////////////////
97static void make_3x3_bitmap(SkBitmap* bitmap) {
98
99    static const int gXSize = 3;
100    static const int gYSize = 3;
101
102    SkColor textureData[gXSize][gYSize] = {
103        { SK_ColorRED,    SK_ColorWHITE, SK_ColorBLUE },
104        { SK_ColorGREEN,  SK_ColorBLACK, SK_ColorCYAN },
105        { SK_ColorYELLOW, SK_ColorGRAY,  SK_ColorMAGENTA }
106    };
107
108
109    bitmap->allocN32Pixels(gXSize, gYSize);
110    for (int y = 0; y < gYSize; y++) {
111        for (int x = 0; x < gXSize; x++) {
112            *bitmap->getAddr32(x, y) = textureData[x][y];
113        }
114    }
115}
116
117// This GM attempts to make visible any issues drawBitmapRectToRect may have
118// with partial source rects. In this case the eight pixels on the border
119// should be half the width/height of the central pixel, i.e.:
120//                         __|____|__
121//                           |    |
122//                         __|____|__
123//                           |    |
124class DrawBitmapRect3 : public skiagm::GM {
125public:
126    DrawBitmapRect3() {
127        this->setBGColor(SK_ColorBLACK);
128    }
129
130protected:
131    virtual SkString onShortName() SK_OVERRIDE {
132        SkString str;
133        str.printf("3x3bitmaprect");
134        return str;
135    }
136
137    virtual SkISize onISize() SK_OVERRIDE {
138        return SkISize::Make(640, 480);
139    }
140
141    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
142
143        SkBitmap bitmap;
144        make_3x3_bitmap(&bitmap);
145
146        SkRect srcR = { 0.5f, 0.5f, 2.5f, 2.5f };
147        SkRect dstR = { 100, 100, 300, 200 };
148
149        canvas->drawBitmapRectToRect(bitmap, &srcR, dstR, NULL);
150    }
151
152private:
153    typedef skiagm::GM INHERITED;
154};
155
156//////////////////////////////////////////////////////////////////////////////
157static void make_big_bitmap(SkBitmap* bitmap) {
158
159    static const int gXSize = 4096;
160    static const int gYSize = 4096;
161    static const int gBorderWidth = 10;
162
163    bitmap->allocN32Pixels(gXSize, gYSize);
164    for (int y = 0; y < gYSize; ++y) {
165        for (int x = 0; x < gXSize; ++x) {
166            if (x <= gBorderWidth || x >= gXSize-gBorderWidth ||
167                y <= gBorderWidth || y >= gYSize-gBorderWidth) {
168                *bitmap->getAddr32(x, y) = 0x88FFFFFF;
169            } else {
170                *bitmap->getAddr32(x, y) = 0x88FF0000;
171            }
172        }
173    }
174}
175
176// This GM attempts to reveal any issues we may have when the GPU has to
177// break up a large texture in order to draw it. The XOR transfer mode will
178// create stripes in the image if there is imprecision in the destination
179// tile placement.
180class DrawBitmapRect4 : public skiagm::GM {
181    bool fUseIRect;
182    SkBitmap fBigBitmap;
183
184public:
185    DrawBitmapRect4(bool useIRect) : fUseIRect(useIRect) {
186        this->setBGColor(0x88444444);
187    }
188
189protected:
190    virtual SkString onShortName() SK_OVERRIDE {
191        SkString str;
192        str.printf("bigbitmaprect_%s", fUseIRect ? "i" : "s");
193        return str;
194    }
195
196    virtual SkISize onISize() SK_OVERRIDE {
197        return SkISize::Make(640, 480);
198    }
199
200    virtual void onOnceBeforeDraw() SK_OVERRIDE {
201        make_big_bitmap(&fBigBitmap);
202    }
203
204    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
205
206        SkXfermode* mode = SkXfermode::Create(SkXfermode::kXor_Mode);
207
208        SkPaint paint;
209        paint.setAlpha(128);
210        paint.setXfermode(mode)->unref();
211
212        SkRect srcR1 = { 0.0f, 0.0f, 4096.0f, 2040.0f };
213        SkRect dstR1 = { 10.1f, 10.1f, 629.9f, 400.9f };
214
215        SkRect srcR2 = { 4085.0f, 10.0f, 4087.0f, 12.0f };
216        SkRect dstR2 = { 10, 410, 30, 430 };
217
218        if (!fUseIRect) {
219            canvas->drawBitmapRectToRect(fBigBitmap, &srcR1, dstR1, &paint);
220            canvas->drawBitmapRectToRect(fBigBitmap, &srcR2, dstR2, &paint);
221        } else {
222            SkIRect iSrcR1, iSrcR2;
223
224            srcR1.roundOut(&iSrcR1);
225            srcR2.roundOut(&iSrcR2);
226
227            canvas->drawBitmapRect(fBigBitmap, &iSrcR1, dstR1, &paint);
228            canvas->drawBitmapRect(fBigBitmap, &iSrcR2, dstR2, &paint);
229        }
230    }
231
232private:
233    typedef skiagm::GM INHERITED;
234};
235
236//////////////////////////////////////////////////////////////////////////////
237
238static skiagm::GM* MyFactory0(void*) { return new DrawBitmapRect2(false); }
239static skiagm::GM* MyFactory1(void*) { return new DrawBitmapRect2(true); }
240
241static skiagm::GM* MyFactory2(void*) { return new DrawBitmapRect3(); }
242
243#ifndef SK_BUILD_FOR_ANDROID
244static skiagm::GM* MyFactory3(void*) { return new DrawBitmapRect4(false); }
245static skiagm::GM* MyFactory4(void*) { return new DrawBitmapRect4(true); }
246#endif
247
248static skiagm::GMRegistry reg0(MyFactory0);
249static skiagm::GMRegistry reg1(MyFactory1);
250
251static skiagm::GMRegistry reg2(MyFactory2);
252
253#ifndef SK_BUILD_FOR_ANDROID
254static skiagm::GMRegistry reg3(MyFactory3);
255static skiagm::GMRegistry reg4(MyFactory4);
256#endif
257