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.h" 9 #include "sk_tool_utils.h" 10 #include "SkCanvas.h" 11 #include "SkPath.h" 12 #include "SkTypeface.h" 13 #include "SkRandom.h" 14 15 /** 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. 18 */ 19 20 class VariedTextGM : public skiagm::GM { 21 public: VariedTextGM(bool effectiveClip,bool lcd)22 VariedTextGM(bool effectiveClip, bool lcd) 23 : fEffectiveClip(effectiveClip) 24 , fLCD(lcd) { 25 } 26 27 protected: onShortName()28 SkString onShortName() override { 29 SkString name("varied_text"); 30 if (fEffectiveClip) { 31 name.append("_clipped"); 32 } else { 33 name.append("_ignorable_clip"); 34 } 35 if (fLCD) { 36 name.append("_lcd"); 37 } else { 38 name.append("_no_lcd"); 39 } 40 return name; 41 } 42 onISize()43 SkISize onISize() override { 44 return SkISize::Make(640, 480); 45 } 46 onOnceBeforeDraw()47 void onOnceBeforeDraw() override { 48 fPaint.setAntiAlias(true); 49 fPaint.setLCDRenderText(fLCD); 50 51 SkISize size = this->getISize(); 52 SkScalar w = SkIntToScalar(size.fWidth); 53 SkScalar h = SkIntToScalar(size.fHeight); 54 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", SkFontStyle::Bold()); 58 fTypefaces[2] = sk_tool_utils::create_portable_typeface("serif", SkFontStyle()); 59 fTypefaces[3] = sk_tool_utils::create_portable_typeface("serif", SkFontStyle::Bold()); 60 61 SkRandom random; 62 for (int i = 0; i < kCnt; ++i) { 63 int length = random.nextRangeU(kMinLength, kMaxLength); 64 char text[kMaxLength]; 65 for (int j = 0; j < length; ++j) { 66 text[j] = (char)random.nextRangeU('!', 'z'); 67 } 68 fStrings[i].set(text, length); 69 70 fColors[i] = random.nextU(); 71 fColors[i] |= 0xFF000000; 72 fColors[i] = sk_tool_utils::color_to_565(fColors[i]); 73 74 constexpr SkScalar kMinPtSize = 8.f; 75 constexpr SkScalar kMaxPtSize = 32.f; 76 77 fPtSizes[i] = random.nextRangeScalar(kMinPtSize, kMaxPtSize); 78 79 fTypefaceIndices[i] = random.nextULessThan(SK_ARRAY_COUNT(fTypefaces)); 80 81 SkRect r; 82 fPaint.setColor(fColors[i]); 83 fPaint.setTypeface(fTypefaces[fTypefaceIndices[i]]); 84 fPaint.setTextSize(fPtSizes[i]); 85 86 fPaint.measureText(fStrings[i].c_str(), fStrings[i].size(), &r); 87 // safeRect is set of x,y positions where we can draw the string without hitting 88 // the GM's border. 89 SkRect safeRect = SkRect::MakeLTRB(-r.fLeft, -r.fTop, w - r.fRight, h - r.fBottom); 90 if (safeRect.isEmpty()) { 91 // If we don't fit then just don't worry about how we get cliped to the device 92 // border. 93 safeRect = SkRect::MakeWH(w, h); 94 } 95 fPositions[i].fX = random.nextRangeScalar(safeRect.fLeft, safeRect.fRight); 96 fPositions[i].fY = random.nextRangeScalar(safeRect.fTop, safeRect.fBottom); 97 98 fClipRects[i] = r; 99 fClipRects[i].offset(fPositions[i].fX, fPositions[i].fY); 100 fClipRects[i].outset(2.f, 2.f); 101 102 if (fEffectiveClip) { 103 fClipRects[i].fRight -= 0.25f * fClipRects[i].width(); 104 } 105 } 106 } 107 onDraw(SkCanvas * canvas)108 void onDraw(SkCanvas* canvas) override { 109 for (int i = 0; i < kCnt; ++i) { 110 fPaint.setColor(fColors[i]); 111 fPaint.setTextSize(fPtSizes[i]); 112 fPaint.setTypeface(fTypefaces[fTypefaceIndices[i]]); 113 114 canvas->save(); 115 canvas->clipRect(fClipRects[i]); 116 canvas->translate(fPositions[i].fX, fPositions[i].fY); 117 canvas->drawString(fStrings[i], 0, 0, fPaint); 118 canvas->restore(); 119 } 120 121 // Visualize the clips, but not in bench mode. 122 if (kBench_Mode != this->getMode()) { 123 SkPaint wirePaint; 124 wirePaint.setAntiAlias(true); 125 wirePaint.setStrokeWidth(0); 126 wirePaint.setStyle(SkPaint::kStroke_Style); 127 for (int i = 0; i < kCnt; ++i) { 128 canvas->drawRect(fClipRects[i], wirePaint); 129 } 130 } 131 } 132 runAsBench() const133 bool runAsBench() const override { return true; } 134 135 private: 136 static constexpr int kCnt = 30; 137 static constexpr int kMinLength = 15; 138 static constexpr int kMaxLength = 40; 139 140 bool fEffectiveClip; 141 bool fLCD; 142 sk_sp<SkTypeface> fTypefaces[4]; 143 SkPaint fPaint; 144 145 // precomputed for each text draw 146 SkString fStrings[kCnt]; 147 SkColor fColors[kCnt]; 148 SkScalar fPtSizes[kCnt]; 149 int fTypefaceIndices[kCnt]; 150 SkPoint fPositions[kCnt]; 151 SkRect fClipRects[kCnt]; 152 153 typedef skiagm::GM INHERITED; 154 }; 155 156 DEF_GM(return new VariedTextGM(false, false);) 157 DEF_GM(return new VariedTextGM(true, false);) 158 DEF_GM(return new VariedTextGM(false, true);) 159 DEF_GM(return new VariedTextGM(true, true);) 160