blob: b17bb7012a3e0cbea3c09f89eb91efc606ceb62e [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"
9#include "SkCanvas.h"
10#include "SkPath.h"
11#include "SkTypeface.h"
12#include "SkRandom.h"
13
14/**
15 * Draws text with random parameters. The text draws each get their own clip rect. It is also
16 * used as a bench to measure how well the GPU backend batches text draws.
17 */
18
19class VariedTextGM : public skiagm::GM {
20public:
21 VariedTextGM(bool effectiveClip, bool lcd)
22 : fEffectiveClip(effectiveClip)
23 , fLCD(lcd) {
bsalomon7c5c9da2014-06-09 15:11:30 -070024 }
25
26protected:
mtklein36352bf2015-03-25 18:17:31 -070027 SkString onShortName() override {
bsalomon7c5c9da2014-06-09 15:11:30 -070028 SkString name("varied_text");
29 if (fEffectiveClip) {
30 name.append("_clipped");
31 } else {
32 name.append("_ignorable_clip");
33 }
34 if (fLCD) {
35 name.append("_lcd");
36 } else {
37 name.append("_no_lcd");
38 }
39 return name;
40 }
41
mtklein36352bf2015-03-25 18:17:31 -070042 SkISize onISize() override {
bsalomon7c5c9da2014-06-09 15:11:30 -070043 return SkISize::Make(640, 480);
44 }
45
mtklein36352bf2015-03-25 18:17:31 -070046 void onOnceBeforeDraw() override {
bsalomon7c5c9da2014-06-09 15:11:30 -070047 fPaint.setAntiAlias(true);
48 fPaint.setLCDRenderText(fLCD);
49
50 SkISize size = this->getISize();
51 SkScalar w = SkIntToScalar(size.fWidth);
52 SkScalar h = SkIntToScalar(size.fHeight);
53
bungeman13b9c952016-05-12 10:09:30 -070054 static_assert(4 == SK_ARRAY_COUNT(fTypefaces), "typeface_cnt");
mbocee6a9912016-05-31 11:42:36 -070055 fTypefaces[0] = sk_tool_utils::create_portable_typeface("sans-serif", SkFontStyle());
56 fTypefaces[1] = sk_tool_utils::create_portable_typeface("sans-serif",
57 SkFontStyle::FromOldStyle(SkTypeface::kBold));
58 fTypefaces[2] = sk_tool_utils::create_portable_typeface("serif", SkFontStyle());
59 fTypefaces[3] = sk_tool_utils::create_portable_typeface("serif",
60 SkFontStyle::FromOldStyle(SkTypeface::kBold));
bsalomon7c5c9da2014-06-09 15:11:30 -070061
62 SkRandom random;
63 for (int i = 0; i < kCnt; ++i) {
64 int length = random.nextRangeU(kMinLength, kMaxLength);
65 char text[kMaxLength];
66 for (int j = 0; j < length; ++j) {
67 text[j] = (char)random.nextRangeU('!', 'z');
68 }
69 fStrings[i].set(text, length);
70
71 fColors[i] = random.nextU();
72 fColors[i] |= 0xFF000000;
caryclarkae3714f2015-07-21 09:15:53 -070073 fColors[i] = sk_tool_utils::color_to_565(fColors[i]);
bsalomon7c5c9da2014-06-09 15:11:30 -070074
mtkleindbfd7ab2016-09-01 11:24:54 -070075 constexpr SkScalar kMinPtSize = 8.f;
76 constexpr SkScalar kMaxPtSize = 32.f;
bsalomon7c5c9da2014-06-09 15:11:30 -070077
78 fPtSizes[i] = random.nextRangeScalar(kMinPtSize, kMaxPtSize);
79
bungeman13b9c952016-05-12 10:09:30 -070080 fTypefaceIndices[i] = random.nextULessThan(SK_ARRAY_COUNT(fTypefaces));
bsalomon7c5c9da2014-06-09 15:11:30 -070081
82 SkRect r;
83 fPaint.setColor(fColors[i]);
bungeman13b9c952016-05-12 10:09:30 -070084 fPaint.setTypeface(fTypefaces[fTypefaceIndices[i]]);
bsalomon7c5c9da2014-06-09 15:11:30 -070085 fPaint.setTextSize(fPtSizes[i]);
86
87 fPaint.measureText(fStrings[i].c_str(), fStrings[i].size(), &r);
88 // safeRect is set of x,y positions where we can draw the string without hitting
89 // the GM's border.
90 SkRect safeRect = SkRect::MakeLTRB(-r.fLeft, -r.fTop, w - r.fRight, h - r.fBottom);
91 if (safeRect.isEmpty()) {
92 // If we don't fit then just don't worry about how we get cliped to the device
93 // border.
94 safeRect = SkRect::MakeWH(w, h);
95 }
96 fPositions[i].fX = random.nextRangeScalar(safeRect.fLeft, safeRect.fRight);
97 fPositions[i].fY = random.nextRangeScalar(safeRect.fTop, safeRect.fBottom);
98
99 fClipRects[i] = r;
100 fClipRects[i].offset(fPositions[i].fX, fPositions[i].fY);
101 fClipRects[i].outset(2.f, 2.f);
102
103 if (fEffectiveClip) {
104 fClipRects[i].fRight -= 0.25f * fClipRects[i].width();
105 }
106 }
107 }
108
mtklein36352bf2015-03-25 18:17:31 -0700109 void onDraw(SkCanvas* canvas) override {
bsalomon7c5c9da2014-06-09 15:11:30 -0700110 for (int i = 0; i < kCnt; ++i) {
111 fPaint.setColor(fColors[i]);
112 fPaint.setTextSize(fPtSizes[i]);
bungeman13b9c952016-05-12 10:09:30 -0700113 fPaint.setTypeface(fTypefaces[fTypefaceIndices[i]]);
bsalomon7c5c9da2014-06-09 15:11:30 -0700114
115 canvas->save();
116 canvas->clipRect(fClipRects[i]);
117 canvas->translate(fPositions[i].fX, fPositions[i].fY);
118 canvas->drawText(fStrings[i].c_str(), fStrings[i].size(), 0, 0, fPaint);
119 canvas->restore();
120 }
121
122 // Visualize the clips, but not in bench mode.
123 if (kBench_Mode != this->getMode()) {
124 SkPaint wirePaint;
125 wirePaint.setAntiAlias(true);
126 wirePaint.setStrokeWidth(0);
127 wirePaint.setStyle(SkPaint::kStroke_Style);
128 for (int i = 0; i < kCnt; ++i) {
129 canvas->drawRect(fClipRects[i], wirePaint);
130 }
131 }
132 }
133
mtklein36352bf2015-03-25 18:17:31 -0700134 bool runAsBench() const override { return true; }
bsalomon7c5c9da2014-06-09 15:11:30 -0700135
136private:
mtkleindbfd7ab2016-09-01 11:24:54 -0700137 static constexpr int kCnt = 30;
138 static constexpr int kMinLength = 15;
139 static constexpr int kMaxLength = 40;
bsalomon7c5c9da2014-06-09 15:11:30 -0700140
141 bool fEffectiveClip;
142 bool fLCD;
bungeman13b9c952016-05-12 10:09:30 -0700143 sk_sp<SkTypeface> fTypefaces[4];
bsalomon7c5c9da2014-06-09 15:11:30 -0700144 SkPaint fPaint;
145
146 // precomputed for each text draw
147 SkString fStrings[kCnt];
148 SkColor fColors[kCnt];
149 SkScalar fPtSizes[kCnt];
bungeman13b9c952016-05-12 10:09:30 -0700150 int fTypefaceIndices[kCnt];
bsalomon7c5c9da2014-06-09 15:11:30 -0700151 SkPoint fPositions[kCnt];
152 SkRect fClipRects[kCnt];
153
154 typedef skiagm::GM INHERITED;
155};
156
halcanary385fe4d2015-08-26 13:07:48 -0700157DEF_GM(return new VariedTextGM(false, false);)
158DEF_GM(return new VariedTextGM(true, false);)
159DEF_GM(return new VariedTextGM(false, true);)
160DEF_GM(return new VariedTextGM(true, true);)