variedtext.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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. #include "gm/gm.h"
  8. #include "include/core/SkCanvas.h"
  9. #include "include/core/SkColor.h"
  10. #include "include/core/SkFont.h"
  11. #include "include/core/SkFontStyle.h"
  12. #include "include/core/SkFontTypes.h"
  13. #include "include/core/SkPaint.h"
  14. #include "include/core/SkPoint.h"
  15. #include "include/core/SkRect.h"
  16. #include "include/core/SkRefCnt.h"
  17. #include "include/core/SkScalar.h"
  18. #include "include/core/SkSize.h"
  19. #include "include/core/SkString.h"
  20. #include "include/core/SkTypeface.h"
  21. #include "include/core/SkTypes.h"
  22. #include "include/utils/SkRandom.h"
  23. #include "tools/ToolUtils.h"
  24. /**
  25. * Draws text with random parameters. The text draws each get their own clip rect. It is also
  26. * used as a bench to measure how well the GPU backend combines draw ops for text draws.
  27. */
  28. class VariedTextGM : public skiagm::GM {
  29. public:
  30. VariedTextGM(bool effectiveClip, bool lcd)
  31. : fEffectiveClip(effectiveClip)
  32. , fLCD(lcd) {
  33. }
  34. protected:
  35. SkString onShortName() override {
  36. SkString name("varied_text");
  37. if (fEffectiveClip) {
  38. name.append("_clipped");
  39. } else {
  40. name.append("_ignorable_clip");
  41. }
  42. if (fLCD) {
  43. name.append("_lcd");
  44. } else {
  45. name.append("_no_lcd");
  46. }
  47. return name;
  48. }
  49. SkISize onISize() override {
  50. return SkISize::Make(640, 480);
  51. }
  52. void onOnceBeforeDraw() override {
  53. fPaint.setAntiAlias(true);
  54. fFont.setEdging(fLCD ? SkFont::Edging::kSubpixelAntiAlias : SkFont::Edging::kAntiAlias);
  55. SkISize size = this->getISize();
  56. SkScalar w = SkIntToScalar(size.fWidth);
  57. SkScalar h = SkIntToScalar(size.fHeight);
  58. static_assert(4 == SK_ARRAY_COUNT(fTypefaces), "typeface_cnt");
  59. fTypefaces[0] = ToolUtils::create_portable_typeface("sans-serif", SkFontStyle());
  60. fTypefaces[1] = ToolUtils::create_portable_typeface("sans-serif", SkFontStyle::Bold());
  61. fTypefaces[2] = ToolUtils::create_portable_typeface("serif", SkFontStyle());
  62. fTypefaces[3] = ToolUtils::create_portable_typeface("serif", SkFontStyle::Bold());
  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. fColors[i] = random.nextU();
  72. fColors[i] |= 0xFF000000;
  73. fColors[i] = ToolUtils::color_to_565(fColors[i]);
  74. constexpr SkScalar kMinPtSize = 8.f;
  75. constexpr SkScalar kMaxPtSize = 32.f;
  76. fPtSizes[i] = random.nextRangeScalar(kMinPtSize, kMaxPtSize);
  77. fTypefaceIndices[i] = random.nextULessThan(SK_ARRAY_COUNT(fTypefaces));
  78. SkRect r;
  79. fPaint.setColor(fColors[i]);
  80. fFont.setTypeface(fTypefaces[fTypefaceIndices[i]]);
  81. fFont.setSize(fPtSizes[i]);
  82. fFont.measureText(fStrings[i].c_str(), fStrings[i].size(), SkTextEncoding::kUTF8, &r);
  83. // safeRect is set of x,y positions where we can draw the string without hitting
  84. // the GM's border.
  85. SkRect safeRect = SkRect::MakeLTRB(-r.fLeft, -r.fTop, w - r.fRight, h - r.fBottom);
  86. if (safeRect.isEmpty()) {
  87. // If we don't fit then just don't worry about how we get cliped to the device
  88. // border.
  89. safeRect = SkRect::MakeWH(w, h);
  90. }
  91. fPositions[i].fX = random.nextRangeScalar(safeRect.fLeft, safeRect.fRight);
  92. fPositions[i].fY = random.nextRangeScalar(safeRect.fTop, safeRect.fBottom);
  93. fClipRects[i] = r;
  94. fClipRects[i].offset(fPositions[i].fX, fPositions[i].fY);
  95. fClipRects[i].outset(2.f, 2.f);
  96. if (fEffectiveClip) {
  97. fClipRects[i].fRight -= 0.25f * fClipRects[i].width();
  98. }
  99. }
  100. }
  101. void onDraw(SkCanvas* canvas) override {
  102. for (int i = 0; i < kCnt; ++i) {
  103. fPaint.setColor(fColors[i]);
  104. fFont.setSize(fPtSizes[i]);
  105. fFont.setTypeface(fTypefaces[fTypefaceIndices[i]]);
  106. canvas->save();
  107. canvas->clipRect(fClipRects[i]);
  108. canvas->translate(fPositions[i].fX, fPositions[i].fY);
  109. canvas->drawSimpleText(fStrings[i].c_str(), fStrings[i].size(), SkTextEncoding::kUTF8,
  110. 0, 0, fFont, fPaint);
  111. canvas->restore();
  112. }
  113. // Visualize the clips, but not in bench mode.
  114. if (kBench_Mode != this->getMode()) {
  115. SkPaint wirePaint;
  116. wirePaint.setAntiAlias(true);
  117. wirePaint.setStrokeWidth(0);
  118. wirePaint.setStyle(SkPaint::kStroke_Style);
  119. for (int i = 0; i < kCnt; ++i) {
  120. canvas->drawRect(fClipRects[i], wirePaint);
  121. }
  122. }
  123. }
  124. bool runAsBench() const override { return true; }
  125. private:
  126. static constexpr int kCnt = 30;
  127. static constexpr int kMinLength = 15;
  128. static constexpr int kMaxLength = 40;
  129. bool fEffectiveClip;
  130. bool fLCD;
  131. sk_sp<SkTypeface> fTypefaces[4];
  132. SkPaint fPaint;
  133. SkFont fFont;
  134. // precomputed for each text draw
  135. SkString fStrings[kCnt];
  136. SkColor fColors[kCnt];
  137. SkScalar fPtSizes[kCnt];
  138. int fTypefaceIndices[kCnt];
  139. SkPoint fPositions[kCnt];
  140. SkRect fClipRects[kCnt];
  141. typedef skiagm::GM INHERITED;
  142. };
  143. DEF_GM(return new VariedTextGM(false, false);)
  144. DEF_GM(return new VariedTextGM(true, false);)
  145. DEF_GM(return new VariedTextGM(false, true);)
  146. DEF_GM(return new VariedTextGM(true, true);)