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
8
9/* Tests text rendering with LCD and subpixel rendering turned on and off.
10 */
11
12#include "gm.h"
13#include "sk_tool_utils.h"
14#include "SkCanvas.h"
15#include "SkPicture.h"
16#include "SkPictureImageFilter.h"
17#include "SkPictureRecorder.h"
18#include "SkSurface.h"
19
20
21class LcdTextGM : public skiagm::GM {
22public:
23    LcdTextGM() {
24        const int pointSize = 36;
25        textHeight = SkIntToScalar(pointSize);
26    }
27
28protected:
29
30    SkString onShortName() {
31        SkString name("lcdtext");
32        name.append(sk_tool_utils::major_platform_os_name());
33        return name;
34    }
35
36    SkISize onISize() { return SkISize::Make(640, 480); }
37
38    virtual void onDraw(SkCanvas* canvas) {
39
40        y = textHeight;
41        drawText(canvas, SkString("TEXT: SubpixelTrue LCDRenderTrue"),
42                 true,  true);
43        drawText(canvas, SkString("TEXT: SubpixelTrue LCDRenderFalse"),
44                 true,  false);
45        drawText(canvas, SkString("TEXT: SubpixelFalse LCDRenderTrue"),
46                 false, true);
47        drawText(canvas, SkString("TEXT: SubpixelFalse LCDRenderFalse"),
48                 false, false);
49    }
50
51    void drawText(SkCanvas* canvas, const SkString& string,
52                  bool subpixelTextEnabled, bool lcdRenderTextEnabled) {
53        SkPaint paint;
54        paint.setColor(SK_ColorBLACK);
55        paint.setDither(true);
56        paint.setAntiAlias(true);
57        paint.setSubpixelText(subpixelTextEnabled);
58        paint.setLCDRenderText(lcdRenderTextEnabled);
59        paint.setTextSize(textHeight);
60
61        canvas->drawString(string, 0, y, paint);
62        y += textHeight;
63    }
64
65private:
66    typedef skiagm::GM INHERITED;
67    SkScalar y, textHeight;
68};
69
70/*
71 *  Skia will automatically disable LCD requests if the total size exceeds some limit
72 *  (hard coded in this test for now, as it is now avaiable as an API)
73 *
74 *  Test this both by changing "textsize" and by changing the computed size (textsize * CTM)
75 */
76class LcdTextSizeGM : public skiagm::GM {
77    enum {
78        kLCDTextSizeLimit = 48
79    };
80
81    static void ScaleAbout(SkCanvas* canvas, SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
82        SkMatrix m;
83        m.setScale(sx, sy, px, py);
84        canvas->concat(m);
85    }
86
87public:
88    LcdTextSizeGM() {}
89
90protected:
91    SkString onShortName() {
92        return SkString("lcdtextsize");
93    }
94
95    SkISize onISize() { return SkISize::Make(320, 120); }
96
97    virtual void onDraw(SkCanvas* canvas) {
98        const char* lcd_text = "LCD";
99        const char* gray_text = "GRAY";
100
101        SkPaint paint;
102        paint.setAntiAlias(true);
103        paint.setLCDRenderText(true);
104
105        const struct {
106            SkPoint     fLoc;
107            SkScalar    fTextSize;
108            SkScalar    fScale;
109            const char* fText;
110        } rec[] = {
111            { {  10,  50 }, kLCDTextSizeLimit - 1,     1,  lcd_text },
112            { { 160,  50 }, kLCDTextSizeLimit + 1,     1,  gray_text },
113            { {  10, 100 }, kLCDTextSizeLimit / 2, 1.99f,  lcd_text },
114            { { 160, 100 }, kLCDTextSizeLimit / 2, 2.01f,  gray_text },
115        };
116
117        for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
118            const SkPoint loc = rec[i].fLoc;
119            SkAutoCanvasRestore acr(canvas, true);
120
121            paint.setTextSize(rec[i].fTextSize);
122            ScaleAbout(canvas, rec[i].fScale, rec[i].fScale, loc.x(), loc.y());
123            canvas->drawString(rec[i].fText, loc.x(), loc.y(), paint);
124        }
125    }
126
127private:
128    typedef skiagm::GM INHERITED;
129};
130DEF_GM( return new LcdTextGM; )
131DEF_GM( return new LcdTextSizeGM; )
132
133///////////////////////////////////////////////////////////////////////////////////////////////////
134
135DEF_SIMPLE_GM(savelayer_lcdtext, canvas, 620, 260) {
136    SkPaint paint;
137    paint.setAntiAlias(true);
138    paint.setLCDRenderText(true);
139    paint.setTextSize(20);
140
141    canvas->drawString("Hamburgefons", 30, 30, paint);
142
143    const bool gPreserveLCDText[] = { false, true };
144
145    canvas->translate(0, 20);
146    for (auto preserve : gPreserveLCDText) {
147        preserve ? canvas->saveLayerPreserveLCDTextRequests(nullptr, nullptr)
148                 : canvas->saveLayer(nullptr, nullptr);
149        if (preserve && !canvas->imageInfo().colorSpace()) {
150            SkPaint noLCD = paint;
151            noLCD.setLCDRenderText(false);
152            canvas->drawString("LCD not supported", 30, 60, noLCD);
153        } else {
154            canvas->drawString("Hamburgefons", 30, 60, paint);
155        }
156
157        SkPaint p;
158        p.setColor(0xFFCCCCCC);
159        canvas->drawRect(SkRect::MakeLTRB(25, 70, 200, 100), p);
160        canvas->drawString("Hamburgefons", 30, 90, paint);
161
162        canvas->restore();
163        canvas->translate(0, 80);
164    }
165}
166