1 /*
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 "modules/sksg/include/SkSGText.h"
9
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkPath.h"
12 #include "include/core/SkTextBlob.h"
13 #include "include/core/SkTypeface.h"
14
15 #include <utility>
16
17 class SkMatrix;
18
19 namespace sksg {
20
Make(sk_sp<SkTypeface> tf,const SkString & text)21 sk_sp<Text> Text::Make(sk_sp<SkTypeface> tf, const SkString& text) {
22 return sk_sp<Text>(new Text(std::move(tf), text));
23 }
24
Text(sk_sp<SkTypeface> tf,const SkString & text)25 Text::Text(sk_sp<SkTypeface> tf, const SkString& text)
26 : fTypeface(std::move(tf))
27 , fText(text) {}
28
29 Text::~Text() = default;
30
alignedPosition(SkScalar advance) const31 SkPoint Text::alignedPosition(SkScalar advance) const {
32 auto aligned = fPosition;
33
34 switch (fAlign) {
35 case SkTextUtils::kLeft_Align:
36 break;
37 case SkTextUtils::kCenter_Align:
38 aligned.offset(-advance / 2, 0);
39 break;
40 case SkTextUtils::kRight_Align:
41 aligned.offset(-advance, 0);
42 break;
43 }
44
45 return aligned;
46 }
47
onRevalidate(InvalidationController *,const SkMatrix &)48 SkRect Text::onRevalidate(InvalidationController*, const SkMatrix&) {
49 // TODO: we could potentially track invals which don't require rebuilding the blob.
50
51 SkFont font;
52 font.setTypeface(fTypeface);
53 font.setSize(fSize);
54 font.setScaleX(fScaleX);
55 font.setSkewX(fSkewX);
56 font.setEdging(fEdging);
57 font.setHinting(fHinting);
58
59 // N.B.: fAlign is applied externally (in alignedPosition()), because
60 // 1) SkTextBlob has some trouble computing accurate bounds with alignment.
61 // 2) SkPaint::Align is slated for deprecation.
62
63 fBlob = SkTextBlob::MakeFromText(fText.c_str(), fText.size(), font, SkTextEncoding::kUTF8);
64 if (!fBlob) {
65 return SkRect::MakeEmpty();
66 }
67
68 const auto& bounds = fBlob->bounds();
69 const auto aligned_pos = this->alignedPosition(bounds.width());
70
71 return bounds.makeOffset(aligned_pos.x(), aligned_pos.y());
72 }
73
onDraw(SkCanvas * canvas,const SkPaint & paint) const74 void Text::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
75 const auto aligned_pos = this->alignedPosition(this->bounds().width());
76 canvas->drawTextBlob(fBlob, aligned_pos.x(), aligned_pos.y(), paint);
77 }
78
onContains(const SkPoint & p) const79 bool Text::onContains(const SkPoint& p) const {
80 return this->asPath().contains(p.x(), p.y());
81 }
82
onAsPath() const83 SkPath Text::onAsPath() const {
84 // TODO
85 return SkPath();
86 }
87
onClip(SkCanvas * canvas,bool antiAlias) const88 void Text::onClip(SkCanvas* canvas, bool antiAlias) const {
89 canvas->clipPath(this->asPath(), antiAlias);
90 }
91
92 } // namespace sksg
93