| /* |
| * 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 SkGlyphRun_DEFINED |
| #define SkGlyphRun_DEFINED |
| |
| #include <functional> |
| #include <vector> |
| |
| #include "include/core/SkFont.h" |
| #include "include/core/SkPaint.h" |
| #include "include/core/SkPoint.h" |
| #include "include/core/SkTypes.h" |
| #include "include/private/SkTemplates.h" |
| #include "src/core/SkSpan.h" |
| #include "src/core/SkZip.h" |
| |
| class SkBaseDevice; |
| class SkGlyph; |
| class SkTextBlob; |
| class SkTextBlobRunIterator; |
| |
| class SkGlyphRun { |
| public: |
| SkGlyphRun() = default; |
| SkGlyphRun(const SkFont& font, |
| SkSpan<const SkPoint> positions, |
| SkSpan<const SkGlyphID> glyphIDs, |
| SkSpan<const char> text, |
| SkSpan<const uint32_t> clusters); |
| SkGlyphRun(const SkGlyphRun& glyphRun, const SkFont& font); |
| |
| size_t runSize() const { return fSource.size(); } |
| SkSpan<const SkPoint> positions() const { return fSource.get<1>(); } |
| SkSpan<const SkGlyphID> glyphsIDs() const { return fSource.get<0>(); } |
| SkZip<const SkGlyphID, const SkPoint> source() const { return fSource; } |
| const SkFont& font() const { return fFont; } |
| SkSpan<const uint32_t> clusters() const { return fClusters; } |
| SkSpan<const char> text() const { return fText; } |
| |
| private: |
| // GlyphIDs and positions. |
| const SkZip<const SkGlyphID, const SkPoint> fSource; |
| // Original text from SkTextBlob if present. Will be empty of not present. |
| const SkSpan<const char> fText; |
| // Original clusters from SkTextBlob if present. Will be empty if not present. |
| const SkSpan<const uint32_t> fClusters; |
| // Paint for this run modified to have glyph encoding and left alignment. |
| SkFont fFont; |
| }; |
| |
| class SkGlyphRunList { |
| SkSpan<const SkGlyphRun> fGlyphRuns; |
| |
| public: |
| SkGlyphRunList(); |
| // Blob maybe null. |
| SkGlyphRunList( |
| const SkPaint& paint, |
| const SkTextBlob* blob, |
| SkPoint origin, |
| SkSpan<const SkGlyphRun> glyphRunList); |
| |
| SkGlyphRunList(const SkGlyphRun& glyphRun, const SkPaint& paint); |
| |
| uint64_t uniqueID() const; |
| bool anyRunsLCD() const; |
| bool anyRunsSubpixelPositioned() const; |
| void temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const; |
| |
| bool canCache() const { return fOriginalTextBlob != nullptr; } |
| size_t runCount() const { return fGlyphRuns.size(); } |
| size_t totalGlyphCount() const { |
| size_t glyphCount = 0; |
| for(const auto& run : fGlyphRuns) { |
| glyphCount += run.runSize(); |
| } |
| return glyphCount; |
| } |
| bool allFontsFinite() const; |
| |
| SkPoint origin() const { return fOrigin; } |
| const SkPaint& paint() const { return *fOriginalPaint; } |
| const SkTextBlob* blob() const { return fOriginalTextBlob; } |
| |
| auto begin() -> decltype(fGlyphRuns.begin()) { return fGlyphRuns.begin(); } |
| auto end() -> decltype(fGlyphRuns.end()) { return fGlyphRuns.end(); } |
| auto begin() const -> decltype(fGlyphRuns.cbegin()) { return fGlyphRuns.cbegin(); } |
| auto end() const -> decltype(fGlyphRuns.cend()) { return fGlyphRuns.cend(); } |
| auto size() const -> decltype(fGlyphRuns.size()) { return fGlyphRuns.size(); } |
| auto empty() const -> decltype(fGlyphRuns.empty()) { return fGlyphRuns.empty(); } |
| auto operator [] (size_t i) const -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i]; } |
| |
| private: |
| const SkPaint* fOriginalPaint{nullptr}; // This should be deleted soon. |
| // The text blob is needed to hookup the call back that the SkTextBlob destructor calls. It |
| // should be used for nothing else |
| const SkTextBlob* fOriginalTextBlob{nullptr}; |
| SkPoint fOrigin = {0, 0}; |
| }; |
| |
| class SkGlyphIDSet { |
| public: |
| SkSpan<const SkGlyphID> uniquifyGlyphIDs( |
| uint32_t universeSize, SkSpan<const SkGlyphID> glyphIDs, |
| SkGlyphID* uniqueGlyphIDs, uint16_t* denseindices); |
| private: |
| size_t fUniverseToUniqueSize{0}; |
| SkAutoTMalloc<uint16_t> fUniverseToUnique; |
| }; |
| |
| class SkGlyphRunBuilder { |
| public: |
| void drawTextUTF8( |
| const SkPaint& paint, const SkFont&, const void* bytes, size_t byteLength, SkPoint origin); |
| void drawGlyphsWithPositions( |
| const SkPaint&, const SkFont&, SkSpan<const SkGlyphID> glyphIDs, const SkPoint* pos); |
| void drawTextBlob(const SkPaint& paint, const SkTextBlob& blob, SkPoint origin, SkBaseDevice*); |
| |
| void textBlobToGlyphRunListIgnoringRSXForm( |
| const SkPaint& paint, const SkTextBlob& blob, SkPoint origin); |
| |
| const SkGlyphRunList& useGlyphRunList(); |
| |
| bool empty() const { return fGlyphRunListStorage.empty(); } |
| |
| private: |
| void initialize(size_t totalRunSize); |
| SkSpan<const SkGlyphID> textToGlyphIDs( |
| const SkFont& font, const void* bytes, size_t byteLength, SkTextEncoding); |
| |
| void makeGlyphRun( |
| const SkFont& font, |
| SkSpan<const SkGlyphID> glyphIDs, |
| SkSpan<const SkPoint> positions, |
| SkSpan<const char> text, |
| SkSpan<const uint32_t> clusters); |
| |
| void makeGlyphRunList(const SkPaint& paint, const SkTextBlob* blob, SkPoint origin); |
| |
| void simplifyDrawText( |
| const SkFont& font, SkSpan<const SkGlyphID> glyphIDs, |
| SkPoint origin, SkPoint* positions, |
| SkSpan<const char> text = SkSpan<const char>{}, |
| SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{}); |
| void simplifyDrawPosTextH( |
| const SkFont& font, SkSpan<const SkGlyphID> glyphIDs, |
| const SkScalar* xpos, SkScalar constY, SkPoint* positions, |
| SkSpan<const char> text = SkSpan<const char>{}, |
| SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{}); |
| void simplifyDrawPosText( |
| const SkFont& font, SkSpan<const SkGlyphID> glyphIDs, |
| const SkPoint* pos, |
| SkSpan<const char> text = SkSpan<const char>{}, |
| SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{}); |
| void simplifyTextBlobIgnoringRSXForm( |
| const SkTextBlobRunIterator& it, |
| SkPoint* positions); |
| |
| size_t fMaxTotalRunSize{0}; |
| SkAutoTMalloc<SkPoint> fPositions; |
| |
| std::vector<SkGlyphRun> fGlyphRunListStorage; |
| SkGlyphRunList fGlyphRunList; |
| |
| // 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<SkGlyphID> fScratchGlyphIDs; |
| }; |
| |
| #endif // SkGlyphRun_DEFINED |