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