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. 32class TextBlobShaderGM : public skiagm::GM { 33public: 34 TextBlobShaderGM() {} 35 36private: 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 91 SkString onShortName() override { 92 return SkString("textblobshader"); 93 } 94 95 SkISize onISize() override { 96 return SkISize::Make(640, 480); 97 } 98 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 125DEF_GM(return new TextBlobShaderGM;) 126