downsamplebitmap.cpp revision e2cf805e9ae57f259307ab0834dd23dfe468c316
1/*
2 * Copyright 2013 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 "SkGradientShader.h"
10
11#include "SkTypeface.h"
12#include "SkImageDecoder.h"
13#include "SkStream.h"
14#include "SkPaint.h"
15
16static void setTypeface(SkPaint* paint, const char name[], SkTypeface::Style style) {
17    SkSafeUnref(paint->setTypeface(SkTypeface::CreateFromName(name, style)));
18}
19
20class DownsampleBitmapGM : public skiagm::GM {
21
22public:
23    SkBitmap    fBM;
24    SkString    fName;
25    bool        fBitmapMade;
26    SkPaint::FilterLevel fFilterLevel;
27
28    DownsampleBitmapGM(SkPaint::FilterLevel filterLevel)
29        : fFilterLevel(filterLevel)
30    {
31        this->setBGColor(0xFFDDDDDD);
32        fBitmapMade = false;
33    }
34
35    const char* filterLevelToString() {
36        static const char *filterLevelNames[] = {
37            "none", "low", "medium", "high"
38        };
39        return filterLevelNames[fFilterLevel];
40    }
41
42protected:
43    virtual SkString onShortName() SK_OVERRIDE {
44        return fName;
45    }
46
47    virtual SkISize onISize() SK_OVERRIDE {
48        make_bitmap_wrapper();
49        return SkISize::Make(4 * fBM.width(), fBM.height());
50    }
51
52    void make_bitmap_wrapper() {
53        if (!fBitmapMade) {
54            fBitmapMade = true;
55            make_bitmap();
56        }
57    }
58
59    virtual void make_bitmap() = 0;
60
61    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
62        make_bitmap_wrapper();
63
64        int curX = 0;
65        int curWidth;
66        float curScale = 1;
67        do {
68
69            SkMatrix matrix;
70            matrix.setScale( curScale, curScale );
71
72            SkPaint paint;
73            paint.setFilterLevel(fFilterLevel);
74
75            canvas->save();
76            canvas->translate( (SkScalar) curX, 0.f );
77            canvas->drawBitmapMatrix( fBM, matrix, &paint );
78            canvas->restore();
79
80            curWidth = (int) (fBM.width() * curScale + 2);
81            curX += curWidth;
82            curScale *= 0.75f;
83        } while (curWidth >= 2 && curX < 4*fBM.width());
84    }
85
86private:
87    typedef skiagm::GM INHERITED;
88};
89
90class DownsampleBitmapTextGM: public DownsampleBitmapGM {
91  public:
92      DownsampleBitmapTextGM(float textSize, SkPaint::FilterLevel filterLevel)
93      : INHERITED(filterLevel), fTextSize(textSize)
94        {
95            fName.printf("downsamplebitmap_text_%s_%.2fpt", this->filterLevelToString(), fTextSize);
96        }
97
98  protected:
99      float fTextSize;
100
101      virtual void make_bitmap() SK_OVERRIDE {
102          fBM.setConfig(SkBitmap::kARGB_8888_Config, int(fTextSize * 8), int(fTextSize * 6));
103          fBM.allocPixels();
104          SkCanvas canvas(fBM);
105          canvas.drawColor(SK_ColorWHITE);
106
107          SkPaint paint;
108          paint.setAntiAlias(true);
109          paint.setSubpixelText(true);
110          paint.setTextSize(fTextSize);
111
112          setTypeface(&paint, "Times", SkTypeface::kNormal);
113          canvas.drawText("Hamburgefons", 12, fTextSize/2, 1.2f*fTextSize, paint);
114          setTypeface(&paint, "Times", SkTypeface::kBold);
115          canvas.drawText("Hamburgefons", 12, fTextSize/2, 2.4f*fTextSize, paint);
116          setTypeface(&paint, "Times", SkTypeface::kItalic);
117          canvas.drawText("Hamburgefons", 12, fTextSize/2, 3.6f*fTextSize, paint);
118          setTypeface(&paint, "Times", SkTypeface::kBoldItalic);
119          canvas.drawText("Hamburgefons", 12, fTextSize/2, 4.8f*fTextSize, paint);
120      }
121  private:
122      typedef DownsampleBitmapGM INHERITED;
123};
124
125class DownsampleBitmapCheckerboardGM: public DownsampleBitmapGM {
126  public:
127      DownsampleBitmapCheckerboardGM(int size, int numChecks, SkPaint::FilterLevel filterLevel)
128      : INHERITED(filterLevel), fSize(size), fNumChecks(numChecks)
129        {
130            fName.printf("downsamplebitmap_checkerboard_%s_%d_%d", this->filterLevelToString(), fSize, fNumChecks);
131        }
132
133  protected:
134      int fSize;
135      int fNumChecks;
136
137      virtual void make_bitmap() SK_OVERRIDE {
138          fBM.setConfig(SkBitmap::kARGB_8888_Config, fSize, fSize);
139          fBM.allocPixels();
140          SkAutoLockPixels lock(fBM);
141          for (int y = 0; y < fSize; ++y) {
142              for (int x = 0; x < fSize; ++x) {
143                  SkPMColor* s = fBM.getAddr32(x, y);
144                  int cx = (x * fNumChecks) / fSize;
145                  int cy = (y * fNumChecks) / fSize;
146                  if ((cx+cy)%2) {
147                      *s = 0xFFFFFFFF;
148                  } else {
149                      *s = 0xFF000000;
150                  }
151              }
152          }
153      }
154  private:
155      typedef DownsampleBitmapGM INHERITED;
156};
157
158class DownsampleBitmapImageGM: public DownsampleBitmapGM {
159  public:
160      DownsampleBitmapImageGM(const char filename[], SkPaint::FilterLevel filterLevel)
161      : INHERITED(filterLevel), fFilename(filename)
162        {
163            fName.printf("downsamplebitmap_image_%s_%s", this->filterLevelToString(), filename);
164        }
165
166  protected:
167      SkString fFilename;
168      int fSize;
169
170      virtual void make_bitmap() SK_OVERRIDE {
171          SkString path(skiagm::GM::gResourcePath);
172          path.append("/");
173          path.append(fFilename);
174
175          SkImageDecoder *codec = NULL;
176          SkFILEStream stream(path.c_str());
177          if (stream.isValid()) {
178              codec = SkImageDecoder::Factory(&stream);
179          }
180          if (codec) {
181              stream.rewind();
182              codec->decode(&stream, &fBM, SkBitmap::kARGB_8888_Config,
183                  SkImageDecoder::kDecodePixels_Mode);
184              SkDELETE(codec);
185          } else {
186              fBM.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
187              fBM.allocPixels();
188              *(fBM.getAddr32(0,0)) = 0xFF0000FF; // red == bad
189          }
190          fSize = fBM.height();
191      }
192  private:
193      typedef DownsampleBitmapGM INHERITED;
194};
195
196//////////////////////////////////////////////////////////////////////////////
197
198DEF_GM( return new DownsampleBitmapTextGM(72, SkPaint::kHigh_FilterLevel); )
199DEF_GM( return new DownsampleBitmapCheckerboardGM(512,256, SkPaint::kHigh_FilterLevel); )
200DEF_GM( return new DownsampleBitmapImageGM("mandrill_512.png", SkPaint::kHigh_FilterLevel); )
201
202DEF_GM( return new DownsampleBitmapTextGM(72, SkPaint::kMedium_FilterLevel); )
203DEF_GM( return new DownsampleBitmapCheckerboardGM(512,256, SkPaint::kMedium_FilterLevel); )
204DEF_GM( return new DownsampleBitmapImageGM("mandrill_512.png", SkPaint::kMedium_FilterLevel); )
205
206DEF_GM( return new DownsampleBitmapTextGM(72, SkPaint::kLow_FilterLevel); )
207DEF_GM( return new DownsampleBitmapCheckerboardGM(512,256, SkPaint::kLow_FilterLevel); )
208DEF_GM( return new DownsampleBitmapImageGM("mandrill_512.png", SkPaint::kLow_FilterLevel); )
209
210DEF_GM( return new DownsampleBitmapTextGM(72, SkPaint::kNone_FilterLevel); )
211DEF_GM( return new DownsampleBitmapCheckerboardGM(512,256, SkPaint::kNone_FilterLevel); )
212DEF_GM( return new DownsampleBitmapImageGM("mandrill_512.png", SkPaint::kNone_FilterLevel); )
213