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", 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)); 62 63 SkRandom random; 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'); 69 } 70 fStrings[i].set(text, length); 71 72 fColors[i] = random.nextU(); 73 fColors[i] |= 0xFF000000; 74 fColors[i] = sk_tool_utils::color_to_565(fColors[i]); 75 76 constexpr SkScalar kMinPtSize = 8.f; 77 constexpr SkScalar kMaxPtSize = 32.f; 78 79 fPtSizes[i] = random.nextRangeScalar(kMinPtSize, kMaxPtSize); 80 81 fTypefaceIndices[i] = random.nextULessThan(SK_ARRAY_COUNT(fTypefaces)); 82 83 SkRect r; 84 fPaint.setColor(fColors[i]); 85 fPaint.setTypeface(fTypefaces[fTypefaceIndices[i]]); 86 fPaint.setTextSize(fPtSizes[i]); 87 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 90 // the GM's border. 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 94 // border. 95 safeRect = SkRect::MakeWH(w, h); 96 } 97 fPositions[i].fX = random.nextRangeScalar(safeRect.fLeft, safeRect.fRight); 98 fPositions[i].fY = random.nextRangeScalar(safeRect.fTop, safeRect.fBottom); 99 100 fClipRects[i] = r; 101 fClipRects[i].offset(fPositions[i].fX, fPositions[i].fY); 102 fClipRects[i].outset(2.f, 2.f); 103 104 if (fEffectiveClip) { 105 fClipRects[i].fRight -= 0.25f * fClipRects[i].width(); 106 } 107 } 108 } 109 onDraw(SkCanvas * canvas)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]]); 115 116 canvas->save(); 117 canvas->clipRect(fClipRects[i]); 118 canvas->translate(fPositions[i].fX, fPositions[i].fY); 119 canvas->drawString(fStrings[i], 0, 0, fPaint); 120 canvas->restore(); 121 } 122 123 // Visualize the clips, but not in bench mode. 124 if (kBench_Mode != this->getMode()) { 125 SkPaint wirePaint; 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); 131 } 132 } 133 } 134 runAsBench() const135 bool runAsBench() const override { return true; } 136 137 private: 138 static constexpr int kCnt = 30; 139 static constexpr int kMinLength = 15; 140 static constexpr int kMaxLength = 40; 141 142 bool fEffectiveClip; 143 bool fLCD; 144 sk_sp<SkTypeface> fTypefaces[4]; 145 SkPaint fPaint; 146 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]; 154 155 typedef skiagm::GM INHERITED; 156 }; 157 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);) 162