1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2018 The Android Open Source Project 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #ifndef SkGlyphRun_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker #define SkGlyphRun_DEFINED 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFont.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontTypes.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSpan.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTextBlob.h" 18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h" 19*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h" 20*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkZip.h" 21*c8dee2aaSAndroid Build Coastguard Worker 22*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm> 23*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef> 24*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint> 25*c8dee2aaSAndroid Build Coastguard Worker #include <iterator> 26*c8dee2aaSAndroid Build Coastguard Worker #include <optional> 27*c8dee2aaSAndroid Build Coastguard Worker #include <tuple> 28*c8dee2aaSAndroid Build Coastguard Worker #include <vector> 29*c8dee2aaSAndroid Build Coastguard Worker 30*c8dee2aaSAndroid Build Coastguard Worker class SkPaint; 31*c8dee2aaSAndroid Build Coastguard Worker struct SkRSXform; 32*c8dee2aaSAndroid Build Coastguard Worker 33*c8dee2aaSAndroid Build Coastguard Worker namespace sktext { 34*c8dee2aaSAndroid Build Coastguard Worker class GlyphRunBuilder; 35*c8dee2aaSAndroid Build Coastguard Worker 36*c8dee2aaSAndroid Build Coastguard Worker class GlyphRun { 37*c8dee2aaSAndroid Build Coastguard Worker public: 38*c8dee2aaSAndroid Build Coastguard Worker GlyphRun(const SkFont& font, 39*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const SkPoint> positions, 40*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const SkGlyphID> glyphIDs, 41*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const char> text, 42*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const uint32_t> clusters, 43*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const SkVector> scaledRotations); 44*c8dee2aaSAndroid Build Coastguard Worker 45*c8dee2aaSAndroid Build Coastguard Worker GlyphRun(const GlyphRun& glyphRun, const SkFont& font); 46*c8dee2aaSAndroid Build Coastguard Worker runSize()47*c8dee2aaSAndroid Build Coastguard Worker size_t runSize() const { return fSource.size(); } positions()48*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const SkPoint> positions() const { return fSource.get<1>(); } glyphsIDs()49*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const SkGlyphID> glyphsIDs() const { return fSource.get<0>(); } source()50*c8dee2aaSAndroid Build Coastguard Worker SkZip<const SkGlyphID, const SkPoint> source() const { return fSource; } font()51*c8dee2aaSAndroid Build Coastguard Worker const SkFont& font() const { return fFont; } clusters()52*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const uint32_t> clusters() const { return fClusters; } text()53*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const char> text() const { return fText; } scaledRotations()54*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const SkVector> scaledRotations() const { return fScaledRotations; } 55*c8dee2aaSAndroid Build Coastguard Worker 56*c8dee2aaSAndroid Build Coastguard Worker private: 57*c8dee2aaSAndroid Build Coastguard Worker // GlyphIDs and positions. 58*c8dee2aaSAndroid Build Coastguard Worker const SkZip<const SkGlyphID, const SkPoint> fSource; 59*c8dee2aaSAndroid Build Coastguard Worker // Original text from SkTextBlob if present. Will be empty of not present. 60*c8dee2aaSAndroid Build Coastguard Worker const SkSpan<const char> fText; 61*c8dee2aaSAndroid Build Coastguard Worker // Original clusters from SkTextBlob if present. Will be empty if not present. 62*c8dee2aaSAndroid Build Coastguard Worker const SkSpan<const uint32_t> fClusters; 63*c8dee2aaSAndroid Build Coastguard Worker // Possible RSXForm information 64*c8dee2aaSAndroid Build Coastguard Worker const SkSpan<const SkVector> fScaledRotations; 65*c8dee2aaSAndroid Build Coastguard Worker // Font for this run modified to have glyph encoding and left alignment. 66*c8dee2aaSAndroid Build Coastguard Worker SkFont fFont; 67*c8dee2aaSAndroid Build Coastguard Worker }; 68*c8dee2aaSAndroid Build Coastguard Worker 69*c8dee2aaSAndroid Build Coastguard Worker class GlyphRunList { 70*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const GlyphRun> fGlyphRuns; 71*c8dee2aaSAndroid Build Coastguard Worker 72*c8dee2aaSAndroid Build Coastguard Worker public: 73*c8dee2aaSAndroid Build Coastguard Worker // Blob maybe null. 74*c8dee2aaSAndroid Build Coastguard Worker GlyphRunList(const SkTextBlob* blob, 75*c8dee2aaSAndroid Build Coastguard Worker SkRect bounds, 76*c8dee2aaSAndroid Build Coastguard Worker SkPoint origin, 77*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const GlyphRun> glyphRunList, 78*c8dee2aaSAndroid Build Coastguard Worker GlyphRunBuilder* builder); 79*c8dee2aaSAndroid Build Coastguard Worker 80*c8dee2aaSAndroid Build Coastguard Worker GlyphRunList(const GlyphRun& glyphRun, 81*c8dee2aaSAndroid Build Coastguard Worker const SkRect& bounds, 82*c8dee2aaSAndroid Build Coastguard Worker SkPoint origin, 83*c8dee2aaSAndroid Build Coastguard Worker GlyphRunBuilder* builder); 84*c8dee2aaSAndroid Build Coastguard Worker uint64_t uniqueID() const; 85*c8dee2aaSAndroid Build Coastguard Worker bool anyRunsLCD() const; 86*c8dee2aaSAndroid Build Coastguard Worker void temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID, SkTextBlob::PurgeDelegate) const; 87*c8dee2aaSAndroid Build Coastguard Worker canCache()88*c8dee2aaSAndroid Build Coastguard Worker bool canCache() const { return fOriginalTextBlob != nullptr; } runCount()89*c8dee2aaSAndroid Build Coastguard Worker size_t runCount() const { return fGlyphRuns.size(); } totalGlyphCount()90*c8dee2aaSAndroid Build Coastguard Worker size_t totalGlyphCount() const { 91*c8dee2aaSAndroid Build Coastguard Worker size_t glyphCount = 0; 92*c8dee2aaSAndroid Build Coastguard Worker for (const GlyphRun& run : *this) { 93*c8dee2aaSAndroid Build Coastguard Worker glyphCount += run.runSize(); 94*c8dee2aaSAndroid Build Coastguard Worker } 95*c8dee2aaSAndroid Build Coastguard Worker return glyphCount; 96*c8dee2aaSAndroid Build Coastguard Worker } maxGlyphRunSize()97*c8dee2aaSAndroid Build Coastguard Worker size_t maxGlyphRunSize() const { 98*c8dee2aaSAndroid Build Coastguard Worker size_t size = 0; 99*c8dee2aaSAndroid Build Coastguard Worker for (const GlyphRun& run : *this) { 100*c8dee2aaSAndroid Build Coastguard Worker size = std::max(run.runSize(), size); 101*c8dee2aaSAndroid Build Coastguard Worker } 102*c8dee2aaSAndroid Build Coastguard Worker return size; 103*c8dee2aaSAndroid Build Coastguard Worker } 104*c8dee2aaSAndroid Build Coastguard Worker hasRSXForm()105*c8dee2aaSAndroid Build Coastguard Worker bool hasRSXForm() const { 106*c8dee2aaSAndroid Build Coastguard Worker for (const GlyphRun& run : *this) { 107*c8dee2aaSAndroid Build Coastguard Worker if (!run.scaledRotations().empty()) { return true; } 108*c8dee2aaSAndroid Build Coastguard Worker } 109*c8dee2aaSAndroid Build Coastguard Worker return false; 110*c8dee2aaSAndroid Build Coastguard Worker } 111*c8dee2aaSAndroid Build Coastguard Worker 112*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTextBlob> makeBlob() const; 113*c8dee2aaSAndroid Build Coastguard Worker origin()114*c8dee2aaSAndroid Build Coastguard Worker SkPoint origin() const { return fOrigin; } sourceBounds()115*c8dee2aaSAndroid Build Coastguard Worker SkRect sourceBounds() const { return fSourceBounds; } sourceBoundsWithOrigin()116*c8dee2aaSAndroid Build Coastguard Worker SkRect sourceBoundsWithOrigin() const { return fSourceBounds.makeOffset(fOrigin); } blob()117*c8dee2aaSAndroid Build Coastguard Worker const SkTextBlob* blob() const { return fOriginalTextBlob; } builder()118*c8dee2aaSAndroid Build Coastguard Worker GlyphRunBuilder* builder() const { return fBuilder; } 119*c8dee2aaSAndroid Build Coastguard Worker 120*c8dee2aaSAndroid Build Coastguard Worker auto begin() -> decltype(fGlyphRuns.begin()) { return fGlyphRuns.begin(); } 121*c8dee2aaSAndroid Build Coastguard Worker auto end() -> decltype(fGlyphRuns.end()) { return fGlyphRuns.end(); } 122*c8dee2aaSAndroid Build Coastguard Worker auto begin() const -> decltype(std::cbegin(fGlyphRuns)) { return std::cbegin(fGlyphRuns); } 123*c8dee2aaSAndroid Build Coastguard Worker auto end() const -> decltype(std::cend(fGlyphRuns)) { return std::cend(fGlyphRuns); } 124*c8dee2aaSAndroid Build Coastguard Worker auto size() const -> decltype(fGlyphRuns.size()) { return fGlyphRuns.size(); } 125*c8dee2aaSAndroid Build Coastguard Worker auto empty() const -> decltype(fGlyphRuns.empty()) { return fGlyphRuns.empty(); } 126*c8dee2aaSAndroid Build Coastguard Worker auto operator [] (size_t i) const -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i]; } 127*c8dee2aaSAndroid Build Coastguard Worker 128*c8dee2aaSAndroid Build Coastguard Worker private: 129*c8dee2aaSAndroid Build Coastguard Worker // The text blob is needed to hook up the call back that the SkTextBlob destructor calls. It 130*c8dee2aaSAndroid Build Coastguard Worker // should be used for nothing else. 131*c8dee2aaSAndroid Build Coastguard Worker const SkTextBlob* fOriginalTextBlob{nullptr}; 132*c8dee2aaSAndroid Build Coastguard Worker const SkRect fSourceBounds{SkRect::MakeEmpty()}; 133*c8dee2aaSAndroid Build Coastguard Worker const SkPoint fOrigin = {0, 0}; 134*c8dee2aaSAndroid Build Coastguard Worker GlyphRunBuilder* const fBuilder; 135*c8dee2aaSAndroid Build Coastguard Worker }; 136*c8dee2aaSAndroid Build Coastguard Worker 137*c8dee2aaSAndroid Build Coastguard Worker class GlyphRunBuilder { 138*c8dee2aaSAndroid Build Coastguard Worker public: 139*c8dee2aaSAndroid Build Coastguard Worker GlyphRunList makeGlyphRunList(const GlyphRun& run, const SkPaint& paint, SkPoint origin); 140*c8dee2aaSAndroid Build Coastguard Worker const GlyphRunList& textToGlyphRunList(const SkFont& font, 141*c8dee2aaSAndroid Build Coastguard Worker const SkPaint& paint, 142*c8dee2aaSAndroid Build Coastguard Worker const void* bytes, 143*c8dee2aaSAndroid Build Coastguard Worker size_t byteLength, 144*c8dee2aaSAndroid Build Coastguard Worker SkPoint origin, 145*c8dee2aaSAndroid Build Coastguard Worker SkTextEncoding encoding = SkTextEncoding::kUTF8); 146*c8dee2aaSAndroid Build Coastguard Worker const GlyphRunList& blobToGlyphRunList(const SkTextBlob& blob, SkPoint origin); 147*c8dee2aaSAndroid Build Coastguard Worker std::tuple<SkSpan<const SkPoint>, SkSpan<const SkVector>> 148*c8dee2aaSAndroid Build Coastguard Worker convertRSXForm(SkSpan<const SkRSXform> xforms); 149*c8dee2aaSAndroid Build Coastguard Worker empty()150*c8dee2aaSAndroid Build Coastguard Worker bool empty() const { return fGlyphRunListStorage.empty(); } 151*c8dee2aaSAndroid Build Coastguard Worker 152*c8dee2aaSAndroid Build Coastguard Worker private: 153*c8dee2aaSAndroid Build Coastguard Worker void initialize(const SkTextBlob& blob); 154*c8dee2aaSAndroid Build Coastguard Worker void prepareBuffers(int positionCount, int RSXFormCount); 155*c8dee2aaSAndroid Build Coastguard Worker 156*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const SkGlyphID> textToGlyphIDs( 157*c8dee2aaSAndroid Build Coastguard Worker const SkFont& font, const void* bytes, size_t byteLength, SkTextEncoding); 158*c8dee2aaSAndroid Build Coastguard Worker 159*c8dee2aaSAndroid Build Coastguard Worker void makeGlyphRun( 160*c8dee2aaSAndroid Build Coastguard Worker const SkFont& font, 161*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const SkGlyphID> glyphIDs, 162*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const SkPoint> positions, 163*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const char> text, 164*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const uint32_t> clusters, 165*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const SkVector> scaledRotations); 166*c8dee2aaSAndroid Build Coastguard Worker 167*c8dee2aaSAndroid Build Coastguard Worker const GlyphRunList& setGlyphRunList( 168*c8dee2aaSAndroid Build Coastguard Worker const SkTextBlob* blob, const SkRect& bounds, SkPoint origin); 169*c8dee2aaSAndroid Build Coastguard Worker 170*c8dee2aaSAndroid Build Coastguard Worker int fMaxTotalRunSize{0}; 171*c8dee2aaSAndroid Build Coastguard Worker skia_private::AutoTMalloc<SkPoint> fPositions; 172*c8dee2aaSAndroid Build Coastguard Worker int fMaxScaledRotations{0}; 173*c8dee2aaSAndroid Build Coastguard Worker skia_private::AutoTMalloc<SkVector> fScaledRotations; 174*c8dee2aaSAndroid Build Coastguard Worker 175*c8dee2aaSAndroid Build Coastguard Worker std::vector<GlyphRun> fGlyphRunListStorage; 176*c8dee2aaSAndroid Build Coastguard Worker std::optional<GlyphRunList> fGlyphRunList; // Defaults to no value; 177*c8dee2aaSAndroid Build Coastguard Worker 178*c8dee2aaSAndroid Build Coastguard Worker // Used as a temporary for preparing using utfN text. This implies that only one run of 179*c8dee2aaSAndroid Build Coastguard Worker // glyph ids will ever be needed because blobs are already glyph based. 180*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkGlyphID> fScratchGlyphIDs; 181*c8dee2aaSAndroid Build Coastguard Worker 182*c8dee2aaSAndroid Build Coastguard Worker }; 183*c8dee2aaSAndroid Build Coastguard Worker } // namespace sktext 184*c8dee2aaSAndroid Build Coastguard Worker 185*c8dee2aaSAndroid Build Coastguard Worker #endif // SkGlyphRun_DEFINED 186