blob: 37c6ac485e39b432f89173e69dc60753a378adbf [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "gm/gm.h"
9#include "include/core/SkCanvas.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040010#include "include/core/SkColor.h"
11#include "include/core/SkFont.h"
12#include "include/core/SkFontStyle.h"
13#include "include/core/SkFontTypes.h"
14#include "include/core/SkPaint.h"
15#include "include/core/SkPoint.h"
16#include "include/core/SkRect.h"
17#include "include/core/SkRefCnt.h"
18#include "include/core/SkScalar.h"
19#include "include/core/SkSize.h"
20#include "include/core/SkString.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#include "include/core/SkTypeface.h"
Ben Wagner7fde8e12019-05-01 17:28:53 -040022#include "include/core/SkTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050023#include "include/utils/SkRandom.h"
24#include "tools/ToolUtils.h"
bsalomon7c5c9da2014-06-09 15:11:30 -070025
26/**
27 * Draws text with random parameters. The text draws each get their own clip rect. It is also
Brian Salomon09d994e2016-12-21 11:14:46 -050028 * used as a bench to measure how well the GPU backend combines draw ops for text draws.
bsalomon7c5c9da2014-06-09 15:11:30 -070029 */
30
31class VariedTextGM : public skiagm::GM {
32public:
33 VariedTextGM(bool effectiveClip, bool lcd)
34 : fEffectiveClip(effectiveClip)
35 , fLCD(lcd) {
bsalomon7c5c9da2014-06-09 15:11:30 -070036 }
37
38protected:
mtklein36352bf2015-03-25 18:17:31 -070039 SkString onShortName() override {
bsalomon7c5c9da2014-06-09 15:11:30 -070040 SkString name("varied_text");
41 if (fEffectiveClip) {
42 name.append("_clipped");
43 } else {
44 name.append("_ignorable_clip");
45 }
46 if (fLCD) {
47 name.append("_lcd");
48 } else {
49 name.append("_no_lcd");
50 }
51 return name;
52 }
53
mtklein36352bf2015-03-25 18:17:31 -070054 SkISize onISize() override {
bsalomon7c5c9da2014-06-09 15:11:30 -070055 return SkISize::Make(640, 480);
56 }
57
mtklein36352bf2015-03-25 18:17:31 -070058 void onOnceBeforeDraw() override {
bsalomon7c5c9da2014-06-09 15:11:30 -070059 fPaint.setAntiAlias(true);
Mike Reed91919132019-01-02 12:21:01 -050060 fFont.setEdging(fLCD ? SkFont::Edging::kSubpixelAntiAlias : SkFont::Edging::kAntiAlias);
bsalomon7c5c9da2014-06-09 15:11:30 -070061
62 SkISize size = this->getISize();
63 SkScalar w = SkIntToScalar(size.fWidth);
64 SkScalar h = SkIntToScalar(size.fHeight);
65
bungeman13b9c952016-05-12 10:09:30 -070066 static_assert(4 == SK_ARRAY_COUNT(fTypefaces), "typeface_cnt");
Mike Kleinea3f0142019-03-20 11:12:10 -050067 fTypefaces[0] = ToolUtils::create_portable_typeface("sans-serif", SkFontStyle());
68 fTypefaces[1] = ToolUtils::create_portable_typeface("sans-serif", SkFontStyle::Bold());
69 fTypefaces[2] = ToolUtils::create_portable_typeface("serif", SkFontStyle());
70 fTypefaces[3] = ToolUtils::create_portable_typeface("serif", SkFontStyle::Bold());
bsalomon7c5c9da2014-06-09 15:11:30 -070071
72 SkRandom random;
73 for (int i = 0; i < kCnt; ++i) {
74 int length = random.nextRangeU(kMinLength, kMaxLength);
75 char text[kMaxLength];
76 for (int j = 0; j < length; ++j) {
77 text[j] = (char)random.nextRangeU('!', 'z');
78 }
79 fStrings[i].set(text, length);
80
81 fColors[i] = random.nextU();
82 fColors[i] |= 0xFF000000;
Mike Kleinea3f0142019-03-20 11:12:10 -050083 fColors[i] = ToolUtils::color_to_565(fColors[i]);
bsalomon7c5c9da2014-06-09 15:11:30 -070084
mtkleindbfd7ab2016-09-01 11:24:54 -070085 constexpr SkScalar kMinPtSize = 8.f;
86 constexpr SkScalar kMaxPtSize = 32.f;
bsalomon7c5c9da2014-06-09 15:11:30 -070087
88 fPtSizes[i] = random.nextRangeScalar(kMinPtSize, kMaxPtSize);
89
bungeman13b9c952016-05-12 10:09:30 -070090 fTypefaceIndices[i] = random.nextULessThan(SK_ARRAY_COUNT(fTypefaces));
bsalomon7c5c9da2014-06-09 15:11:30 -070091
92 SkRect r;
93 fPaint.setColor(fColors[i]);
Mike Reed91919132019-01-02 12:21:01 -050094 fFont.setTypeface(fTypefaces[fTypefaceIndices[i]]);
95 fFont.setSize(fPtSizes[i]);
bsalomon7c5c9da2014-06-09 15:11:30 -070096
Ben Wagner51e15a62019-05-07 15:38:46 -040097 fFont.measureText(fStrings[i].c_str(), fStrings[i].size(), SkTextEncoding::kUTF8, &r);
bsalomon7c5c9da2014-06-09 15:11:30 -070098 // safeRect is set of x,y positions where we can draw the string without hitting
99 // the GM's border.
100 SkRect safeRect = SkRect::MakeLTRB(-r.fLeft, -r.fTop, w - r.fRight, h - r.fBottom);
101 if (safeRect.isEmpty()) {
102 // If we don't fit then just don't worry about how we get cliped to the device
103 // border.
104 safeRect = SkRect::MakeWH(w, h);
105 }
106 fPositions[i].fX = random.nextRangeScalar(safeRect.fLeft, safeRect.fRight);
107 fPositions[i].fY = random.nextRangeScalar(safeRect.fTop, safeRect.fBottom);
108
109 fClipRects[i] = r;
110 fClipRects[i].offset(fPositions[i].fX, fPositions[i].fY);
111 fClipRects[i].outset(2.f, 2.f);
112
113 if (fEffectiveClip) {
114 fClipRects[i].fRight -= 0.25f * fClipRects[i].width();
115 }
116 }
117 }
118
mtklein36352bf2015-03-25 18:17:31 -0700119 void onDraw(SkCanvas* canvas) override {
bsalomon7c5c9da2014-06-09 15:11:30 -0700120 for (int i = 0; i < kCnt; ++i) {
121 fPaint.setColor(fColors[i]);
Mike Reed91919132019-01-02 12:21:01 -0500122 fFont.setSize(fPtSizes[i]);
123 fFont.setTypeface(fTypefaces[fTypefaceIndices[i]]);
bsalomon7c5c9da2014-06-09 15:11:30 -0700124
125 canvas->save();
126 canvas->clipRect(fClipRects[i]);
127 canvas->translate(fPositions[i].fX, fPositions[i].fY);
Ben Wagner51e15a62019-05-07 15:38:46 -0400128 canvas->drawSimpleText(fStrings[i].c_str(), fStrings[i].size(), SkTextEncoding::kUTF8,
Mike Reed91919132019-01-02 12:21:01 -0500129 0, 0, fFont, fPaint);
bsalomon7c5c9da2014-06-09 15:11:30 -0700130 canvas->restore();
131 }
132
133 // Visualize the clips, but not in bench mode.
134 if (kBench_Mode != this->getMode()) {
135 SkPaint wirePaint;
136 wirePaint.setAntiAlias(true);
137 wirePaint.setStrokeWidth(0);
138 wirePaint.setStyle(SkPaint::kStroke_Style);
139 for (int i = 0; i < kCnt; ++i) {
140 canvas->drawRect(fClipRects[i], wirePaint);
141 }
142 }
143 }
144
mtklein36352bf2015-03-25 18:17:31 -0700145 bool runAsBench() const override { return true; }
bsalomon7c5c9da2014-06-09 15:11:30 -0700146
147private:
mtkleindbfd7ab2016-09-01 11:24:54 -0700148 static constexpr int kCnt = 30;
149 static constexpr int kMinLength = 15;
150 static constexpr int kMaxLength = 40;
bsalomon7c5c9da2014-06-09 15:11:30 -0700151
152 bool fEffectiveClip;
153 bool fLCD;
bungeman13b9c952016-05-12 10:09:30 -0700154 sk_sp<SkTypeface> fTypefaces[4];
bsalomon7c5c9da2014-06-09 15:11:30 -0700155 SkPaint fPaint;
Mike Reed91919132019-01-02 12:21:01 -0500156 SkFont fFont;
bsalomon7c5c9da2014-06-09 15:11:30 -0700157
158 // precomputed for each text draw
159 SkString fStrings[kCnt];
160 SkColor fColors[kCnt];
161 SkScalar fPtSizes[kCnt];
bungeman13b9c952016-05-12 10:09:30 -0700162 int fTypefaceIndices[kCnt];
bsalomon7c5c9da2014-06-09 15:11:30 -0700163 SkPoint fPositions[kCnt];
164 SkRect fClipRects[kCnt];
165
166 typedef skiagm::GM INHERITED;
167};
168
halcanary385fe4d2015-08-26 13:07:48 -0700169DEF_GM(return new VariedTextGM(false, false);)
170DEF_GM(return new VariedTextGM(true, false);)
171DEF_GM(return new VariedTextGM(false, true);)
172DEF_GM(return new VariedTextGM(true, true);)