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 10 #include "SkCanvas.h" 11 #include "SkGradientShader.h" 12 #include "SkPoint.h" 13 #include "SkShader.h" 14 #include "SkTextBlob.h" 15 #include "SkTDArray.h" 16 #include "SkTypeface.h" 17 18 // This GM exercises drawTextBlob offset vs. shader space behavior. 19 class TextBlobShaderGM : public skiagm::GM { 20 public: 21 TextBlobShaderGM(const char* txt) { 22 SkPaint p; 23 size_t txtLen = strlen(txt); 24 fGlyphs.append(p.textToGlyphs(txt, txtLen, NULL)); 25 p.textToGlyphs(txt, txtLen, fGlyphs.begin()); 26 } 27 28 protected: 29 30 void onOnceBeforeDraw() override { 31 SkPaint p; 32 p.setAntiAlias(true); 33 p.setSubpixelText(true); 34 p.setTextSize(30); 35 p.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 36 37 SkTextBlobBuilder builder; 38 int glyphCount = fGlyphs.count(); 39 const SkTextBlobBuilder::RunBuffer* run; 40 41 run = &builder.allocRun(p, glyphCount, 10, 10, NULL); 42 memcpy(run->glyphs, fGlyphs.begin(), glyphCount * sizeof(uint16_t)); 43 44 run = &builder.allocRunPosH(p, glyphCount, 80, NULL); 45 memcpy(run->glyphs, fGlyphs.begin(), glyphCount * sizeof(uint16_t)); 46 for (int i = 0; i < glyphCount; ++i) { 47 run->pos[i] = p.getTextSize() * i * .75f; 48 } 49 50 run = &builder.allocRunPos(p, glyphCount, NULL); 51 memcpy(run->glyphs, fGlyphs.begin(), glyphCount * sizeof(uint16_t)); 52 for (int i = 0; i < glyphCount; ++i) { 53 run->pos[i * 2] = p.getTextSize() * i * .75f; 54 run->pos[i * 2 + 1] = 150 + 5 * sinf((float)i * 8 / glyphCount); 55 } 56 57 fBlob.reset(builder.build()); 58 59 SkColor colors[2]; 60 colors[0] = SK_ColorRED; 61 colors[1] = SK_ColorGREEN; 62 63 SkScalar pos[SK_ARRAY_COUNT(colors)]; 64 for (unsigned i = 0; i < SK_ARRAY_COUNT(pos); ++i) { 65 pos[i] = (float)i / (SK_ARRAY_COUNT(pos) - 1); 66 } 67 68 SkISize sz = this->onISize(); 69 fShader.reset(SkGradientShader::CreateRadial(SkPoint::Make(SkIntToScalar(sz.width() / 2), 70 SkIntToScalar(sz.height() / 2)), 71 sz.width() * .66f, colors, pos, 72 SK_ARRAY_COUNT(colors), 73 SkShader::kRepeat_TileMode)); 74 } 75 76 SkString onShortName() override { 77 return SkString("textblobshader"); 78 } 79 80 SkISize onISize() override { 81 return SkISize::Make(640, 480); 82 } 83 84 void onDraw(SkCanvas* canvas) override { 85 SkPaint p; 86 p.setStyle(SkPaint::kFill_Style); 87 p.setShader(fShader); 88 89 SkISize sz = this->onISize(); 90 static const int kXCount = 4; 91 static const int kYCount = 3; 92 for (int i = 0; i < kXCount; ++i) { 93 for (int j = 0; j < kYCount; ++j) { 94 canvas->drawTextBlob(fBlob, 95 SkIntToScalar(i * sz.width() / kXCount), 96 SkIntToScalar(j * sz.height() / kYCount), 97 p); 98 } 99 } 100 } 101 102 private: 103 SkTDArray<uint16_t> fGlyphs; 104 SkAutoTUnref<const SkTextBlob> fBlob; 105 SkAutoTUnref<SkShader> fShader; 106 107 typedef skiagm::GM INHERITED; 108 }; 109 110 DEF_GM( return SkNEW_ARGS(TextBlobShaderGM, ("Blobber")); ) 111