xref: /third_party/skia/gm/colrv1.cpp (revision cb93a386)
1/*
2 * Copyright 2021 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/SkFontMetrics.h"
13#include "include/core/SkPaint.h"
14#include "include/core/SkRefCnt.h"
15#include "include/core/SkScalar.h"
16#include "include/core/SkSize.h"
17#include "include/core/SkString.h"
18#include "include/core/SkTypeface.h"
19#include "tools/Resources.h"
20#include "tools/ToolUtils.h"
21
22#include <string.h>
23#include <initializer_list>
24
25namespace skiagm {
26
27class ColrV1GM : public GM {
28public:
29
30  // TODO(drott): Consolidate test fonts.
31  enum ColrV1TestType {
32    kSkiaSampleFont,
33    kColorFontsRepoGradients,
34    kColorFontsRepoScaling,
35    kColorFontsRepoExtendMode,
36    kColorFontsRepoRotate,
37    kColorFontsRepoSkew,
38    kColorFontsRepoTransform,
39    kColorFontsRepoClipBox,
40    kColorFontsRepoComposite,
41    kColorFontsRepoForeground
42  };
43
44  ColrV1GM(ColrV1TestType testType, SkScalar skewX, SkScalar rotateDeg)
45          : fSkewX(skewX), fRotateDeg(rotateDeg), fTestType(testType) {}
46
47protected:
48    static SkString testTypeToString(ColrV1TestType testType) {
49        switch (testType) {
50            case kSkiaSampleFont:
51                return SkString("skia");
52            case kColorFontsRepoGradients:
53                return SkString("gradients");
54            case kColorFontsRepoScaling:
55                return SkString("scaling");
56            case kColorFontsRepoExtendMode:
57                return SkString("extend_mode");
58            case kColorFontsRepoRotate:
59                return SkString("rotate");
60            case kColorFontsRepoSkew:
61                return SkString("skew");
62            case kColorFontsRepoTransform:
63                return SkString("transform");
64            case kColorFontsRepoClipBox:
65                return SkString("clipbox");
66            case kColorFontsRepoComposite:
67                return SkString("composite");
68            case kColorFontsRepoForeground:
69                return SkString("foreground");
70        }
71        SkASSERT(false); /* not reached */
72        return SkString();
73    }
74
75    struct EmojiFont {
76        sk_sp<SkTypeface> fTypeface;
77        std::vector<uint16_t> fGlyphs;
78        size_t bytesize() { return fGlyphs.size() * sizeof(uint16_t); }
79    } fEmojiFont;
80
81    void onOnceBeforeDraw() override {
82        if (fTestType == kSkiaSampleFont) {
83            fEmojiFont.fTypeface = MakeResourceAsTypeface("fonts/colrv1_samples.ttf");
84            fEmojiFont.fGlyphs = {19, 33, 34, 35, 20, 21, 22, 23, 24, 25};
85            return;
86        }
87
88        fEmojiFont.fTypeface = MakeResourceAsTypeface("fonts/more_samples-glyf_colr_1.ttf");
89
90        switch (fTestType) {
91            case kSkiaSampleFont:
92                SkASSERT(false);
93                break;
94            case kColorFontsRepoGradients:
95                fEmojiFont.fGlyphs = {2, 5, 6, 7, 8};
96                break;
97            case kColorFontsRepoScaling:
98                fEmojiFont.fGlyphs = {9, 10, 11, 12, 13, 14};
99                break;
100            case kColorFontsRepoExtendMode:
101                fEmojiFont.fGlyphs = {15, 16, 17, 18, 19, 20};
102                break;
103            case kColorFontsRepoRotate:
104                fEmojiFont.fGlyphs = {21, 22, 23, 24};
105                break;
106            case kColorFontsRepoSkew:
107                fEmojiFont.fGlyphs = {25, 26, 27, 28, 29, 30};
108                break;
109            case kColorFontsRepoTransform:
110                fEmojiFont.fGlyphs = {31, 32, 33, 34};
111                break;
112            case kColorFontsRepoClipBox:
113                fEmojiFont.fGlyphs = {35, 36, 37, 38, 39};
114                break;
115            case kColorFontsRepoComposite:
116                fEmojiFont.fGlyphs = {40, 41, 42, 43, 44, 45, 46};
117                break;
118            case kColorFontsRepoForeground:
119                fEmojiFont.fGlyphs = {47, 48, 49, 50, 51, 52, 53, 54};
120                break;
121        }
122    }
123
124    SkString onShortName() override {
125        SkString gm_name = SkStringPrintf("colrv1_%s_samples",
126                                          testTypeToString(fTestType).c_str());
127        if (fSkewX) {
128            gm_name.append("_skew");
129        }
130
131        if (fRotateDeg) {
132            gm_name.append("_rotate");
133        }
134        return gm_name;
135    }
136
137    SkISize onISize() override { return SkISize::Make(1400, 600); }
138
139    DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
140        canvas->drawColor(SK_ColorWHITE);
141        SkPaint paint;
142
143        canvas->translate(200, 20);
144
145        if (!fEmojiFont.fTypeface) {
146          *errorMsg = "Did not recognize COLR v1 font format.";
147          return DrawResult::kSkip;
148        }
149
150        canvas->rotate(fRotateDeg);
151        canvas->skew(fSkewX, 0);
152
153        SkFont font(fEmojiFont.fTypeface);
154
155        SkFontMetrics metrics;
156        SkScalar y = 0;
157        std::vector<SkColor> paint_colors = {
158                SK_ColorBLACK, SK_ColorGREEN, SK_ColorRED, SK_ColorBLUE};
159        auto paint_color_iterator = paint_colors.begin();
160        for (SkScalar textSize : { 12, 18, 30, 120 }) {
161            font.setSize(textSize);
162            font.getMetrics(&metrics);
163            y += -metrics.fAscent;
164            paint.setColor(*paint_color_iterator);
165            canvas->drawSimpleText(fEmojiFont.fGlyphs.data(),
166                                   fEmojiFont.bytesize(),
167                                   SkTextEncoding::kGlyphID,
168                                   10, y, font, paint);
169            y += metrics.fDescent + metrics.fLeading;
170            paint_color_iterator++;
171        }
172        return DrawResult::kOk;
173    }
174
175private:
176    using INHERITED = GM;
177    SkScalar fSkewX;
178    SkScalar fRotateDeg;
179    ColrV1TestType fTestType;
180};
181
182DEF_GM(return new ColrV1GM(ColrV1GM::kSkiaSampleFont, 0.f, 0.f);)
183DEF_GM(return new ColrV1GM(ColrV1GM::kSkiaSampleFont, -0.5f, 0.f);)
184DEF_GM(return new ColrV1GM(ColrV1GM::kSkiaSampleFont, 0.f, 20.f);)
185DEF_GM(return new ColrV1GM(ColrV1GM::kSkiaSampleFont, -0.5f, 20.f);)
186DEF_GM(return new ColrV1GM(ColrV1GM::kColorFontsRepoGradients, 0.f, 0.f);)
187DEF_GM(return new ColrV1GM(ColrV1GM::kColorFontsRepoScaling, 0.f, 0.f);)
188DEF_GM(return new ColrV1GM(ColrV1GM::kColorFontsRepoExtendMode, 0.f, 0.f);)
189DEF_GM(return new ColrV1GM(ColrV1GM::kColorFontsRepoRotate, 0.f, 0.f);)
190DEF_GM(return new ColrV1GM(ColrV1GM::kColorFontsRepoSkew, 0.f, 0.f);)
191DEF_GM(return new ColrV1GM(ColrV1GM::kColorFontsRepoTransform, 0.f, 0.f);)
192DEF_GM(return new ColrV1GM(ColrV1GM::kColorFontsRepoClipBox, 0.f, 0.f);)
193DEF_GM(return new ColrV1GM(ColrV1GM::kColorFontsRepoClipBox, -0.5f, 20.f);)
194DEF_GM(return new ColrV1GM(ColrV1GM::kColorFontsRepoComposite, 0.f, 0.f);)
195DEF_GM(return new ColrV1GM(ColrV1GM::kColorFontsRepoForeground, 0.f, 0.f);)
196
197}  // namespace skiagm
198