blob: e5d04635fffdab0d0e9e80620ef9844a8802fa84 [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"
Kevin Lubickdc6cc022023-01-13 11:24:27 -050014#include "include/private/base/SkTDArray.h"
Kevin Lubicked377432023-01-25 13:34:36 -050015#include "src/base/SkZip.h"
Herb Derbye90a2952021-04-16 11:31:39 -040016#include "tools/ToolUtils.h"
Kevin Lubicke836c3a2023-10-20 06:55:35 -040017#include "tools/fonts/FontToolUtils.h"
Herb Derbye90a2952021-04-16 11:31:39 -040018
19static const char gText[] = "Call me Ishmael. Some years ago—never mind how long precisely";
20
21class DrawGlyphsGM : public skiagm::GM {
22public:
23 void onOnceBeforeDraw() override {
Kevin Lubicke836c3a2023-10-20 06:55:35 -040024 fTypeface = ToolUtils::CreatePortableTypeface("serif", SkFontStyle());
Herb Derbye90a2952021-04-16 11:31:39 -040025 fFont = SkFont(fTypeface);
26 fFont.setSubpixel(true);
27 fFont.setSize(18);
Herb Derbyf9cf1aa2021-04-21 10:57:25 -040028 const size_t txtLen = strlen(gText);
Herb Derbye90a2952021-04-16 11:31:39 -040029 fGlyphCount = fFont.countText(gText, txtLen, SkTextEncoding::kUTF8);
30
31 fGlyphs.append(fGlyphCount);
32 fFont.textToGlyphs(gText, txtLen, SkTextEncoding::kUTF8, fGlyphs.begin(), fGlyphCount);
33
34 fPositions.append(fGlyphCount);
35 fFont.getPos(fGlyphs.begin(), fGlyphCount, fPositions.begin());
Herb Derby8ccbeee2022-06-14 12:09:25 -040036 auto positions = SkSpan(fPositions.begin(), fGlyphCount);
Herb Derbyf9cf1aa2021-04-21 10:57:25 -040037
38 fLength = positions.back().x() - positions.front().x();
39 fRadius = fLength / SK_FloatPI;
40 fXforms.append(fGlyphCount);
41
42 for (auto [xform, pos] : SkMakeZip(fXforms.begin(), positions)) {
43 const SkScalar lengthToGlyph = pos.x() - positions.front().x();
44 const SkScalar angle = SK_FloatPI * (fLength - lengthToGlyph) / fLength;
45 const SkScalar cos = std::cos(angle);
46 const SkScalar sin = std::sin(angle);
47 xform = SkRSXform::Make(sin, cos, fRadius*cos, -fRadius*sin);
48 }
Herb Derbye90a2952021-04-16 11:31:39 -040049 }
50
Leandro Lovisolo24fa2112023-08-15 19:05:17 +000051 SkString getName() const override { return SkString("drawglyphs"); }
Herb Derbye90a2952021-04-16 11:31:39 -040052
Leandro Lovisolo8f023882023-08-15 21:13:52 +000053 SkISize getISize() override { return SkISize::Make(640, 480); }
Herb Derbye90a2952021-04-16 11:31:39 -040054
55 void onDraw(SkCanvas* canvas) override {
56 canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fPositions.begin(), {50, 100}, fFont,
57 SkPaint{});
58
59 canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fPositions.begin(), {50, 120}, fFont,
60 SkPaint{});
61
62 // Check bounding box calculation.
63 for (auto& pos : fPositions) {
64 pos += {0, -500};
65 }
66 canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fPositions.begin(), {50, 640}, fFont,
67 SkPaint{});
68
Herb Derbyf9cf1aa2021-04-21 10:57:25 -040069 canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fXforms.begin(),
70 {50 + fLength / 2, 160 + fRadius}, fFont, SkPaint{});
71
Herb Derbye90a2952021-04-16 11:31:39 -040072 // TODO: add tests for cluster versions of drawGlyphs.
73 }
74
75private:
76 sk_sp<SkTypeface> fTypeface;
77 SkFont fFont;
78 SkTDArray<SkGlyphID> fGlyphs;
Herb Derbyf9cf1aa2021-04-21 10:57:25 -040079 SkTDArray<SkPoint> fPositions;
80 SkTDArray<SkRSXform> fXforms;
Herb Derbye90a2952021-04-16 11:31:39 -040081 int fGlyphCount;
Herb Derbyf9cf1aa2021-04-21 10:57:25 -040082 SkScalar fRadius;
83 SkScalar fLength;
Herb Derbye90a2952021-04-16 11:31:39 -040084};
85
86DEF_GM(return new DrawGlyphsGM{};)