1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "modules/sksg/include/SkSGText.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 11cb93a386Sopenharmony_ci#include "include/core/SkPaint.h" 12cb93a386Sopenharmony_ci#include "include/core/SkPath.h" 13cb93a386Sopenharmony_ci#include "include/core/SkTypeface.h" 14cb93a386Sopenharmony_ci#include "include/private/SkTArray.h" 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_cinamespace sksg { 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_cisk_sp<Text> Text::Make(sk_sp<SkTypeface> tf, const SkString& text) { 19cb93a386Sopenharmony_ci return sk_sp<Text>(new Text(std::move(tf), text)); 20cb93a386Sopenharmony_ci} 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_ciText::Text(sk_sp<SkTypeface> tf, const SkString& text) 23cb93a386Sopenharmony_ci : fTypeface(std::move(tf)) 24cb93a386Sopenharmony_ci , fText(text) {} 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ciText::~Text() = default; 27cb93a386Sopenharmony_ci 28cb93a386Sopenharmony_ciSkPoint Text::alignedPosition(SkScalar advance) const { 29cb93a386Sopenharmony_ci auto aligned = fPosition; 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_ci switch (fAlign) { 32cb93a386Sopenharmony_ci case SkTextUtils::kLeft_Align: 33cb93a386Sopenharmony_ci break; 34cb93a386Sopenharmony_ci case SkTextUtils::kCenter_Align: 35cb93a386Sopenharmony_ci aligned.offset(-advance / 2, 0); 36cb93a386Sopenharmony_ci break; 37cb93a386Sopenharmony_ci case SkTextUtils::kRight_Align: 38cb93a386Sopenharmony_ci aligned.offset(-advance, 0); 39cb93a386Sopenharmony_ci break; 40cb93a386Sopenharmony_ci } 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_ci return aligned; 43cb93a386Sopenharmony_ci} 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_ciSkRect Text::onRevalidate(InvalidationController*, const SkMatrix&) { 46cb93a386Sopenharmony_ci // TODO: we could potentially track invals which don't require rebuilding the blob. 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ci SkFont font; 49cb93a386Sopenharmony_ci font.setTypeface(fTypeface); 50cb93a386Sopenharmony_ci font.setSize(fSize); 51cb93a386Sopenharmony_ci font.setScaleX(fScaleX); 52cb93a386Sopenharmony_ci font.setSkewX(fSkewX); 53cb93a386Sopenharmony_ci font.setEdging(fEdging); 54cb93a386Sopenharmony_ci font.setHinting(fHinting); 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci // N.B.: fAlign is applied externally (in alignedPosition()), because 57cb93a386Sopenharmony_ci // 1) SkTextBlob has some trouble computing accurate bounds with alignment. 58cb93a386Sopenharmony_ci // 2) SkPaint::Align is slated for deprecation. 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci fBlob = SkTextBlob::MakeFromText(fText.c_str(), fText.size(), font, SkTextEncoding::kUTF8); 61cb93a386Sopenharmony_ci if (!fBlob) { 62cb93a386Sopenharmony_ci return SkRect::MakeEmpty(); 63cb93a386Sopenharmony_ci } 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_ci const auto& bounds = fBlob->bounds(); 66cb93a386Sopenharmony_ci const auto aligned_pos = this->alignedPosition(bounds.width()); 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci return bounds.makeOffset(aligned_pos.x(), aligned_pos.y()); 69cb93a386Sopenharmony_ci} 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_civoid Text::onDraw(SkCanvas* canvas, const SkPaint& paint) const { 72cb93a386Sopenharmony_ci const auto aligned_pos = this->alignedPosition(this->bounds().width()); 73cb93a386Sopenharmony_ci canvas->drawTextBlob(fBlob, aligned_pos.x(), aligned_pos.y(), paint); 74cb93a386Sopenharmony_ci} 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_cibool Text::onContains(const SkPoint& p) const { 77cb93a386Sopenharmony_ci return this->asPath().contains(p.x(), p.y()); 78cb93a386Sopenharmony_ci} 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_ciSkPath Text::onAsPath() const { 81cb93a386Sopenharmony_ci // TODO 82cb93a386Sopenharmony_ci return SkPath(); 83cb93a386Sopenharmony_ci} 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_civoid Text::onClip(SkCanvas* canvas, bool antiAlias) const { 86cb93a386Sopenharmony_ci canvas->clipPath(this->asPath(), antiAlias); 87cb93a386Sopenharmony_ci} 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_cisk_sp<TextBlob> TextBlob::Make(sk_sp<SkTextBlob> blob) { 90cb93a386Sopenharmony_ci return sk_sp<TextBlob>(new TextBlob(std::move(blob))); 91cb93a386Sopenharmony_ci} 92cb93a386Sopenharmony_ci 93cb93a386Sopenharmony_ciTextBlob::TextBlob(sk_sp<SkTextBlob> blob) 94cb93a386Sopenharmony_ci : fBlob(std::move(blob)) {} 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ciTextBlob::~TextBlob() = default; 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ciSkRect TextBlob::onRevalidate(InvalidationController*, const SkMatrix&) { 99cb93a386Sopenharmony_ci return fBlob ? fBlob->bounds().makeOffset(fPosition.x(), fPosition.y()) 100cb93a386Sopenharmony_ci : SkRect::MakeEmpty(); 101cb93a386Sopenharmony_ci} 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_civoid TextBlob::onDraw(SkCanvas* canvas, const SkPaint& paint) const { 104cb93a386Sopenharmony_ci canvas->drawTextBlob(fBlob, fPosition.x(), fPosition.y(), paint); 105cb93a386Sopenharmony_ci} 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_cibool TextBlob::onContains(const SkPoint& p) const { 108cb93a386Sopenharmony_ci return this->asPath().contains(p.x(), p.y()); 109cb93a386Sopenharmony_ci} 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_ciSkPath TextBlob::onAsPath() const { 112cb93a386Sopenharmony_ci // TODO 113cb93a386Sopenharmony_ci return SkPath(); 114cb93a386Sopenharmony_ci} 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_civoid TextBlob::onClip(SkCanvas* canvas, bool antiAlias) const { 117cb93a386Sopenharmony_ci canvas->clipPath(this->asPath(), antiAlias); 118cb93a386Sopenharmony_ci} 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci} // namespace sksg 121