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
10namespace skiagm {
11
12/** Create a bitmap image suitable for testing SkBitmap::scrollRect().
13 *
14 *  @param quarterWidth bitmap will be 4x this many pixels wide
15 *  @param quarterHeight bitmap will be 4x this many pixels tall
16 *  @param bitmap the bitmap data is written into this object
17 */
18static void make_bitmap(int quarterWidth, int quarterHeight, SkBitmap *bitmap) {
19    SkPaint pRed, pWhite, pGreen, pBlue, pLine, pAlphaGray;
20    pRed.setColor(0xFFFF9999);
21    pWhite.setColor(0xFFFFFFFF);
22    pGreen.setColor(0xFF99FF99);
23    pBlue.setColor(0xFF9999FF);
24    pLine.setColor(0xFF000000);
25    pLine.setStyle(SkPaint::kStroke_Style);
26    pAlphaGray.setColor(0x66888888);
27
28    // Prepare bitmap, and a canvas that draws into it.
29    bitmap->allocN32Pixels(quarterWidth*4, quarterHeight*4);
30    SkCanvas canvas(*bitmap);
31
32    SkScalar w = SkIntToScalar(quarterWidth);
33    SkScalar h = SkIntToScalar(quarterHeight);
34    canvas.drawRectCoords(  0,   0, w*2, h*2, pRed);
35    canvas.drawRectCoords(w*2,   0, w*4, h*2, pGreen);
36    canvas.drawRectCoords(  0, h*2, w*2, h*4, pBlue);
37    canvas.drawRectCoords(w*2, h*2, w*4, h*4, pWhite);
38    canvas.drawRectCoords(w, h, w*3, h*3, pAlphaGray);
39    canvas.drawLine(w*2,   0, w*2, h*4, pLine);
40    canvas.drawLine(  0, h*2, w*4, h*2, pLine);
41    canvas.drawRectCoords(w, h, w*3, h*3, pLine);
42}
43
44class BitmapScrollGM : public GM {
45    bool fInited;
46    void init() {
47        if (fInited) {
48            return;
49        }
50        fInited = true;
51        // Create the original bitmap.
52        make_bitmap(quarterWidth, quarterHeight, &origBitmap);
53    }
54
55public:
56    BitmapScrollGM() {
57        fInited = false;
58        this->setBGColor(0xFFDDDDDD);
59    }
60
61protected:
62    virtual uint32_t onGetFlags() const SK_OVERRIDE {
63        return kSkipTiled_Flag;
64    }
65
66    virtual SkString onShortName() {
67        return SkString("bitmapscroll");
68    }
69
70    virtual SkISize onISize() {
71      return SkISize::Make(800, 600);
72    }
73
74    virtual void onDraw(SkCanvas* canvas) {
75        this->init();
76        SkIRect scrollCenterRegion = SkIRect::MakeXYWH(
77            quarterWidth, quarterHeight, quarterWidth*2+1, quarterHeight*2+1);
78        int x = quarterWidth;
79        int y = quarterHeight;
80        int xSpacing = quarterWidth * 20;
81        int ySpacing = quarterHeight * 16;
82
83        // Draw left-hand text labels.
84        drawLabel(canvas, "scroll entire bitmap",
85                  x, y, x, y + ySpacing);
86        drawLabel(canvas, "scroll part of bitmap",
87                  x, y + ySpacing, x, y + ySpacing*2);
88        x += 30;
89
90        // Draw various permutations of scrolled bitmaps, scrolling a bit
91        // further each time.
92        draw9(canvas, x, y, NULL, quarterWidth*1/2, quarterHeight*1/2);
93        draw9(canvas, x, y+ySpacing, &scrollCenterRegion,
94              quarterWidth*1/2, quarterHeight*1/2);
95        x += xSpacing;
96        draw9(canvas, x, y, NULL, quarterWidth*3/2, quarterHeight*3/2);
97        draw9(canvas, x, y+ySpacing, &scrollCenterRegion,
98              quarterWidth*3/2, quarterHeight*3/2);
99        x += xSpacing;
100        draw9(canvas, x, y, NULL, quarterWidth*5/2, quarterHeight*5/2);
101        draw9(canvas, x, y+ySpacing, &scrollCenterRegion,
102              quarterWidth*5/2, quarterHeight*5/2);
103        x += xSpacing;
104        draw9(canvas, x, y, NULL, quarterWidth*9/2, quarterHeight*9/2);
105        draw9(canvas, x, y+ySpacing, &scrollCenterRegion,
106              quarterWidth*9/2, quarterHeight*9/2);
107    }
108
109    void drawLabel(SkCanvas* canvas, const char *text, int startX, int startY,
110                 int endX, int endY) {
111        SkPaint paint;
112        paint.setColor(0xFF000000);
113        SkPath path;
114        path.moveTo(SkIntToScalar(startX), SkIntToScalar(startY));
115        path.lineTo(SkIntToScalar(endX), SkIntToScalar(endY));
116        canvas->drawTextOnPath(text, strlen(text), path, NULL, paint);
117    }
118
119    /** Stamp out 9 copies of origBitmap, scrolled in each direction (and
120     *  not scrolled at all).
121     */
122    void draw9(SkCanvas* canvas, int x, int y, SkIRect* subset,
123               int scrollX, int scrollY) {
124        for (int yMult=-1; yMult<=1; yMult++) {
125            for (int xMult=-1; xMult<=1; xMult++) {
126                // Figure out the (x,y) to draw this copy at
127                SkScalar bitmapX = SkIntToScalar(
128                    x + quarterWidth * 5 * (xMult+1));
129                SkScalar bitmapY = SkIntToScalar(
130                    y + quarterHeight * 5 * (yMult+1));
131
132                // Scroll a new copy of the bitmap, and then draw it.
133                // scrollRect() should always return true, even if it's a no-op
134                SkBitmap scrolledBitmap;
135                SkDEBUGCODE(bool copyToReturnValue = )origBitmap.copyTo(
136                    &scrolledBitmap, origBitmap.colorType());
137                SkASSERT(copyToReturnValue);
138                SkDEBUGCODE(bool scrollRectReturnValue = )scrolledBitmap.scrollRect(
139                    subset, scrollX * xMult, scrollY * yMult);
140                SkASSERT(scrollRectReturnValue);
141                canvas->drawBitmap(scrolledBitmap, bitmapX, bitmapY);
142            }
143        }
144    }
145
146private:
147    typedef GM INHERITED;
148    static const int quarterWidth = 10;
149    static const int quarterHeight = 14;
150    SkBitmap origBitmap;
151};
152
153//////////////////////////////////////////////////////////////////////////////
154
155static GM* MyFactory(void*) { return new BitmapScrollGM; }
156static GMRegistry reg(MyFactory);
157
158}
159