/* * Copyright 2018 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkGlyphRunInfo_DEFINED #define SkGlyphRunInfo_DEFINED #include #include #include #include "SkDescriptor.h" #include "SkMask.h" #include "SkPath.h" #include "SkPoint.h" #include "SkTypes.h" class SkBaseDevice; template class SkSpan { public: SkSpan() : fPtr{nullptr}, fSize{0} {} SkSpan(T* ptr, ptrdiff_t size) : fPtr{ptr}, fSize{size} { SkASSERT(size >= 0); } template explicit SkSpan(std::vector& v) : fPtr{v.data()}, fSize{SkTo(v.size())} {} SkSpan(const SkSpan& o) = default; SkSpan& operator=( const SkSpan& other ) = default; T& operator [] (ptrdiff_t i) const { return fPtr[i]; } T* begin() const { return fPtr; } T* end() const { return fPtr + fSize; } const T* cbegin() const { return fPtr; } const T* cend() const { return fPtr + fSize; } T* data() const { return fPtr; } ptrdiff_t size() const { return fSize; } bool empty() const { return fSize == 0; } private: T* fPtr; ptrdiff_t fSize; }; class SkGlyphRun { public: SkGlyphRun() = default; SkGlyphRun(SkPaint&& runPaint, SkSpan denseIndices, SkSpan positions, SkSpan glyphIDs, SkSpan uniqueGlyphIDs, SkSpan text, SkSpan clusters); // The temporaryShunt calls are to allow inter-operating with existing code while glyph runs // are developed. void temporaryShuntToDrawPosText(SkBaseDevice* device); using TemporaryShuntCallback = std::function; void temporaryShuntToCallback(TemporaryShuntCallback callback); size_t runSize() const { return fUniqueGlyphIDIndices.size(); } uint16_t uniqueSize() const { return fUniqueGlyphIDs.size(); } SkSpan positions() const { return fPositions; } SkSpan uniqueGlyphIDs() const { return fUniqueGlyphIDs; } SkSpan shuntGlyphsIDs() const { return fTemporaryShuntGlyphIDs; } private: // const SkSpan fUniqueGlyphIDIndices; // const SkSpan fPositions; // This is temporary while converting from the old per glyph code to the bulk code. const SkSpan fTemporaryShuntGlyphIDs; // The unique glyphs from fTemporaryShuntGlyphIDs. const SkSpan fUniqueGlyphIDs; // Original text from SkTextBlob if present. Will be empty of not present. const SkSpan fText; // Original clusters from SkTextBlob if present. Will be empty if not present. const SkSpan fClusters; // Paint for this run modified to have glyph encoding and left alignment. const SkPaint fRunPaint; }; // A faster set implementation that does not need any initialization, and reading the set items // is order the number of items, and not the size of the universe. // This implementation is based on the paper by Briggs and Torczon, "An Efficient Representation // for Sparse Sets" // // This implementation assumes that the unique glyphs added are appended to a vector that may // already have unique glyph from a previous computation. This allows the packing of multiple // UniqueID sequences in a single vector. class SkGlyphSet { public: SkGlyphSet() = default; uint16_t add(SkGlyphID glyphID); void reuse(uint32_t glyphUniverseSize, std::vector* uniqueGlyphIDs); private: uint32_t uniqueSize(); uint32_t fUniverseSize{0}; size_t fStartOfUniqueIDs{0}; std::vector fIndices; std::vector* fUniqueGlyphIDs{nullptr}; }; class SkGlyphRunBuilder { public: SkGlyphRunBuilder() = default; void prepareDrawText( const SkPaint& paint, const void* bytes, size_t byteLength, SkPoint origin); void prepareDrawPosTextH( const SkPaint& paint, const void* bytes, size_t byteLength, const SkScalar xpos[], SkScalar constY); void prepareDrawPosText( const SkPaint& paint, const void* bytes, size_t byteLength, const SkPoint pos[]); void prepareTextBlob(const SkPaint& paint, const SkTextBlob& blob, SkPoint origin); SkGlyphRun* useGlyphRun(); private: void initialize(); void addDenseAndUnique(const SkPaint& paint, const void* bytes, size_t byteLength); void makeGlyphRun( const SkPaint& runPaint, SkSpan text, SkSpan clusters); void drawText( const SkPaint& paint, const void* bytes, size_t byteLength, SkPoint origin, SkSpan text, SkSpan clusters); void drawPosTextH( const SkPaint& paint, const void* bytes, size_t byteLength, const SkScalar* xpos, SkScalar constY, SkSpan text, SkSpan clusters); void drawPosText( const SkPaint& paint, const void* bytes, size_t byteLength, const SkPoint* pos, SkSpan text, SkSpan clusters); uint64_t fUniqueID{0}; std::vector fDenseIndex; std::vector fPositions; std::vector fUniqueGlyphIDs; SkGlyphID* fGlyphIDs{nullptr}; // Used as a temporary for preparing using utfN text. This implies that only one run of // glyph ids will ever be needed because blobs are already glyph based. std::vector fScratchGlyphIDs; // Used as temporary storage for calculating positions for drawText. std::vector fScratchAdvances; // Used as temporary glyph run for the rest of the Text stack. SkGlyphRun fScratchGlyphRun; // Used for collecting the set of unique glyphs. SkGlyphSet fGlyphSet; }; #endif // SkGlyphRunInfo_DEFINED