2021-04-16 15:31:39 +00:00
|
|
|
/*
|
|
|
|
* 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"
|
2021-04-21 14:57:25 +00:00
|
|
|
#include "include/core/SkRSXform.h"
|
2021-05-11 17:41:46 +00:00
|
|
|
#include "include/core/SkSpan.h"
|
2021-04-16 15:31:39 +00:00
|
|
|
#include "include/private/SkTDArray.h"
|
2021-04-21 14:57:25 +00:00
|
|
|
#include "src/core/SkZip.h"
|
2021-04-16 15:31:39 +00:00
|
|
|
#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);
|
2021-04-21 14:57:25 +00:00
|
|
|
const size_t txtLen = strlen(gText);
|
2021-04-16 15:31:39 +00:00
|
|
|
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());
|
2021-05-11 17:36:10 +00:00
|
|
|
auto positions = SkMakeSpan(fPositions.begin(), fGlyphCount);
|
2021-04-21 14:57:25 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2021-04-16 15:31:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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{});
|
|
|
|
|
2021-04-21 14:57:25 +00:00
|
|
|
canvas->drawGlyphs(fGlyphCount, fGlyphs.begin(), fXforms.begin(),
|
|
|
|
{50 + fLength / 2, 160 + fRadius}, fFont, SkPaint{});
|
|
|
|
|
2021-04-16 15:31:39 +00:00
|
|
|
// TODO: add tests for cluster versions of drawGlyphs.
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
sk_sp<SkTypeface> fTypeface;
|
|
|
|
SkFont fFont;
|
|
|
|
SkTDArray<SkGlyphID> fGlyphs;
|
2021-04-21 14:57:25 +00:00
|
|
|
SkTDArray<SkPoint> fPositions;
|
|
|
|
SkTDArray<SkRSXform> fXforms;
|
2021-04-16 15:31:39 +00:00
|
|
|
int fGlyphCount;
|
2021-04-21 14:57:25 +00:00
|
|
|
SkScalar fRadius;
|
|
|
|
SkScalar fLength;
|
2021-04-16 15:31:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
DEF_GM(return new DrawGlyphsGM{};)
|