blob: 0d6bed95ac0ce688872d84c29df3293f0ff29217 [file] [log] [blame]
Florin Malita51012ce2018-01-31 17:06:59 -05001/*
2 * Copyright 2018 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 "SkSGText.h"
9
10#include "SkCanvas.h"
11#include "SkPaint.h"
12#include "SkPath.h"
13#include "SkTArray.h"
Florin Malita51012ce2018-01-31 17:06:59 -050014#include "SkTypeface.h"
15
16namespace sksg {
17
18sk_sp<Text> Text::Make(sk_sp<SkTypeface> tf, const SkString& text) {
19 return sk_sp<Text>(new Text(std::move(tf), text));
20}
21
22Text::Text(sk_sp<SkTypeface> tf, const SkString& text)
23 : fTypeface(std::move(tf))
24 , fText(text) {}
25
26Text::~Text() = default;
27
Florin Malita77af3862018-08-15 16:51:42 -040028SkPoint Text::alignedPosition(SkScalar advance) const {
29 auto aligned = fPosition;
30
31 switch (fAlign) {
Mike Reed3a42ec02018-10-30 12:53:21 -040032 case SkTextUtils::kLeft_Align:
Florin Malita77af3862018-08-15 16:51:42 -040033 break;
Mike Reed3a42ec02018-10-30 12:53:21 -040034 case SkTextUtils::kCenter_Align:
Florin Malita77af3862018-08-15 16:51:42 -040035 aligned.offset(-advance / 2, 0);
36 break;
Mike Reed3a42ec02018-10-30 12:53:21 -040037 case SkTextUtils::kRight_Align:
Florin Malita77af3862018-08-15 16:51:42 -040038 aligned.offset(-advance, 0);
39 break;
40 }
41
42 return aligned;
43}
44
Florin Malita51012ce2018-01-31 17:06:59 -050045SkRect Text::onRevalidate(InvalidationController*, const SkMatrix&) {
46 // TODO: we could potentially track invals which don't require rebuilding the blob.
47
Mike Reed2ed78202018-11-21 15:10:08 -050048 SkFont font;
Florin Malita51012ce2018-01-31 17:06:59 -050049 font.setTypeface(fTypeface);
Mike Reed2ed78202018-11-21 15:10:08 -050050 font.setSize(fSize);
51 font.setScaleX(fScaleX);
52 font.setSkewX(fSkewX);
Florin Malitaf7d6ac12018-11-21 16:03:58 -050053 font.setEdging(fEdging);
Florin Malita51012ce2018-01-31 17:06:59 -050054 font.setHinting(fHinting);
55
Florin Malita77af3862018-08-15 16:51:42 -040056 // N.B.: fAlign is applied externally (in alignedPosition()), because
57 // 1) SkTextBlob has some trouble computing accurate bounds with alignment.
58 // 2) SkPaint::Align is slated for deprecation.
59
Florin Malita51012ce2018-01-31 17:06:59 -050060 // First, convert to glyphIDs.
Florin Malita51012ce2018-01-31 17:06:59 -050061 SkSTArray<256, SkGlyphID, true> glyphs;
Mike Reed2ed78202018-11-21 15:10:08 -050062 glyphs.reset(font.countText(fText.c_str(), fText.size(), kUTF8_SkTextEncoding));
63 SkAssertResult(font.textToGlyphs(fText.c_str(), fText.size(), kUTF8_SkTextEncoding,
64 glyphs.begin(), glyphs.count()));
Florin Malita51012ce2018-01-31 17:06:59 -050065
66 // Next, build the cached blob.
67 SkTextBlobBuilder builder;
68 const auto& buf = builder.allocRun(font, glyphs.count(), 0, 0, nullptr);
69 if (!buf.glyphs) {
70 fBlob.reset();
71 return SkRect::MakeEmpty();
72 }
73
74 memcpy(buf.glyphs, glyphs.begin(), glyphs.count() * sizeof(SkGlyphID));
75
76 fBlob = builder.make();
Florin Malita77af3862018-08-15 16:51:42 -040077 if (!fBlob) {
78 return SkRect::MakeEmpty();
79 }
80
81 const auto& bounds = fBlob->bounds();
82 const auto aligned_pos = this->alignedPosition(bounds.width());
83
84 return bounds.makeOffset(aligned_pos.x(), aligned_pos.y());
Florin Malita51012ce2018-01-31 17:06:59 -050085}
86
87void Text::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
Florin Malita77af3862018-08-15 16:51:42 -040088 const auto aligned_pos = this->alignedPosition(this->bounds().width());
89 canvas->drawTextBlob(fBlob, aligned_pos.x(), aligned_pos.y(), paint);
Florin Malita51012ce2018-01-31 17:06:59 -050090}
91
92SkPath Text::onAsPath() const {
93 // TODO
94 return SkPath();
95}
96
97void Text::onClip(SkCanvas* canvas, bool antiAlias) const {
98 canvas->clipPath(this->asPath(), antiAlias);
99}
100
Florin Malita0a8b4e12018-11-01 11:16:18 -0400101sk_sp<TextBlob> TextBlob::Make(sk_sp<SkTextBlob> blob) {
102 return sk_sp<TextBlob>(new TextBlob(std::move(blob)));
103}
104
105TextBlob::TextBlob(sk_sp<SkTextBlob> blob)
106 : fBlob(std::move(blob)) {}
107
108TextBlob::~TextBlob() = default;
109
110SkRect TextBlob::onRevalidate(InvalidationController*, const SkMatrix&) {
111 return fBlob ? fBlob->bounds() : SkRect::MakeEmpty();
112}
113
114void TextBlob::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
115 canvas->drawTextBlob(fBlob, fPosition.x(), fPosition.y(), paint);
116}
117
118SkPath TextBlob::onAsPath() const {
119 // TODO
120 return SkPath();
121}
122
123void TextBlob::onClip(SkCanvas* canvas, bool antiAlias) const {
124 canvas->clipPath(this->asPath(), antiAlias);
125}
126
Florin Malita51012ce2018-01-31 17:06:59 -0500127} // namespace sksg