1 /* 2 * Copyright 2020 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/SkRSXform.h" 11 #include "include/core/SkShader.h" 12 #include "include/core/SkSurface.h" 13 #include "include/core/SkTextBlob.h" 14 #include "tools/ToolUtils.h" 15 16 // Exercises RSX text blobs + shader with various local matrix combinations. 17 // Yellow grid should stay aligned for text vs. background. 18 class RSXShaderGM : public skiagm::GM { 19 public: 20 private: onShortName()21 SkString onShortName() override { 22 return SkString("rsx_blob_shader"); 23 } 24 onISize()25 SkISize onISize() override { 26 return SkISize::Make(kSZ*kScale*2.1f, kSZ*kScale*2.1f); 27 } 28 onOnceBeforeDraw()29 void onOnceBeforeDraw() override { 30 const SkFontStyle style(SkFontStyle::kExtraBlack_Weight, 31 SkFontStyle::kNormal_Width, 32 SkFontStyle::kUpright_Slant); 33 SkFont font(ToolUtils::create_portable_typeface(nullptr, style), kFontSZ); 34 font.setEdging(SkFont::Edging::kAntiAlias); 35 36 static constexpr char txt[] = "TEST"; 37 SkGlyphID glyphs[16]; 38 float widths[16]; 39 const auto glyph_count = font.textToGlyphs(txt, strlen(txt), SkTextEncoding::kUTF8, 40 glyphs, SK_ARRAY_COUNT(glyphs)); 41 font.getWidths(glyphs, glyph_count, widths); 42 43 SkTextBlobBuilder builder; 44 const auto& buf = builder.allocRunRSXform(font, glyph_count); 45 std::copy(glyphs, glyphs + glyph_count, buf.glyphs); 46 47 float x = 0; 48 for (int i = 0; i < glyph_count; ++i) { 49 buf.xforms()[i] = { 50 1, 0, 51 x, 0, 52 }; 53 x += widths[i]; 54 } 55 56 fBlob = builder.make(); 57 } 58 onDraw(SkCanvas * canvas)59 void onDraw(SkCanvas* canvas) override { 60 canvas->scale(kScale, kScale); 61 this->draw_one(canvas, 62 {0, 0}, SkMatrix::I(), SkMatrix::I()); 63 this->draw_one(canvas, 64 {kSZ*1.1f, 0}, SkMatrix::Scale(2, 2), SkMatrix::I()); 65 this->draw_one(canvas, 66 {0, kSZ*1.1f}, SkMatrix::I(), SkMatrix::RotateDeg(45)); 67 this->draw_one(canvas, 68 {kSZ*1.1f, kSZ*1.1f}, SkMatrix::Scale(2, 2), SkMatrix::RotateDeg(45)); 69 } 70 draw_one(SkCanvas * canvas,SkPoint pos,const SkMatrix & lm,const SkMatrix & outer_lm) const71 void draw_one(SkCanvas* canvas, SkPoint pos, const SkMatrix& lm, 72 const SkMatrix& outer_lm) const { 73 SkAutoCanvasRestore acr(canvas, true); 74 canvas->translate(pos.fX, pos.fY); 75 76 SkPaint p; 77 p.setShader(make_shader(lm, outer_lm)); 78 p.setAlphaf(0.75f); 79 canvas->drawRect(SkRect::MakeWH(kSZ, kSZ), p); 80 81 p.setAlphaf(1); 82 canvas->drawTextBlob(fBlob, 0, kFontSZ*1, p); 83 canvas->drawTextBlob(fBlob, 0, kFontSZ*2, p); 84 } 85 make_shader(const SkMatrix & lm,const SkMatrix & outer_lm)86 static sk_sp<SkShader> make_shader(const SkMatrix& lm, const SkMatrix& outer_lm) { 87 static constexpr SkISize kTileSize = { 30, 30 }; 88 auto surface = SkSurface::MakeRasterN32Premul(kTileSize.width(), kTileSize.height()); 89 90 SkPaint p; 91 p.setColor(0xffffff00); 92 surface->getCanvas()->drawPaint(p); 93 p.setColor(0xff008000); 94 surface->getCanvas() 95 ->drawRect({0, 0, kTileSize.width()*0.9f, kTileSize.height()*0.9f}, p); 96 97 return surface->makeImageSnapshot() 98 ->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, 99 SkSamplingOptions(SkFilterMode::kLinear), &lm) 100 ->makeWithLocalMatrix(outer_lm); 101 } 102 103 static constexpr float kSZ = 300, 104 kFontSZ = kSZ * 0.38, 105 kScale = 1.4f; 106 107 sk_sp<SkTextBlob> fBlob; 108 }; 109 110 DEF_GM(return new RSXShaderGM;) 111