• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/SkFont.h"
11 #include "include/core/SkPaint.h"
12 #include "include/core/SkRSXform.h"
13 #include "include/core/SkSpan.h"
14 #include "include/private/base/SkTDArray.h"
15 #include "src/base/SkZip.h"
16 #include "tools/ToolUtils.h"
17 
18 static const char gText[] = "Call me Ishmael. Some years ago—never mind how long precisely";
19 
20 class DrawGlyphsGM : public skiagm::GM {
21 public:
onOnceBeforeDraw()22     void onOnceBeforeDraw() override {
23         fTypeface = ToolUtils::create_portable_typeface("serif", SkFontStyle());
24         fFont = SkFont(fTypeface);
25         fFont.setSubpixel(true);
26         fFont.setSize(18);
27         const size_t txtLen = strlen(gText);
28         fGlyphCount = fFont.countText(gText, txtLen, SkTextEncoding::kUTF8);
29 
30         fGlyphs.append(fGlyphCount);
31         fFont.textToGlyphs(gText, txtLen, SkTextEncoding::kUTF8, fGlyphs.begin(), fGlyphCount);
32 
33         fPositions.append(fGlyphCount);
34         fFont.getPos(fGlyphs.begin(), fGlyphCount, fPositions.begin());
35         auto positions = SkSpan(fPositions.begin(), fGlyphCount);
36 
37         fLength = positions.back().x() - positions.front().x();
38         fRadius = fLength / SK_FloatPI;
39         fXforms.append(fGlyphCount);
40 
41         for (auto [xform, pos] : SkMakeZip(fXforms.begin(), positions)) {
42             const SkScalar lengthToGlyph = pos.x() - positions.front().x();
43             const SkScalar angle = SK_FloatPI * (fLength - lengthToGlyph) / fLength;
44             const SkScalar cos = std::cos(angle);
45             const SkScalar sin = std::sin(angle);
46             xform = SkRSXform::Make(sin, cos, fRadius*cos, -fRadius*sin);
47         }
48     }
49 
onShortName()50     SkString onShortName() override {
51         return SkString("drawglyphs");
52     }
53 
onISize()54     SkISize onISize() override {
55         return SkISize::Make(640, 480);
56     }
57 
onDraw(SkCanvas * canvas)58     void onDraw(SkCanvas* canvas) override {
59         canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fPositions.begin(), {50, 100}, fFont,
60                            SkPaint{});
61 
62         canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fPositions.begin(), {50, 120}, fFont,
63                            SkPaint{});
64 
65         // Check bounding box calculation.
66         for (auto& pos : fPositions) {
67             pos += {0, -500};
68         }
69         canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fPositions.begin(), {50, 640}, fFont,
70                            SkPaint{});
71 
72         canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fXforms.begin(),
73                            {50 + fLength / 2, 160 + fRadius}, fFont, SkPaint{});
74 
75         // TODO: add tests for cluster versions of drawGlyphs.
76     }
77 
78 private:
79     sk_sp<SkTypeface>   fTypeface;
80     SkFont fFont;
81     SkTDArray<SkGlyphID> fGlyphs;
82     SkTDArray<SkPoint>   fPositions;
83     SkTDArray<SkRSXform> fXforms;
84     int fGlyphCount;
85     SkScalar fRadius;
86     SkScalar fLength;
87 };
88 
89 DEF_GM(return new DrawGlyphsGM{};)
90