blob: e8e1c29632b457172da08dffb29afdfe1fbece80 [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());
Ben Wagner71319502017-07-27 10:45:29 -040057 fTypefaces[1] = sk_tool_utils::create_portable_typeface("sans-serif", SkFontStyle::Bold());
mbocee6a9912016-05-31 11:42:36 -070058 fTypefaces[2] = sk_tool_utils::create_portable_typeface("serif", SkFontStyle());
Ben Wagner71319502017-07-27 10:45:29 -040059 fTypefaces[3] = sk_tool_utils::create_portable_typeface("serif", SkFontStyle::Bold());
bsalomon7c5c9da2014-06-09 15:11:30 -070060
61 SkRandom random;
62 for (int i = 0; i < kCnt; ++i) {
63 int length = random.nextRangeU(kMinLength, kMaxLength);
64 char text[kMaxLength];
65 for (int j = 0; j < length; ++j) {
66 text[j] = (char)random.nextRangeU('!', 'z');
67 }
68 fStrings[i].set(text, length);
69
70 fColors[i] = random.nextU();
71 fColors[i] |= 0xFF000000;
caryclarkae3714f2015-07-21 09:15:53 -070072 fColors[i] = sk_tool_utils::color_to_565(fColors[i]);
bsalomon7c5c9da2014-06-09 15:11:30 -070073
mtkleindbfd7ab2016-09-01 11:24:54 -070074 constexpr SkScalar kMinPtSize = 8.f;
75 constexpr SkScalar kMaxPtSize = 32.f;
bsalomon7c5c9da2014-06-09 15:11:30 -070076
77 fPtSizes[i] = random.nextRangeScalar(kMinPtSize, kMaxPtSize);
78
bungeman13b9c952016-05-12 10:09:30 -070079 fTypefaceIndices[i] = random.nextULessThan(SK_ARRAY_COUNT(fTypefaces));
bsalomon7c5c9da2014-06-09 15:11:30 -070080
81 SkRect r;
82 fPaint.setColor(fColors[i]);
bungeman13b9c952016-05-12 10:09:30 -070083 fPaint.setTypeface(fTypefaces[fTypefaceIndices[i]]);
bsalomon7c5c9da2014-06-09 15:11:30 -070084 fPaint.setTextSize(fPtSizes[i]);
85
86 fPaint.measureText(fStrings[i].c_str(), fStrings[i].size(), &r);
87 // safeRect is set of x,y positions where we can draw the string without hitting
88 // the GM's border.
89 SkRect safeRect = SkRect::MakeLTRB(-r.fLeft, -r.fTop, w - r.fRight, h - r.fBottom);
90 if (safeRect.isEmpty()) {
91 // If we don't fit then just don't worry about how we get cliped to the device
92 // border.
93 safeRect = SkRect::MakeWH(w, h);
94 }
95 fPositions[i].fX = random.nextRangeScalar(safeRect.fLeft, safeRect.fRight);
96 fPositions[i].fY = random.nextRangeScalar(safeRect.fTop, safeRect.fBottom);
97
98 fClipRects[i] = r;
99 fClipRects[i].offset(fPositions[i].fX, fPositions[i].fY);
100 fClipRects[i].outset(2.f, 2.f);
101
102 if (fEffectiveClip) {
103 fClipRects[i].fRight -= 0.25f * fClipRects[i].width();
104 }
105 }
106 }
107
mtklein36352bf2015-03-25 18:17:31 -0700108 void onDraw(SkCanvas* canvas) override {
bsalomon7c5c9da2014-06-09 15:11:30 -0700109 for (int i = 0; i < kCnt; ++i) {
110 fPaint.setColor(fColors[i]);
111 fPaint.setTextSize(fPtSizes[i]);
bungeman13b9c952016-05-12 10:09:30 -0700112 fPaint.setTypeface(fTypefaces[fTypefaceIndices[i]]);
bsalomon7c5c9da2014-06-09 15:11:30 -0700113
114 canvas->save();
115 canvas->clipRect(fClipRects[i]);
116 canvas->translate(fPositions[i].fX, fPositions[i].fY);
Cary Clark2a475ea2017-04-28 15:35:12 -0400117 canvas->drawString(fStrings[i], 0, 0, fPaint);
bsalomon7c5c9da2014-06-09 15:11:30 -0700118 canvas->restore();
119 }
120
121 // Visualize the clips, but not in bench mode.
122 if (kBench_Mode != this->getMode()) {
123 SkPaint wirePaint;
124 wirePaint.setAntiAlias(true);
125 wirePaint.setStrokeWidth(0);
126 wirePaint.setStyle(SkPaint::kStroke_Style);
127 for (int i = 0; i < kCnt; ++i) {
128 canvas->drawRect(fClipRects[i], wirePaint);
129 }
130 }
131 }
132
mtklein36352bf2015-03-25 18:17:31 -0700133 bool runAsBench() const override { return true; }
bsalomon7c5c9da2014-06-09 15:11:30 -0700134
135private:
mtkleindbfd7ab2016-09-01 11:24:54 -0700136 static constexpr int kCnt = 30;
137 static constexpr int kMinLength = 15;
138 static constexpr int kMaxLength = 40;
bsalomon7c5c9da2014-06-09 15:11:30 -0700139
140 bool fEffectiveClip;
141 bool fLCD;
bungeman13b9c952016-05-12 10:09:30 -0700142 sk_sp<SkTypeface> fTypefaces[4];
bsalomon7c5c9da2014-06-09 15:11:30 -0700143 SkPaint fPaint;
144
145 // precomputed for each text draw
146 SkString fStrings[kCnt];
147 SkColor fColors[kCnt];
148 SkScalar fPtSizes[kCnt];
bungeman13b9c952016-05-12 10:09:30 -0700149 int fTypefaceIndices[kCnt];
bsalomon7c5c9da2014-06-09 15:11:30 -0700150 SkPoint fPositions[kCnt];
151 SkRect fClipRects[kCnt];
152
153 typedef skiagm::GM INHERITED;
154};
155
halcanary385fe4d2015-08-26 13:07:48 -0700156DEF_GM(return new VariedTextGM(false, false);)
157DEF_GM(return new VariedTextGM(true, false);)
158DEF_GM(return new VariedTextGM(false, true);)
159DEF_GM(return new VariedTextGM(true, true);)