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/SkFontTypes.h" 13 #include "include/core/SkPaint.h" 14 #include "include/core/SkPoint.h" 15 #include "include/core/SkRefCnt.h" 16 #include "include/core/SkScalar.h" 17 #include "include/core/SkShader.h" 18 #include "include/core/SkSize.h" 19 #include "include/core/SkString.h" 20 #include "include/core/SkTextBlob.h" 21 #include "include/core/SkTileMode.h" 22 #include "include/core/SkTypeface.h" 23 #include "include/core/SkTypes.h" 24 #include "include/effects/SkGradientShader.h" 25 #include "include/private/base/SkTDArray.h" 26 #include "tools/ToolUtils.h" 27 #include "tools/fonts/FontToolUtils.h" 28 29 #include <math.h> 30 #include <string.h> 31 32 // This GM exercises drawTextBlob offset vs. shader space behavior. 33 class TextBlobShaderGM : public skiagm::GM { 34 public: TextBlobShaderGM()35 TextBlobShaderGM() {} 36 37 private: onOnceBeforeDraw()38 void onOnceBeforeDraw() override { 39 { 40 SkFont font = ToolUtils::DefaultPortableFont(); 41 const char* txt = "Blobber"; 42 size_t txtLen = strlen(txt); 43 fGlyphs.append(font.countText(txt, txtLen, SkTextEncoding::kUTF8)); 44 font.textToGlyphs(txt, txtLen, SkTextEncoding::kUTF8, fGlyphs.begin(), fGlyphs.size()); 45 } 46 47 SkFont font = ToolUtils::DefaultPortableFont(); 48 font.setSubpixel(true); 49 font.setEdging(SkFont::Edging::kAntiAlias); 50 font.setSize(30); 51 52 SkTextBlobBuilder builder; 53 int glyphCount = fGlyphs.size(); 54 const SkTextBlobBuilder::RunBuffer* run; 55 56 run = &builder.allocRun(font, glyphCount, 10, 10, nullptr); 57 memcpy(run->glyphs, fGlyphs.begin(), glyphCount * sizeof(uint16_t)); 58 59 run = &builder.allocRunPosH(font, glyphCount, 80, nullptr); 60 memcpy(run->glyphs, fGlyphs.begin(), glyphCount * sizeof(uint16_t)); 61 for (int i = 0; i < glyphCount; ++i) { 62 run->pos[i] = font.getSize() * i * .75f; 63 } 64 65 run = &builder.allocRunPos(font, glyphCount, nullptr); 66 memcpy(run->glyphs, fGlyphs.begin(), glyphCount * sizeof(uint16_t)); 67 for (int i = 0; i < glyphCount; ++i) { 68 run->pos[i * 2] = font.getSize() * i * .75f; 69 run->pos[i * 2 + 1] = 150 + 5 * sinf((float)i * 8 / glyphCount); 70 } 71 72 fBlob = builder.make(); 73 74 SkColor colors[2]; 75 colors[0] = SK_ColorRED; 76 colors[1] = SK_ColorGREEN; 77 78 SkScalar pos[std::size(colors)]; 79 for (unsigned i = 0; i < std::size(pos); ++i) { 80 pos[i] = (float)i / (std::size(pos) - 1); 81 } 82 83 SkISize sz = this->getISize(); 84 fShader = SkGradientShader::MakeRadial(SkPoint::Make(SkIntToScalar(sz.width() / 2), 85 SkIntToScalar(sz.height() / 2)), 86 sz.width() * .66f, colors, pos, 87 std::size(colors), 88 SkTileMode::kRepeat); 89 } 90 getName() const91 SkString getName() const override { return SkString("textblobshader"); } 92 getISize()93 SkISize getISize() override { return SkISize::Make(640, 480); } 94 onDraw(SkCanvas * canvas)95 void onDraw(SkCanvas* canvas) override { 96 SkPaint p; 97 p.setAntiAlias(true); 98 p.setStyle(SkPaint::kFill_Style); 99 p.setShader(fShader); 100 101 SkISize sz = this->getISize(); 102 constexpr int kXCount = 4; 103 constexpr int kYCount = 3; 104 for (int i = 0; i < kXCount; ++i) { 105 for (int j = 0; j < kYCount; ++j) { 106 canvas->drawTextBlob(fBlob, 107 SkIntToScalar(i * sz.width() / kXCount), 108 SkIntToScalar(j * sz.height() / kYCount), 109 p); 110 } 111 } 112 } 113 114 SkTDArray<uint16_t> fGlyphs; 115 sk_sp<SkTextBlob> fBlob; 116 sk_sp<SkShader> fShader; 117 118 using INHERITED = skiagm::GM; 119 }; 120 121 DEF_GM(return new TextBlobShaderGM;) 122