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/SkTDArray.h" 26 #include "tools/ToolUtils.h" 27 28 #include <math.h> 29 #include <string.h> 30 31 // This GM exercises drawTextBlob offset vs. shader space behavior. 32 class TextBlobShaderGM : public skiagm::GM { 33 public: TextBlobShaderGM()34 TextBlobShaderGM() {} 35 36 private: onOnceBeforeDraw()37 void onOnceBeforeDraw() override { 38 { 39 SkFont font(ToolUtils::create_portable_typeface()); 40 const char* txt = "Blobber"; 41 size_t txtLen = strlen(txt); 42 fGlyphs.append(font.countText(txt, txtLen, SkTextEncoding::kUTF8)); 43 font.textToGlyphs(txt, txtLen, SkTextEncoding::kUTF8, fGlyphs.begin(), fGlyphs.count()); 44 } 45 46 SkFont font; 47 font.setSubpixel(true); 48 font.setEdging(SkFont::Edging::kAntiAlias); 49 font.setSize(30); 50 font.setTypeface(ToolUtils::create_portable_typeface()); 51 52 SkTextBlobBuilder builder; 53 int glyphCount = fGlyphs.count(); 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[SK_ARRAY_COUNT(colors)]; 79 for (unsigned i = 0; i < SK_ARRAY_COUNT(pos); ++i) { 80 pos[i] = (float)i / (SK_ARRAY_COUNT(pos) - 1); 81 } 82 83 SkISize sz = this->onISize(); 84 fShader = SkGradientShader::MakeRadial(SkPoint::Make(SkIntToScalar(sz.width() / 2), 85 SkIntToScalar(sz.height() / 2)), 86 sz.width() * .66f, colors, pos, 87 SK_ARRAY_COUNT(colors), 88 SkTileMode::kRepeat); 89 } 90 onShortName()91 SkString onShortName() override { 92 return SkString("textblobshader"); 93 } 94 onISize()95 SkISize onISize() override { 96 return SkISize::Make(640, 480); 97 } 98 onDraw(SkCanvas * canvas)99 void onDraw(SkCanvas* canvas) override { 100 SkPaint p; 101 p.setAntiAlias(true); 102 p.setStyle(SkPaint::kFill_Style); 103 p.setShader(fShader); 104 105 SkISize sz = this->onISize(); 106 constexpr int kXCount = 4; 107 constexpr int kYCount = 3; 108 for (int i = 0; i < kXCount; ++i) { 109 for (int j = 0; j < kYCount; ++j) { 110 canvas->drawTextBlob(fBlob, 111 SkIntToScalar(i * sz.width() / kXCount), 112 SkIntToScalar(j * sz.height() / kYCount), 113 p); 114 } 115 } 116 } 117 118 SkTDArray<uint16_t> fGlyphs; 119 sk_sp<SkTextBlob> fBlob; 120 sk_sp<SkShader> fShader; 121 122 using INHERITED = skiagm::GM; 123 }; 124 125 DEF_GM(return new TextBlobShaderGM;) 126