2 * Copyright 2014 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "sk_tool_utils.h"
12 #include "SkTypeface.h"
16 * Draws text with random parameters. The text draws each get their own clip rect. It is also
17 * used as a bench to measure how well the GPU backend combines draw ops for text draws.
20 class VariedTextGM : public skiagm::GM {
22 VariedTextGM(bool effectiveClip, bool lcd)
23 : fEffectiveClip(effectiveClip)
28 SkString onShortName() override {
29 SkString name("varied_text");
31 name.append("_clipped");
33 name.append("_ignorable_clip");
38 name.append("_no_lcd");
43 SkISize onISize() override {
44 return SkISize::Make(640, 480);
47 void onOnceBeforeDraw() override {
48 fPaint.setAntiAlias(true);
49 fPaint.setLCDRenderText(fLCD);
51 SkISize size = this->getISize();
52 SkScalar w = SkIntToScalar(size.fWidth);
53 SkScalar h = SkIntToScalar(size.fHeight);
55 static_assert(4 == SK_ARRAY_COUNT(fTypefaces), "typeface_cnt");
56 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));
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');
70 fStrings[i].set(text, length);
72 fColors[i] = random.nextU();
73 fColors[i] |= 0xFF000000;
74 fColors[i] = sk_tool_utils::color_to_565(fColors[i]);
76 constexpr SkScalar kMinPtSize = 8.f;
77 constexpr SkScalar kMaxPtSize = 32.f;
79 fPtSizes[i] = random.nextRangeScalar(kMinPtSize, kMaxPtSize);
81 fTypefaceIndices[i] = random.nextULessThan(SK_ARRAY_COUNT(fTypefaces));
84 fPaint.setColor(fColors[i]);
85 fPaint.setTypeface(fTypefaces[fTypefaceIndices[i]]);
86 fPaint.setTextSize(fPtSizes[i]);
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
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
95 safeRect = SkRect::MakeWH(w, h);
97 fPositions[i].fX = random.nextRangeScalar(safeRect.fLeft, safeRect.fRight);
98 fPositions[i].fY = random.nextRangeScalar(safeRect.fTop, safeRect.fBottom);
101 fClipRects[i].offset(fPositions[i].fX, fPositions[i].fY);
102 fClipRects[i].outset(2.f, 2.f);
104 if (fEffectiveClip) {
105 fClipRects[i].fRight -= 0.25f * fClipRects[i].width();
110 void onDraw(SkCanvas* canvas) override {
111 for (int i = 0; i < kCnt; ++i) {
112 fPaint.setColor(fColors[i]);
113 fPaint.setTextSize(fPtSizes[i]);
114 fPaint.setTypeface(fTypefaces[fTypefaceIndices[i]]);
117 canvas->clipRect(fClipRects[i]);
118 canvas->translate(fPositions[i].fX, fPositions[i].fY);
119 canvas->drawString(fStrings[i], 0, 0, fPaint);
123 // Visualize the clips, but not in bench mode.
124 if (kBench_Mode != this->getMode()) {
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);
135 bool runAsBench() const override { return true; }
138 static constexpr int kCnt = 30;
139 static constexpr int kMinLength = 15;
140 static constexpr int kMaxLength = 40;
144 sk_sp<SkTypeface> fTypefaces[4];
147 // precomputed for each text draw
148 SkString fStrings[kCnt];
149 SkColor fColors[kCnt];
150 SkScalar fPtSizes[kCnt];
151 int fTypefaceIndices[kCnt];
152 SkPoint fPositions[kCnt];
153 SkRect fClipRects[kCnt];
155 typedef skiagm::GM INHERITED;
158 DEF_GM(return new VariedTextGM(false, false);)
159 DEF_GM(return new VariedTextGM(true, false);)
160 DEF_GM(return new VariedTextGM(false, true);)
161 DEF_GM(return new VariedTextGM(true, true);)