blob: 0595379105a6e6fab9d8b005d97391a9eb6d52bf [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"
Kevin Lubick0d4d1142023-02-13 09:13:10 -050023#include "src/base/SkRandom.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "tools/ToolUtils.h"
Kevin Lubicke836c3a2023-10-20 06:55:35 -040025#include "tools/fonts/FontToolUtils.h"
bsalomon7c5c9da2014-06-09 15:11:30 -070026
27/**
28 * Draws text with random parameters. The text draws each get their own clip rect. It is also
Brian Salomon09d994e2016-12-21 11:14:46 -050029 * used as a bench to measure how well the GPU backend combines draw ops for text draws.
bsalomon7c5c9da2014-06-09 15:11:30 -070030 */
31
32class VariedTextGM : public skiagm::GM {
33public:
34 VariedTextGM(bool effectiveClip, bool lcd)
35 : fEffectiveClip(effectiveClip)
36 , fLCD(lcd) {
bsalomon7c5c9da2014-06-09 15:11:30 -070037 }
38
39protected:
Leandro Lovisolo24fa2112023-08-15 19:05:17 +000040 SkString getName() const override {
bsalomon7c5c9da2014-06-09 15:11:30 -070041 SkString name("varied_text");
42 if (fEffectiveClip) {
43 name.append("_clipped");
44 } else {
45 name.append("_ignorable_clip");
46 }
47 if (fLCD) {
48 name.append("_lcd");
49 } else {
50 name.append("_no_lcd");
51 }
52 return name;
53 }
54
Leandro Lovisolo8f023882023-08-15 21:13:52 +000055 SkISize getISize() override { return SkISize::Make(640, 480); }
bsalomon7c5c9da2014-06-09 15:11:30 -070056
mtklein36352bf2015-03-25 18:17:31 -070057 void onOnceBeforeDraw() override {
bsalomon7c5c9da2014-06-09 15:11:30 -070058 fPaint.setAntiAlias(true);
Mike Reed91919132019-01-02 12:21:01 -050059 fFont.setEdging(fLCD ? SkFont::Edging::kSubpixelAntiAlias : SkFont::Edging::kAntiAlias);
bsalomon7c5c9da2014-06-09 15:11:30 -070060
61 SkISize size = this->getISize();
62 SkScalar w = SkIntToScalar(size.fWidth);
63 SkScalar h = SkIntToScalar(size.fHeight);
64
Herb Derbyc37b3862022-06-21 09:49:17 -040065 SkASSERTF(4 == std::size(fTypefaces), "typeface_cnt");
Kevin Lubicke836c3a2023-10-20 06:55:35 -040066 fTypefaces[0] = ToolUtils::CreatePortableTypeface("sans-serif", SkFontStyle());
67 fTypefaces[1] = ToolUtils::CreatePortableTypeface("sans-serif", SkFontStyle::Bold());
68 fTypefaces[2] = ToolUtils::CreatePortableTypeface("serif", SkFontStyle());
69 fTypefaces[3] = ToolUtils::CreatePortableTypeface("serif", SkFontStyle::Bold());
bsalomon7c5c9da2014-06-09 15:11:30 -070070
71 SkRandom random;
72 for (int i = 0; i < kCnt; ++i) {
73 int length = random.nextRangeU(kMinLength, kMaxLength);
74 char text[kMaxLength];
75 for (int j = 0; j < length; ++j) {
76 text[j] = (char)random.nextRangeU('!', 'z');
77 }
78 fStrings[i].set(text, length);
79
80 fColors[i] = random.nextU();
81 fColors[i] |= 0xFF000000;
Mike Kleinea3f0142019-03-20 11:12:10 -050082 fColors[i] = ToolUtils::color_to_565(fColors[i]);
bsalomon7c5c9da2014-06-09 15:11:30 -070083
mtkleindbfd7ab2016-09-01 11:24:54 -070084 constexpr SkScalar kMinPtSize = 8.f;
85 constexpr SkScalar kMaxPtSize = 32.f;
bsalomon7c5c9da2014-06-09 15:11:30 -070086
87 fPtSizes[i] = random.nextRangeScalar(kMinPtSize, kMaxPtSize);
88
Herb Derbyc37b3862022-06-21 09:49:17 -040089 fTypefaceIndices[i] = random.nextULessThan(std::size(fTypefaces));
bsalomon7c5c9da2014-06-09 15:11:30 -070090
91 SkRect r;
92 fPaint.setColor(fColors[i]);
Mike Reed91919132019-01-02 12:21:01 -050093 fFont.setTypeface(fTypefaces[fTypefaceIndices[i]]);
94 fFont.setSize(fPtSizes[i]);
bsalomon7c5c9da2014-06-09 15:11:30 -070095
Ben Wagner51e15a62019-05-07 15:38:46 -040096 fFont.measureText(fStrings[i].c_str(), fStrings[i].size(), SkTextEncoding::kUTF8, &r);
Ben Wagner12857d42020-09-25 14:17:30 -040097 // The set of x,y offsets which place the bounding box inside the GM's border.
bsalomon7c5c9da2014-06-09 15:11:30 -070098 SkRect safeRect = SkRect::MakeLTRB(-r.fLeft, -r.fTop, w - r.fRight, h - r.fBottom);
99 if (safeRect.isEmpty()) {
Ben Wagner12857d42020-09-25 14:17:30 -0400100 // If the bounds don't fit then allow any offset in the GM's border.
bsalomon7c5c9da2014-06-09 15:11:30 -0700101 safeRect = SkRect::MakeWH(w, h);
102 }
Ben Wagner12857d42020-09-25 14:17:30 -0400103 fOffsets[i].fX = random.nextRangeScalar(safeRect.fLeft, safeRect.fRight);
104 fOffsets[i].fY = random.nextRangeScalar(safeRect.fTop, safeRect.fBottom);
bsalomon7c5c9da2014-06-09 15:11:30 -0700105
106 fClipRects[i] = r;
Ben Wagner12857d42020-09-25 14:17:30 -0400107 fClipRects[i].offset(fOffsets[i].fX, fOffsets[i].fY);
bsalomon7c5c9da2014-06-09 15:11:30 -0700108 fClipRects[i].outset(2.f, 2.f);
109
110 if (fEffectiveClip) {
111 fClipRects[i].fRight -= 0.25f * fClipRects[i].width();
112 }
113 }
114 }
115
mtklein36352bf2015-03-25 18:17:31 -0700116 void onDraw(SkCanvas* canvas) override {
bsalomon7c5c9da2014-06-09 15:11:30 -0700117 for (int i = 0; i < kCnt; ++i) {
118 fPaint.setColor(fColors[i]);
Mike Reed91919132019-01-02 12:21:01 -0500119 fFont.setSize(fPtSizes[i]);
120 fFont.setTypeface(fTypefaces[fTypefaceIndices[i]]);
bsalomon7c5c9da2014-06-09 15:11:30 -0700121
122 canvas->save();
123 canvas->clipRect(fClipRects[i]);
Ben Wagner12857d42020-09-25 14:17:30 -0400124 canvas->translate(fOffsets[i].fX, fOffsets[i].fY);
Ben Wagner51e15a62019-05-07 15:38:46 -0400125 canvas->drawSimpleText(fStrings[i].c_str(), fStrings[i].size(), SkTextEncoding::kUTF8,
Mike Reed91919132019-01-02 12:21:01 -0500126 0, 0, fFont, fPaint);
bsalomon7c5c9da2014-06-09 15:11:30 -0700127 canvas->restore();
128 }
129
130 // Visualize the clips, but not in bench mode.
131 if (kBench_Mode != this->getMode()) {
132 SkPaint wirePaint;
133 wirePaint.setAntiAlias(true);
134 wirePaint.setStrokeWidth(0);
135 wirePaint.setStyle(SkPaint::kStroke_Style);
136 for (int i = 0; i < kCnt; ++i) {
137 canvas->drawRect(fClipRects[i], wirePaint);
138 }
139 }
140 }
141
mtklein36352bf2015-03-25 18:17:31 -0700142 bool runAsBench() const override { return true; }
bsalomon7c5c9da2014-06-09 15:11:30 -0700143
144private:
Brian Salomon9fa47cc2021-10-08 18:48:26 -0400145 inline static constexpr int kCnt = 30;
146 inline static constexpr int kMinLength = 15;
147 inline static constexpr int kMaxLength = 40;
bsalomon7c5c9da2014-06-09 15:11:30 -0700148
149 bool fEffectiveClip;
150 bool fLCD;
bungeman13b9c952016-05-12 10:09:30 -0700151 sk_sp<SkTypeface> fTypefaces[4];
bsalomon7c5c9da2014-06-09 15:11:30 -0700152 SkPaint fPaint;
Mike Reed91919132019-01-02 12:21:01 -0500153 SkFont fFont;
bsalomon7c5c9da2014-06-09 15:11:30 -0700154
155 // precomputed for each text draw
156 SkString fStrings[kCnt];
157 SkColor fColors[kCnt];
158 SkScalar fPtSizes[kCnt];
bungeman13b9c952016-05-12 10:09:30 -0700159 int fTypefaceIndices[kCnt];
Ben Wagner12857d42020-09-25 14:17:30 -0400160 SkPoint fOffsets[kCnt];
bsalomon7c5c9da2014-06-09 15:11:30 -0700161 SkRect fClipRects[kCnt];
162
John Stiles7571f9e2020-09-02 22:42:33 -0400163 using INHERITED = skiagm::GM;
bsalomon7c5c9da2014-06-09 15:11:30 -0700164};
165
halcanary385fe4d2015-08-26 13:07:48 -0700166DEF_GM(return new VariedTextGM(false, false);)
167DEF_GM(return new VariedTextGM(true, false);)
168DEF_GM(return new VariedTextGM(false, true);)
169DEF_GM(return new VariedTextGM(true, true);)