| /* | |
| * Copyright 2021 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "gm/gm.h" | |
| #include "include/core/SkCanvas.h" | |
| #include "include/core/SkFont.h" | |
| #include "include/core/SkPaint.h" | |
| #include "include/core/SkRSXform.h" | |
| #include "include/core/SkSpan.h" | |
| #include "include/private/SkTDArray.h" | |
| #include "src/core/SkZip.h" | |
| #include "tools/ToolUtils.h" | |
| #include "tools/fonts/FontToolUtils.h" | |
| static const char gText[] = "Call me Ishmael. Some years ago—never mind how long precisely"; | |
| class DrawGlyphsGM : public skiagm::GM { | |
| public: | |
| void onOnceBeforeDraw() override { | |
| fTypeface = ToolUtils::CreatePortableTypeface("serif", SkFontStyle()); | |
| fFont = SkFont(fTypeface); | |
| fFont.setSubpixel(true); | |
| fFont.setSize(18); | |
| const size_t txtLen = strlen(gText); | |
| fGlyphCount = fFont.countText(gText, txtLen, SkTextEncoding::kUTF8); | |
| fGlyphs.append(fGlyphCount); | |
| fFont.textToGlyphs(gText, txtLen, SkTextEncoding::kUTF8, fGlyphs); | |
| fPositions.append(fGlyphCount); | |
| fFont.getPos(fGlyphs, fPositions); | |
| auto positions = SkSpan(fPositions.begin(), fGlyphCount); | |
| fLength = positions.back().x() - positions.front().x(); | |
| fRadius = fLength / SK_FloatPI; | |
| fXforms.append(fGlyphCount); | |
| for (auto [xform, pos] : SkMakeZip(fXforms.begin(), positions)) { | |
| const SkScalar lengthToGlyph = pos.x() - positions.front().x(); | |
| const SkScalar angle = SK_FloatPI * (fLength - lengthToGlyph) / fLength; | |
| const SkScalar cos = std::cos(angle); | |
| const SkScalar sin = std::sin(angle); | |
| xform = SkRSXform::Make(sin, cos, fRadius*cos, -fRadius*sin); | |
| } | |
| } | |
| SkString getName() const override { return SkString("drawglyphs"); } | |
| SkISize getISize() override { return SkISize::Make(640, 480); } | |
| void onDraw(SkCanvas* canvas) override { | |
| SkSpan<const SkGlyphID> glyphs = {fGlyphs.data(), (size_t)fGlyphCount}; | |
| SkSpan<SkPoint> pos = {fPositions.data(), (size_t)fGlyphCount}; | |
| canvas->drawGlyphs(glyphs, pos, {50, 100}, fFont, SkPaint{}); | |
| canvas->drawGlyphs(glyphs, pos, {50, 120}, fFont, SkPaint{}); | |
| // Check bounding box calculation. | |
| for (auto& p : fPositions) { | |
| p += {0, -500}; | |
| } | |
| canvas->drawGlyphs(glyphs, pos, {50, 640}, fFont, SkPaint{}); | |
| canvas->drawGlyphsRSXform(fGlyphs, fXforms, | |
| {50 + fLength / 2, 160 + fRadius}, fFont, SkPaint{}); | |
| // TODO: add tests for cluster versions of drawGlyphs. | |
| } | |
| private: | |
| sk_sp<SkTypeface> fTypeface; | |
| SkFont fFont; | |
| SkTDArray<SkGlyphID> fGlyphs; | |
| SkTDArray<SkPoint> fPositions; | |
| SkTDArray<SkRSXform> fXforms; | |
| int fGlyphCount; | |
| SkScalar fRadius; | |
| SkScalar fLength; | |
| }; | |
| DEF_GM(return new DrawGlyphsGM{};) |