xref: /aosp_15_r20/external/skia/modules/sksg/src/SkSGText.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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