1/*
2 * Copyright 2011 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#include "gm.h"
8#include "SkSurface.h"
9#include "SkTypeface.h"
10
11namespace skiagm {
12
13class DFTextGM : public GM {
14public:
15    DFTextGM() {
16        this->setBGColor(0xFFFFFFFF);
17    }
18
19    virtual ~DFTextGM() {
20    }
21
22protected:
23    virtual uint32_t onGetFlags() const SK_OVERRIDE {
24        return kGPUOnly_Flag;
25    }
26
27    virtual SkString onShortName() {
28        return SkString("dftext");
29    }
30
31    virtual SkISize onISize() {
32        return SkISize::Make(1024, 768);
33    }
34
35    static void rotate_about(SkCanvas* canvas,
36        SkScalar degrees,
37        SkScalar px, SkScalar py) {
38        canvas->translate(px, py);
39        canvas->rotate(degrees);
40        canvas->translate(-px, -py);
41    }
42
43    virtual void onDraw(SkCanvas* inputCanvas) {
44        SkScalar textSizes[] = { 11.0f, 11.0f*2.0f, 11.0f*5.0f, 11.0f*2.0f*5.0f };
45        SkScalar scales[] = { 2.0f*5.0f, 5.0f, 2.0f, 1.0f };
46
47        // set up offscreen rendering with distance field text
48#if SK_SUPPORT_GPU
49        GrContext* ctx = inputCanvas->getGrContext();
50        SkImageInfo info = SkImageInfo::MakeN32Premul(onISize());
51        SkSurfaceProps props(SkSurfaceProps::kUseDistanceFieldFonts_Flag,
52                             SkSurfaceProps::kLegacyFontHost_InitType);
53        SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(ctx, info, 0, &props));
54        SkCanvas* canvas = surface.get() ? surface->getCanvas() : inputCanvas;
55#else
56        SkCanvas* canvas = inputCanvas;
57#endif
58
59        // apply global scale to test glyph positioning
60        canvas->scale(1.05f, 1.05f);
61        canvas->clear(0xffffffff);
62
63        SkPaint paint;
64        paint.setAntiAlias(true);
65        paint.setSubpixelText(true);
66#if !SK_SUPPORT_GPU
67        paint.setDistanceFieldTextTEMP(true);
68#endif
69        sk_tool_utils::set_portable_typeface(&paint, "Times New Roman", SkTypeface::kNormal);
70
71        const char* text = "Hamburgefons";
72        const size_t textLen = strlen(text);
73
74        // check scaling up
75        SkScalar x = SkIntToScalar(0);
76        SkScalar y = SkIntToScalar(78);
77        for (size_t i = 0; i < SK_ARRAY_COUNT(textSizes); ++i) {
78            SkAutoCanvasRestore acr(canvas, true);
79            canvas->translate(x, y);
80            canvas->scale(scales[i], scales[i]);
81            paint.setTextSize(textSizes[i]);
82            canvas->drawText(text, textLen, 0, 0, paint);
83            y += paint.getFontMetrics(NULL)*scales[i];
84        }
85
86        // check rotation
87        for (size_t i = 0; i < 5; ++i) {
88            SkScalar rotX = SkIntToScalar(10);
89            SkScalar rotY = y;
90
91            SkAutoCanvasRestore acr(canvas, true);
92            canvas->translate(SkIntToScalar(10 + i * 200), -80);
93            rotate_about(canvas, SkIntToScalar(i * 5), rotX, rotY);
94            for (int ps = 6; ps <= 32; ps += 3) {
95                paint.setTextSize(SkIntToScalar(ps));
96                canvas->drawText(text, textLen, rotX, rotY, paint);
97                rotY += paint.getFontMetrics(NULL);
98            }
99        }
100
101        // check scaling down
102        paint.setLCDRenderText(true);
103        x = SkIntToScalar(680);
104        y = SkIntToScalar(20);
105        size_t arraySize = SK_ARRAY_COUNT(textSizes);
106        for (size_t i = 0; i < arraySize; ++i) {
107            SkAutoCanvasRestore acr(canvas, true);
108            canvas->translate(x, y);
109            SkScalar scaleFactor = SkScalarInvert(scales[arraySize - i - 1]);
110            canvas->scale(scaleFactor, scaleFactor);
111            paint.setTextSize(textSizes[i]);
112            canvas->drawText(text, textLen, 0, 0, paint);
113            y += paint.getFontMetrics(NULL)*scaleFactor;
114        }
115
116        // check pos text
117        {
118            SkAutoCanvasRestore acr(canvas, true);
119
120            canvas->scale(2.0f, 2.0f);
121
122            SkAutoTArray<SkPoint>  pos(textLen);
123            SkAutoTArray<SkScalar> widths(textLen);
124            paint.setTextSize(textSizes[0]);
125
126            paint.getTextWidths(text, textLen, &widths[0]);
127
128            SkScalar x = SkIntToScalar(340);
129            SkScalar y = SkIntToScalar(75);
130            for (unsigned int i = 0; i < textLen; ++i) {
131                pos[i].set(x, y);
132                x += widths[i];
133            }
134
135            canvas->drawPosText(text, textLen, &pos[0], paint);
136        }
137
138
139        // check gamma-corrected blending
140        const SkColor fg[] = {
141            0xFFFFFFFF,
142            0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF,
143            0xFFFF0000, 0xFF00FF00, 0xFF0000FF,
144            0xFF000000,
145        };
146
147        paint.setColor(0xFFF1F1F1);
148        SkRect r = SkRect::MakeLTRB(670, 250, 820, 460);
149        canvas->drawRect(r, paint);
150
151        x = SkIntToScalar(680);
152        y = SkIntToScalar(270);
153        paint.setTextSize(SkIntToScalar(22));
154        for (size_t i = 0; i < SK_ARRAY_COUNT(fg); ++i) {
155            paint.setColor(fg[i]);
156
157            canvas->drawText(text, textLen, x, y, paint);
158            y += paint.getFontMetrics(NULL);
159        }
160
161        paint.setColor(0xFF1F1F1F);
162        r = SkRect::MakeLTRB(820, 250, 970, 460);
163        canvas->drawRect(r, paint);
164
165        x = SkIntToScalar(830);
166        y = SkIntToScalar(270);
167        paint.setTextSize(SkIntToScalar(22));
168        for (size_t i = 0; i < SK_ARRAY_COUNT(fg); ++i) {
169            paint.setColor(fg[i]);
170
171            canvas->drawText(text, textLen, x, y, paint);
172            y += paint.getFontMetrics(NULL);
173        }
174
175#if SK_SUPPORT_GPU
176        // render offscreen buffer
177        if (surface) {
178            SkImage* image = surface->newImageSnapshot();
179            inputCanvas->drawImage(image, 0, 0, NULL);
180            image->unref();
181        }
182#endif
183    }
184
185private:
186    typedef GM INHERITED;
187};
188
189//////////////////////////////////////////////////////////////////////////////
190
191static GM* MyFactory(void*) { return new DFTextGM; }
192static GMRegistry reg(MyFactory);
193
194}
195