xref: /aosp_15_r20/external/skia/gm/lcdtext.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 #include "gm/gm.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkColor.h"
11 #include "include/core/SkFont.h"
12 #include "include/core/SkMatrix.h"
13 #include "include/core/SkPaint.h"
14 #include "include/core/SkPoint.h"
15 #include "include/core/SkRefCnt.h"
16 #include "include/core/SkScalar.h"
17 #include "include/core/SkSize.h"
18 #include "include/core/SkString.h"
19 #include "include/core/SkTypeface.h"
20 #include "include/core/SkTypes.h"
21 #include "tools/fonts/FontToolUtils.h"
22 
23 class LcdTextGM : public skiagm::GM {
24     static constexpr SkScalar kTextHeight = 36;
25     SkScalar fY = kTextHeight;
26 
getName() const27     SkString getName() const override { return SkString("lcdtext"); }
28 
getISize()29     SkISize getISize() override { return {640, 480}; }
30 
onDraw(SkCanvas * canvas)31     void onDraw(SkCanvas* canvas) override {
32         fY = kTextHeight;
33         drawText(canvas, SkString("TEXT: SubpixelTrue LCDRenderTrue"),
34                  true,  true);
35         drawText(canvas, SkString("TEXT: SubpixelTrue LCDRenderFalse"),
36                  true,  false);
37         drawText(canvas, SkString("TEXT: SubpixelFalse LCDRenderTrue"),
38                  false, true);
39         drawText(canvas, SkString("TEXT: SubpixelFalse LCDRenderFalse"),
40                  false, false);
41     }
42 
drawText(SkCanvas * canvas,const SkString & string,bool subpixelTextEnabled,bool lcdRenderTextEnabled)43     void drawText(SkCanvas* canvas, const SkString& string,
44                   bool subpixelTextEnabled, bool lcdRenderTextEnabled) {
45         SkPaint paint;
46         paint.setColor(SK_ColorBLACK);
47         paint.setDither(true);
48         SkFont font(ToolUtils::DefaultPortableTypeface(), kTextHeight);
49         if (subpixelTextEnabled) {
50             font.setSubpixel(true);
51         }
52         if (lcdRenderTextEnabled) {
53             font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
54         }
55         canvas->drawString(string, 0, fY, font, paint);
56         fY += kTextHeight;
57     }
58 };
59 
60 /*
61  *  Skia will automatically disable LCD requests if the total size exceeds some limit
62  *  (hard coded in this test for now, as it is now available as an API)
63  *
64  *  Test this both by changing "textsize" and by changing the computed size (textsize * CTM)
65  */
66 class LcdTextSizeGM : public skiagm::GM {
ScaleAbout(SkCanvas * canvas,SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)67     static void ScaleAbout(SkCanvas* canvas, SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
68         SkMatrix m;
69         m.setScale(sx, sy, px, py);
70         canvas->concat(m);
71     }
72 
getName() const73     SkString getName() const override { return SkString("lcdtextsize"); }
74 
getISize()75     SkISize getISize() override { return {320, 120}; }
76 
onDraw(SkCanvas * canvas)77     void onDraw(SkCanvas* canvas) override {
78         const char* lcd_text = "LCD";
79         const char* gray_text = "GRAY";
80 
81         constexpr static float kLCDTextSizeLimit = 48;
82 
83         const struct {
84             SkPoint     fLoc;
85             SkScalar    fTextSize;
86             SkScalar    fScale;
87             const char* fText;
88         } rec[] = {
89             { {  10,  50 }, kLCDTextSizeLimit - 1,     1,  lcd_text },
90             { { 160,  50 }, kLCDTextSizeLimit + 1,     1,  gray_text },
91             { {  10, 100 }, kLCDTextSizeLimit / 2, 1.99f,  lcd_text },
92             { { 160, 100 }, kLCDTextSizeLimit / 2, 2.01f,  gray_text },
93         };
94 
95         for (size_t i = 0; i < std::size(rec); ++i) {
96             const SkPoint loc = rec[i].fLoc;
97             SkAutoCanvasRestore acr(canvas, true);
98 
99             SkFont font(ToolUtils::DefaultPortableTypeface(), rec[i].fTextSize);
100             font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
101 
102             ScaleAbout(canvas, rec[i].fScale, rec[i].fScale, loc.x(), loc.y());
103             canvas->drawString(rec[i].fText, loc.x(), loc.y(), font, SkPaint());
104         }
105     }
106 };
107 
108 class SaveLayerPreserveLCDTextGM : public skiagm::GM {
109     static constexpr SkScalar kTextHeight = 36;
110 
getName() const111     SkString getName() const override { return SkString("savelayerpreservelcdtext"); }
112 
getISize()113     SkISize getISize() override { return {620, 300}; }
114 
onDraw(SkCanvas * canvas)115     void onDraw(SkCanvas* canvas) override {
116         drawText(canvas, SkString("SaveLayer PreserveLCDText"), 50,
117                  SkCanvas::kPreserveLCDText_SaveLayerFlag);
118         drawText(canvas, SkString("SaveLayer Default (LCDText not preserved)"), 150, 0);
119     }
120 
drawText(SkCanvas * canvas,const SkString & string,int y,SkCanvas::SaveLayerFlags saveLayerFlags)121     void drawText(SkCanvas* canvas,
122                   const SkString& string,
123                   int y,
124                   SkCanvas::SaveLayerFlags saveLayerFlags) {
125         SkCanvas::SaveLayerRec rec(nullptr, nullptr, saveLayerFlags);
126         canvas->saveLayer(rec);
127         SkPaint paint;
128         paint.setColor(SK_ColorWHITE);
129         canvas->drawRect(SkRect::MakeXYWH(0, y - 10, 640, kTextHeight + 20), paint);
130         paint.setColor(SK_ColorBLACK);
131         SkFont font(ToolUtils::DefaultPortableTypeface(), kTextHeight);
132         font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
133         canvas->drawString(string, 10, y, font, paint);
134         canvas->restore();
135     }
136 };
137 
138 DEF_GM(return new LcdTextGM;)
139 DEF_GM(return new LcdTextSizeGM;)
140 DEF_GM(return new SaveLayerPreserveLCDTextGM;)
141