blob: cfd0acdac4b4912dc1536f7e861fe9642c50a344 [file] [log] [blame]
Florin Malitace613002020-12-23 11:58:16 -05001/*
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.
18class RSXShaderGM : public skiagm::GM {
19public:
20private:
21 SkString onShortName() override {
22 return SkString("rsx_blob_shader");
23 }
24
25 SkISize onISize() override {
26 return SkISize::Make(kSZ*kScale*2.1f, kSZ*kScale*2.1f);
27 }
28
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);
Florin Malita697e2462020-12-30 13:12:58 +000034 font.setEdging(SkFont::Edging::kAntiAlias);
Florin Malitace613002020-12-23 11:58:16 -050035
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
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
71 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
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()
Florin Malita697e2462020-12-30 13:12:58 +000098 ->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
Mike Reed5ec22382021-01-14 21:59:01 -050099 SkSamplingOptions(SkFilterMode::kLinear), &lm)
Florin Malitace613002020-12-23 11:58:16 -0500100 ->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
110DEF_GM(return new RSXShaderGM;)