| /* |
| * Copyright 2021 Google Inc. |
| * |
| * 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" |
| |
| 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::create_portable_typeface("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.begin(), fGlyphCount); |
| |
| fPositions.append(fGlyphCount); |
| fFont.getPos(fGlyphs.begin(), fGlyphCount, fPositions.begin()); |
| auto positions = SkMakeSpan(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 onShortName() override { |
| return SkString("drawglyphs"); |
| } |
| |
| SkISize onISize() override { |
| return SkISize::Make(640, 480); |
| } |
| |
| void onDraw(SkCanvas* canvas) override { |
| canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fPositions.begin(), {50, 100}, fFont, |
| SkPaint{}); |
| |
| canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fPositions.begin(), {50, 120}, fFont, |
| SkPaint{}); |
| |
| // Check bounding box calculation. |
| for (auto& pos : fPositions) { |
| pos += {0, -500}; |
| } |
| canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fPositions.begin(), {50, 640}, fFont, |
| SkPaint{}); |
| |
| canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fXforms.begin(), |
| {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{};) |