From 51012ce332016cca5160b5a63b91a04b6cb56899 Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Wed, 31 Jan 2018 17:06:59 -0500 Subject: [sksg] Initial text support Use the new node type for SkottieSlide2 labels. TBR= Change-Id: Icd6a4faf1c281bd83a2331c0072d1a6ed71acc09 Reviewed-on: https://skia-review.googlesource.com/102441 Reviewed-by: Florin Malita Commit-Queue: Florin Malita --- experimental/sksg/geometry/SkSGGeometryTransform.h | 2 +- experimental/sksg/geometry/SkSGMerge.h | 2 + experimental/sksg/geometry/SkSGPath.h | 2 + experimental/sksg/geometry/SkSGRect.h | 4 ++ experimental/sksg/geometry/SkSGText.cpp | 77 ++++++++++++++++++++++ experimental/sksg/geometry/SkSGText.h | 69 +++++++++++++++++++ experimental/sksg/geometry/SkSGTrimEffect.h | 2 + 7 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 experimental/sksg/geometry/SkSGText.cpp create mode 100644 experimental/sksg/geometry/SkSGText.h (limited to 'experimental') diff --git a/experimental/sksg/geometry/SkSGGeometryTransform.h b/experimental/sksg/geometry/SkSGGeometryTransform.h index ea990c6f29..fe7e026031 100644 --- a/experimental/sksg/geometry/SkSGGeometryTransform.h +++ b/experimental/sksg/geometry/SkSGGeometryTransform.h @@ -50,7 +50,7 @@ private: const sk_sp fMatrix; SkPath fTransformed; - typedef GeometryNode INHERITED; + using INHERITED = GeometryNode; }; } diff --git a/experimental/sksg/geometry/SkSGMerge.h b/experimental/sksg/geometry/SkSGMerge.h index 69f824e011..54924d6475 100644 --- a/experimental/sksg/geometry/SkSGMerge.h +++ b/experimental/sksg/geometry/SkSGMerge.h @@ -55,6 +55,8 @@ private: std::vector> fGeos; SkPath fMerged; Mode fMode; + + using INHERITED = GeometryNode; }; } // namespace sksg diff --git a/experimental/sksg/geometry/SkSGPath.h b/experimental/sksg/geometry/SkSGPath.h index 6dd259394b..a398e2f0a4 100644 --- a/experimental/sksg/geometry/SkSGPath.h +++ b/experimental/sksg/geometry/SkSGPath.h @@ -38,6 +38,8 @@ private: explicit Path(const SkPath&); SkPath fPath; + + using INHERITED = GeometryNode; }; } // namespace sksg diff --git a/experimental/sksg/geometry/SkSGRect.h b/experimental/sksg/geometry/SkSGRect.h index a99c76ab98..f5fcb962c6 100644 --- a/experimental/sksg/geometry/SkSGRect.h +++ b/experimental/sksg/geometry/SkSGRect.h @@ -42,6 +42,8 @@ private: explicit Rect(const SkRect&); SkRect fRect; + + using INHERITED = GeometryNode; }; /** @@ -65,6 +67,8 @@ private: explicit RRect(const SkRRect&); SkRRect fRRect; + + using INHERITED = GeometryNode; }; } // namespace sksg diff --git a/experimental/sksg/geometry/SkSGText.cpp b/experimental/sksg/geometry/SkSGText.cpp new file mode 100644 index 0000000000..c149390023 --- /dev/null +++ b/experimental/sksg/geometry/SkSGText.cpp @@ -0,0 +1,77 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkSGText.h" + +#include "SkCanvas.h" +#include "SkPaint.h" +#include "SkPath.h" +#include "SkTArray.h" +#include "SkTextBlob.h" +#include "SkTypeface.h" + +namespace sksg { + +sk_sp Text::Make(sk_sp tf, const SkString& text) { + return sk_sp(new Text(std::move(tf), text)); +} + +Text::Text(sk_sp tf, const SkString& text) + : fTypeface(std::move(tf)) + , fText(text) {} + +Text::~Text() = default; + +SkRect Text::onRevalidate(InvalidationController*, const SkMatrix&) { + // TODO: we could potentially track invals which don't require rebuilding the blob. + + SkPaint font; + font.setFlags(fFlags); + font.setTypeface(fTypeface); + font.setTextSize(fSize); + font.setTextScaleX(fScaleX); + font.setTextSkewX(fSkewX); + font.setTextAlign(fAlign); + font.setHinting(fHinting); + + // First, convert to glyphIDs. + font.setTextEncoding(SkPaint::kUTF8_TextEncoding); + SkSTArray<256, SkGlyphID, true> glyphs; + glyphs.reset(font.textToGlyphs(fText.c_str(), fText.size(), nullptr)); + SkAssertResult(font.textToGlyphs(fText.c_str(), fText.size(), glyphs.begin()) == glyphs.count()); + font.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + + // Next, build the cached blob. + SkTextBlobBuilder builder; + const auto& buf = builder.allocRun(font, glyphs.count(), 0, 0, nullptr); + if (!buf.glyphs) { + fBlob.reset(); + return SkRect::MakeEmpty(); + } + + memcpy(buf.glyphs, glyphs.begin(), glyphs.count() * sizeof(SkGlyphID)); + + fBlob = builder.make(); + return fBlob + ? fBlob->bounds().makeOffset(fPosition.x(), fPosition.y()) + : SkRect::MakeEmpty(); +} + +void Text::onDraw(SkCanvas* canvas, const SkPaint& paint) const { + canvas->drawTextBlob(fBlob, fPosition.x(), fPosition.y(), paint); +} + +SkPath Text::onAsPath() const { + // TODO + return SkPath(); +} + +void Text::onClip(SkCanvas* canvas, bool antiAlias) const { + canvas->clipPath(this->asPath(), antiAlias); +} + +} // namespace sksg diff --git a/experimental/sksg/geometry/SkSGText.h b/experimental/sksg/geometry/SkSGText.h new file mode 100644 index 0000000000..eb43337a10 --- /dev/null +++ b/experimental/sksg/geometry/SkSGText.h @@ -0,0 +1,69 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkSGText_DEFINED +#define SkSGText_DEFINED + +#include "SkSGGeometryNode.h" + +#include "SkPaintDefaults.h" +#include "SkPoint.h" +#include "SkString.h" + +class SkCanvas; +class SkPaint; +class SkTextBlob; +class SkTypeface; + +namespace sksg { + +/** + * Concrete Geometry node, wrapping a (shaped) SkTextBlob. + */ +class Text final : public GeometryNode { +public: + static sk_sp Make(sk_sp tf, const SkString& text); + ~Text() override; + + SG_ATTRIBUTE(Text , SkString , fText ) + SG_ATTRIBUTE(Flags , uint32_t , fFlags ) + SG_ATTRIBUTE(Position, SkPoint , fPosition) + SG_ATTRIBUTE(Size , SkScalar , fSize ) + SG_ATTRIBUTE(ScaleX , SkScalar , fScaleX ) + SG_ATTRIBUTE(SkewX , SkScalar , fSkewX ) + SG_ATTRIBUTE(Align , SkPaint::Align, fAlign ) + + // TODO: add shaping functionality. + +protected: + void onClip(SkCanvas*, bool antiAlias) const override; + void onDraw(SkCanvas*, const SkPaint&) const override; + + SkRect onRevalidate(InvalidationController*, const SkMatrix&) override; + SkPath onAsPath() const override; + +private: + explicit Text(sk_sp, const SkString&); + + const sk_sp fTypeface; + SkString fText; + uint32_t fFlags = SkPaintDefaults_Flags; + SkPoint fPosition = SkPoint::Make(0, 0); + SkScalar fSize = SkPaintDefaults_TextSize; + SkScalar fScaleX = 1; + SkScalar fSkewX = 0; + SkPaint::Align fAlign = SkPaint::kLeft_Align; + SkPaint::Hinting fHinting = SkPaintDefaults_Hinting; + + sk_sp fBlob; // cached text blob + + using INHERITED = GeometryNode; +}; + +} // namespace sksg + +#endif // SkSGText_DEFINED diff --git a/experimental/sksg/geometry/SkSGTrimEffect.h b/experimental/sksg/geometry/SkSGTrimEffect.h index 860cfafc25..e86ede83e6 100644 --- a/experimental/sksg/geometry/SkSGTrimEffect.h +++ b/experimental/sksg/geometry/SkSGTrimEffect.h @@ -47,6 +47,8 @@ private: SkScalar fStart = 0, // starting t fEnd = 1, // ending t fOffset = 0; // t offset + + using INHERITED = GeometryNode; }; } // namespace sksg -- cgit v1.2.3