blob: 92dfb26f6d535c8aade5bafaeb5a6b82919652a3 [file] [log] [blame]
Herb Derbye90a2952021-04-16 11:31:39 -04001/*
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"
Herb Derbyf9cf1aa2021-04-21 10:57:25 -040012#include "include/core/SkRSXform.h"
Brian Osmana5842bc2021-05-11 13:41:46 -040013#include "include/core/SkSpan.h"
Herb Derbye90a2952021-04-16 11:31:39 -040014#include "include/private/SkTDArray.h"
Herb Derbyf9cf1aa2021-04-21 10:57:25 -040015#include "src/core/SkZip.h"
Herb Derbye90a2952021-04-16 11:31:39 -040016#include "tools/ToolUtils.h"
17
18static const char gText[] = "Call me Ishmael. Some years ago—never mind how long precisely";
19
20class DrawGlyphsGM : public skiagm::GM {
21public:
22 void onOnceBeforeDraw() override {
23 fTypeface = ToolUtils::create_portable_typeface("serif", SkFontStyle());
24 fFont = SkFont(fTypeface);
25 fFont.setSubpixel(true);
26 fFont.setSize(18);
Herb Derbyf9cf1aa2021-04-21 10:57:25 -040027 const size_t txtLen = strlen(gText);
Herb Derbye90a2952021-04-16 11:31:39 -040028 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());
Brian Osmanae87bf12021-05-11 13:36:10 -040035 auto positions = SkMakeSpan(fPositions.begin(), fGlyphCount);
Herb Derbyf9cf1aa2021-04-21 10:57:25 -040036
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 }
Herb Derbye90a2952021-04-16 11:31:39 -040048 }
49
50 SkString onShortName() override {
51 return SkString("drawglyphs");
52 }
53
54 SkISize onISize() override {
55 return SkISize::Make(640, 480);
56 }
57
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
Herb Derbyf9cf1aa2021-04-21 10:57:25 -040072 canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fXforms.begin(),
73 {50 + fLength / 2, 160 + fRadius}, fFont, SkPaint{});
74
Herb Derbye90a2952021-04-16 11:31:39 -040075 // TODO: add tests for cluster versions of drawGlyphs.
76 }
77
78private:
79 sk_sp<SkTypeface> fTypeface;
80 SkFont fFont;
81 SkTDArray<SkGlyphID> fGlyphs;
Herb Derbyf9cf1aa2021-04-21 10:57:25 -040082 SkTDArray<SkPoint> fPositions;
83 SkTDArray<SkRSXform> fXforms;
Herb Derbye90a2952021-04-16 11:31:39 -040084 int fGlyphCount;
Herb Derbyf9cf1aa2021-04-21 10:57:25 -040085 SkScalar fRadius;
86 SkScalar fLength;
Herb Derbye90a2952021-04-16 11:31:39 -040087};
88
89DEF_GM(return new DrawGlyphsGM{};)