1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2021 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h" 9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h" 10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFont.h" 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRSXform.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSpan.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTDArray.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkZip.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h" 18*c8dee2aaSAndroid Build Coastguard Worker 19*c8dee2aaSAndroid Build Coastguard Worker static const char gText[] = "Call me Ishmael. Some years ago—never mind how long precisely"; 20*c8dee2aaSAndroid Build Coastguard Worker 21*c8dee2aaSAndroid Build Coastguard Worker class DrawGlyphsGM : public skiagm::GM { 22*c8dee2aaSAndroid Build Coastguard Worker public: onOnceBeforeDraw()23*c8dee2aaSAndroid Build Coastguard Worker void onOnceBeforeDraw() override { 24*c8dee2aaSAndroid Build Coastguard Worker fTypeface = ToolUtils::CreatePortableTypeface("serif", SkFontStyle()); 25*c8dee2aaSAndroid Build Coastguard Worker fFont = SkFont(fTypeface); 26*c8dee2aaSAndroid Build Coastguard Worker fFont.setSubpixel(true); 27*c8dee2aaSAndroid Build Coastguard Worker fFont.setSize(18); 28*c8dee2aaSAndroid Build Coastguard Worker const size_t txtLen = strlen(gText); 29*c8dee2aaSAndroid Build Coastguard Worker fGlyphCount = fFont.countText(gText, txtLen, SkTextEncoding::kUTF8); 30*c8dee2aaSAndroid Build Coastguard Worker 31*c8dee2aaSAndroid Build Coastguard Worker fGlyphs.append(fGlyphCount); 32*c8dee2aaSAndroid Build Coastguard Worker fFont.textToGlyphs(gText, txtLen, SkTextEncoding::kUTF8, fGlyphs.begin(), fGlyphCount); 33*c8dee2aaSAndroid Build Coastguard Worker 34*c8dee2aaSAndroid Build Coastguard Worker fPositions.append(fGlyphCount); 35*c8dee2aaSAndroid Build Coastguard Worker fFont.getPos(fGlyphs.begin(), fGlyphCount, fPositions.begin()); 36*c8dee2aaSAndroid Build Coastguard Worker auto positions = SkSpan(fPositions.begin(), fGlyphCount); 37*c8dee2aaSAndroid Build Coastguard Worker 38*c8dee2aaSAndroid Build Coastguard Worker fLength = positions.back().x() - positions.front().x(); 39*c8dee2aaSAndroid Build Coastguard Worker fRadius = fLength / SK_FloatPI; 40*c8dee2aaSAndroid Build Coastguard Worker fXforms.append(fGlyphCount); 41*c8dee2aaSAndroid Build Coastguard Worker 42*c8dee2aaSAndroid Build Coastguard Worker for (auto [xform, pos] : SkMakeZip(fXforms.begin(), positions)) { 43*c8dee2aaSAndroid Build Coastguard Worker const SkScalar lengthToGlyph = pos.x() - positions.front().x(); 44*c8dee2aaSAndroid Build Coastguard Worker const SkScalar angle = SK_FloatPI * (fLength - lengthToGlyph) / fLength; 45*c8dee2aaSAndroid Build Coastguard Worker const SkScalar cos = std::cos(angle); 46*c8dee2aaSAndroid Build Coastguard Worker const SkScalar sin = std::sin(angle); 47*c8dee2aaSAndroid Build Coastguard Worker xform = SkRSXform::Make(sin, cos, fRadius*cos, -fRadius*sin); 48*c8dee2aaSAndroid Build Coastguard Worker } 49*c8dee2aaSAndroid Build Coastguard Worker } 50*c8dee2aaSAndroid Build Coastguard Worker getName() const51*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return SkString("drawglyphs"); } 52*c8dee2aaSAndroid Build Coastguard Worker getISize()53*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(640, 480); } 54*c8dee2aaSAndroid Build Coastguard Worker onDraw(SkCanvas * canvas)55*c8dee2aaSAndroid Build Coastguard Worker void onDraw(SkCanvas* canvas) override { 56*c8dee2aaSAndroid Build Coastguard Worker canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fPositions.begin(), {50, 100}, fFont, 57*c8dee2aaSAndroid Build Coastguard Worker SkPaint{}); 58*c8dee2aaSAndroid Build Coastguard Worker 59*c8dee2aaSAndroid Build Coastguard Worker canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fPositions.begin(), {50, 120}, fFont, 60*c8dee2aaSAndroid Build Coastguard Worker SkPaint{}); 61*c8dee2aaSAndroid Build Coastguard Worker 62*c8dee2aaSAndroid Build Coastguard Worker // Check bounding box calculation. 63*c8dee2aaSAndroid Build Coastguard Worker for (auto& pos : fPositions) { 64*c8dee2aaSAndroid Build Coastguard Worker pos += {0, -500}; 65*c8dee2aaSAndroid Build Coastguard Worker } 66*c8dee2aaSAndroid Build Coastguard Worker canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fPositions.begin(), {50, 640}, fFont, 67*c8dee2aaSAndroid Build Coastguard Worker SkPaint{}); 68*c8dee2aaSAndroid Build Coastguard Worker 69*c8dee2aaSAndroid Build Coastguard Worker canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fXforms.begin(), 70*c8dee2aaSAndroid Build Coastguard Worker {50 + fLength / 2, 160 + fRadius}, fFont, SkPaint{}); 71*c8dee2aaSAndroid Build Coastguard Worker 72*c8dee2aaSAndroid Build Coastguard Worker // TODO: add tests for cluster versions of drawGlyphs. 73*c8dee2aaSAndroid Build Coastguard Worker } 74*c8dee2aaSAndroid Build Coastguard Worker 75*c8dee2aaSAndroid Build Coastguard Worker private: 76*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTypeface> fTypeface; 77*c8dee2aaSAndroid Build Coastguard Worker SkFont fFont; 78*c8dee2aaSAndroid Build Coastguard Worker SkTDArray<SkGlyphID> fGlyphs; 79*c8dee2aaSAndroid Build Coastguard Worker SkTDArray<SkPoint> fPositions; 80*c8dee2aaSAndroid Build Coastguard Worker SkTDArray<SkRSXform> fXforms; 81*c8dee2aaSAndroid Build Coastguard Worker int fGlyphCount; 82*c8dee2aaSAndroid Build Coastguard Worker SkScalar fRadius; 83*c8dee2aaSAndroid Build Coastguard Worker SkScalar fLength; 84*c8dee2aaSAndroid Build Coastguard Worker }; 85*c8dee2aaSAndroid Build Coastguard Worker 86*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new DrawGlyphsGM{};) 87