blob: c0f6cbf8c7e3f1e6d78ac4e51d2707ada63d4546 [file] [log] [blame]
bsalomon7c5c9da2014-06-09 15:11:30 -07001/*
2 * Copyright 2014 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"
Mike Klein33d20552017-03-22 13:47:51 -04009#include "sk_tool_utils.h"
bsalomon7c5c9da2014-06-09 15:11:30 -070010#include "SkCanvas.h"
11#include "SkPath.h"
12#include "SkTypeface.h"
13#include "SkRandom.h"
14
15/**
16 * Draws text with random parameters. The text draws each get their own clip rect. It is also
Brian Salomon09d994e2016-12-21 11:14:46 -050017 * used as a bench to measure how well the GPU backend combines draw ops for text draws.
bsalomon7c5c9da2014-06-09 15:11:30 -070018 */
19
20class VariedTextGM : public skiagm::GM {
21public:
22 VariedTextGM(bool effectiveClip, bool lcd)
23 : fEffectiveClip(effectiveClip)
24 , fLCD(lcd) {
bsalomon7c5c9da2014-06-09 15:11:30 -070025 }
26
27protected:
mtklein36352bf2015-03-25 18:17:31 -070028 SkString onShortName() override {
bsalomon7c5c9da2014-06-09 15:11:30 -070029 SkString name("varied_text");
30 if (fEffectiveClip) {
31 name.append("_clipped");
32 } else {
33 name.append("_ignorable_clip");
34 }
35 if (fLCD) {
36 name.append("_lcd");
37 } else {
38 name.append("_no_lcd");
39 }
40 return name;
41 }
42
mtklein36352bf2015-03-25 18:17:31 -070043 SkISize onISize() override {
bsalomon7c5c9da2014-06-09 15:11:30 -070044 return SkISize::Make(640, 480);
45 }
46
mtklein36352bf2015-03-25 18:17:31 -070047 void onOnceBeforeDraw() override {
bsalomon7c5c9da2014-06-09 15:11:30 -070048 fPaint.setAntiAlias(true);
49 fPaint.setLCDRenderText(fLCD);
50
51 SkISize size = this->getISize();
52 SkScalar w = SkIntToScalar(size.fWidth);
53 SkScalar h = SkIntToScalar(size.fHeight);
54
bungeman13b9c952016-05-12 10:09:30 -070055 static_assert(4 == SK_ARRAY_COUNT(fTypefaces), "typeface_cnt");
mbocee6a9912016-05-31 11:42:36 -070056 fTypefaces[0] = sk_tool_utils::create_portable_typeface("sans-serif", SkFontStyle());
57 fTypefaces[1] = sk_tool_utils::create_portable_typeface("sans-serif",
58 SkFontStyle::FromOldStyle(SkTypeface::kBold));
59 fTypefaces[2] = sk_tool_utils::create_portable_typeface("serif", SkFontStyle());
60 fTypefaces[3] = sk_tool_utils::create_portable_typeface("serif",
61 SkFontStyle::FromOldStyle(SkTypeface::kBold));
bsalomon7c5c9da2014-06-09 15:11:30 -070062
63 SkRandom random;
64 for (int i = 0; i < kCnt; ++i) {
65 int length = random.nextRangeU(kMinLength, kMaxLength);
66 char text[kMaxLength];
67 for (int j = 0; j < length; ++j) {
68 text[j] = (char)random.nextRangeU('!', 'z');
69 }
70 fStrings[i].set(text, length);
71
72 fColors[i] = random.nextU();
73 fColors[i] |= 0xFF000000;
caryclarkae3714f2015-07-21 09:15:53 -070074 fColors[i] = sk_tool_utils::color_to_565(fColors[i]);
bsalomon7c5c9da2014-06-09 15:11:30 -070075
mtkleindbfd7ab2016-09-01 11:24:54 -070076 constexpr SkScalar kMinPtSize = 8.f;
77 constexpr SkScalar kMaxPtSize = 32.f;
bsalomon7c5c9da2014-06-09 15:11:30 -070078
79 fPtSizes[i] = random.nextRangeScalar(kMinPtSize, kMaxPtSize);
80
bungeman13b9c952016-05-12 10:09:30 -070081 fTypefaceIndices[i] = random.nextULessThan(SK_ARRAY_COUNT(fTypefaces));
bsalomon7c5c9da2014-06-09 15:11:30 -070082
83 SkRect r;
84 fPaint.setColor(fColors[i]);
bungeman13b9c952016-05-12 10:09:30 -070085 fPaint.setTypeface(fTypefaces[fTypefaceIndices[i]]);
bsalomon7c5c9da2014-06-09 15:11:30 -070086 fPaint.setTextSize(fPtSizes[i]);
87
88 fPaint.measureText(fStrings[i].c_str(), fStrings[i].size(), &r);
89 // safeRect is set of x,y positions where we can draw the string without hitting
90 // the GM's border.
91 SkRect safeRect = SkRect::MakeLTRB(-r.fLeft, -r.fTop, w - r.fRight, h - r.fBottom);
92 if (safeRect.isEmpty()) {
93 // If we don't fit then just don't worry about how we get cliped to the device
94 // border.
95 safeRect = SkRect::MakeWH(w, h);
96 }
97 fPositions[i].fX = random.nextRangeScalar(safeRect.fLeft, safeRect.fRight);
98 fPositions[i].fY = random.nextRangeScalar(safeRect.fTop, safeRect.fBottom);
99
100 fClipRects[i] = r;
101 fClipRects[i].offset(fPositions[i].fX, fPositions[i].fY);
102 fClipRects[i].outset(2.f, 2.f);
103
104 if (fEffectiveClip) {
105 fClipRects[i].fRight -= 0.25f * fClipRects[i].width();
106 }
107 }
108 }
109
mtklein36352bf2015-03-25 18:17:31 -0700110 void onDraw(SkCanvas* canvas) override {
bsalomon7c5c9da2014-06-09 15:11:30 -0700111 for (int i = 0; i < kCnt; ++i) {
112 fPaint.setColor(fColors[i]);
113 fPaint.setTextSize(fPtSizes[i]);
bungeman13b9c952016-05-12 10:09:30 -0700114 fPaint.setTypeface(fTypefaces[fTypefaceIndices[i]]);
bsalomon7c5c9da2014-06-09 15:11:30 -0700115
116 canvas->save();
117 canvas->clipRect(fClipRects[i]);
118 canvas->translate(fPositions[i].fX, fPositions[i].fY);
Cary Clark2a475ea2017-04-28 15:35:12 -0400119 canvas->drawString(fStrings[i], 0, 0, fPaint);
bsalomon7c5c9da2014-06-09 15:11:30 -0700120 canvas->restore();
121 }
122
123 // Visualize the clips, but not in bench mode.
124 if (kBench_Mode != this->getMode()) {
125 SkPaint wirePaint;
126 wirePaint.setAntiAlias(true);
127 wirePaint.setStrokeWidth(0);
128 wirePaint.setStyle(SkPaint::kStroke_Style);
129 for (int i = 0; i < kCnt; ++i) {
130 canvas->drawRect(fClipRects[i], wirePaint);
131 }
132 }
133 }
134
mtklein36352bf2015-03-25 18:17:31 -0700135 bool runAsBench() const override { return true; }
bsalomon7c5c9da2014-06-09 15:11:30 -0700136
137private:
mtkleindbfd7ab2016-09-01 11:24:54 -0700138 static constexpr int kCnt = 30;
139 static constexpr int kMinLength = 15;
140 static constexpr int kMaxLength = 40;
bsalomon7c5c9da2014-06-09 15:11:30 -0700141
142 bool fEffectiveClip;
143 bool fLCD;
bungeman13b9c952016-05-12 10:09:30 -0700144 sk_sp<SkTypeface> fTypefaces[4];
bsalomon7c5c9da2014-06-09 15:11:30 -0700145 SkPaint fPaint;
146
147 // precomputed for each text draw
148 SkString fStrings[kCnt];
149 SkColor fColors[kCnt];
150 SkScalar fPtSizes[kCnt];
bungeman13b9c952016-05-12 10:09:30 -0700151 int fTypefaceIndices[kCnt];
bsalomon7c5c9da2014-06-09 15:11:30 -0700152 SkPoint fPositions[kCnt];
153 SkRect fClipRects[kCnt];
154
155 typedef skiagm::GM INHERITED;
156};
157
halcanary385fe4d2015-08-26 13:07:48 -0700158DEF_GM(return new VariedTextGM(false, false);)
159DEF_GM(return new VariedTextGM(true, false);)
160DEF_GM(return new VariedTextGM(false, true);)
161DEF_GM(return new VariedTextGM(true, true);)