• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
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/gm.h"
9  #include "include/core/SkCanvas.h"
10  #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"
21  #include "include/core/SkTypeface.h"
22  #include "include/core/SkTypes.h"
23  #include "include/utils/SkRandom.h"
24  #include "tools/ToolUtils.h"
25  
26  /**
27   * Draws text with random parameters. The text draws each get their own clip rect. It is also
28   * used as a bench to measure how well the GPU backend combines draw ops for text draws.
29   */
30  
31  class VariedTextGM : public skiagm::GM {
32  public:
VariedTextGM(bool effectiveClip,bool lcd)33      VariedTextGM(bool effectiveClip, bool lcd)
34          : fEffectiveClip(effectiveClip)
35          , fLCD(lcd) {
36      }
37  
38  protected:
onShortName()39      SkString onShortName() override {
40          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  
onISize()54      SkISize onISize() override {
55          return SkISize::Make(640, 480);
56      }
57  
onOnceBeforeDraw()58      void onOnceBeforeDraw() override {
59          fPaint.setAntiAlias(true);
60          fFont.setEdging(fLCD ? SkFont::Edging::kSubpixelAntiAlias : SkFont::Edging::kAntiAlias);
61  
62          SkISize size = this->getISize();
63          SkScalar w = SkIntToScalar(size.fWidth);
64          SkScalar h = SkIntToScalar(size.fHeight);
65  
66          static_assert(4 == SK_ARRAY_COUNT(fTypefaces), "typeface_cnt");
67          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());
71  
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;
83              fColors[i] = ToolUtils::color_to_565(fColors[i]);
84  
85              constexpr SkScalar kMinPtSize = 8.f;
86              constexpr SkScalar kMaxPtSize = 32.f;
87  
88              fPtSizes[i] = random.nextRangeScalar(kMinPtSize, kMaxPtSize);
89  
90              fTypefaceIndices[i] = random.nextULessThan(SK_ARRAY_COUNT(fTypefaces));
91  
92              SkRect r;
93              fPaint.setColor(fColors[i]);
94              fFont.setTypeface(fTypefaces[fTypefaceIndices[i]]);
95              fFont.setSize(fPtSizes[i]);
96  
97              fFont.measureText(fStrings[i].c_str(), fStrings[i].size(), SkTextEncoding::kUTF8, &r);
98              // 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  
onDraw(SkCanvas * canvas)119      void onDraw(SkCanvas* canvas) override {
120          for (int i = 0; i < kCnt; ++i) {
121              fPaint.setColor(fColors[i]);
122              fFont.setSize(fPtSizes[i]);
123              fFont.setTypeface(fTypefaces[fTypefaceIndices[i]]);
124  
125              canvas->save();
126                  canvas->clipRect(fClipRects[i]);
127                  canvas->translate(fPositions[i].fX, fPositions[i].fY);
128                  canvas->drawSimpleText(fStrings[i].c_str(), fStrings[i].size(), SkTextEncoding::kUTF8,
129                                         0, 0, fFont, fPaint);
130              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  
runAsBench() const145      bool runAsBench() const override { return true; }
146  
147  private:
148      static constexpr int kCnt = 30;
149      static constexpr int kMinLength = 15;
150      static constexpr int kMaxLength = 40;
151  
152      bool        fEffectiveClip;
153      bool        fLCD;
154      sk_sp<SkTypeface> fTypefaces[4];
155      SkPaint     fPaint;
156      SkFont      fFont;
157  
158      // precomputed for each text draw
159      SkString        fStrings[kCnt];
160      SkColor         fColors[kCnt];
161      SkScalar        fPtSizes[kCnt];
162      int             fTypefaceIndices[kCnt];
163      SkPoint         fPositions[kCnt];
164      SkRect          fClipRects[kCnt];
165  
166      typedef skiagm::GM INHERITED;
167  };
168  
169  DEF_GM(return new VariedTextGM(false, false);)
170  DEF_GM(return new VariedTextGM(true, false);)
171  DEF_GM(return new VariedTextGM(false, true);)
172  DEF_GM(return new VariedTextGM(true, true);)
173