1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkGlyphRun_DEFINED
9 #define SkGlyphRun_DEFINED
10 
11 #include <functional>
12 #include <vector>
13 
14 #include "include/core/SkFont.h"
15 #include "include/core/SkPaint.h"
16 #include "include/core/SkPoint.h"
17 #include "include/core/SkTypes.h"
18 #include "include/private/SkTemplates.h"
19 #include "src/core/SkSpan.h"
20 #include "src/core/SkZip.h"
21 
22 class SkBaseDevice;
23 class SkGlyph;
24 class SkTextBlob;
25 class SkTextBlobRunIterator;
26 
27 class SkGlyphRun {
28 public:
29     SkGlyphRun() = default;
30     SkGlyphRun(const SkFont& font,
31                SkSpan<const SkPoint> positions,
32                SkSpan<const SkGlyphID> glyphIDs,
33                SkSpan<const char> text,
34                SkSpan<const uint32_t> clusters);
35     SkGlyphRun(const SkGlyphRun& glyphRun, const SkFont& font);
36 
runSize()37     size_t runSize() const { return fSource.size(); }
positions()38     SkSpan<const SkPoint> positions() const { return fSource.get<1>(); }
glyphsIDs()39     SkSpan<const SkGlyphID> glyphsIDs() const { return fSource.get<0>(); }
source()40     SkZip<const SkGlyphID, const SkPoint> source() const { return fSource; }
font()41     const SkFont& font() const { return fFont; }
clusters()42     SkSpan<const uint32_t> clusters() const { return fClusters; }
text()43     SkSpan<const char> text() const { return fText; }
44 
45 private:
46     // GlyphIDs and positions.
47     const SkZip<const SkGlyphID, const SkPoint> fSource;
48     // Original text from SkTextBlob if present. Will be empty of not present.
49     const SkSpan<const char> fText;
50     // Original clusters from SkTextBlob if present. Will be empty if not present.
51     const SkSpan<const uint32_t>   fClusters;
52     // Paint for this run modified to have glyph encoding and left alignment.
53     SkFont fFont;
54 };
55 
56 class SkGlyphRunList {
57     SkSpan<const SkGlyphRun> fGlyphRuns;
58 
59 public:
60     SkGlyphRunList();
61     // Blob maybe null.
62     SkGlyphRunList(
63             const SkPaint& paint,
64             const SkTextBlob* blob,
65             SkPoint origin,
66             SkSpan<const SkGlyphRun> glyphRunList);
67 
68     SkGlyphRunList(const SkGlyphRun& glyphRun, const SkPaint& paint);
69 
70     uint64_t uniqueID() const;
71     bool anyRunsLCD() const;
72     bool anyRunsSubpixelPositioned() const;
73     void temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const;
74 
canCache()75     bool canCache() const { return fOriginalTextBlob != nullptr; }
runCount()76     size_t runCount() const { return fGlyphRuns.size(); }
totalGlyphCount()77     size_t totalGlyphCount() const {
78         size_t glyphCount = 0;
79         for(const auto& run : fGlyphRuns) {
80             glyphCount += run.runSize();
81         }
82         return glyphCount;
83     }
84     bool allFontsFinite() const;
85 
origin()86     SkPoint origin() const { return fOrigin; }
paint()87     const SkPaint& paint() const { return *fOriginalPaint; }
blob()88     const SkTextBlob* blob() const { return fOriginalTextBlob; }
89 
90     auto begin() -> decltype(fGlyphRuns.begin())               { return fGlyphRuns.begin();  }
91     auto end()   -> decltype(fGlyphRuns.end())                 { return fGlyphRuns.end();    }
92     auto begin() const -> decltype(fGlyphRuns.cbegin())        { return fGlyphRuns.cbegin(); }
93     auto end()   const -> decltype(fGlyphRuns.cend())          { return fGlyphRuns.cend();   }
94     auto size()  const -> decltype(fGlyphRuns.size())          { return fGlyphRuns.size();   }
95     auto empty() const -> decltype(fGlyphRuns.empty())         { return fGlyphRuns.empty();  }
96     auto operator [] (size_t i) const -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i];     }
97 
98 private:
99     const SkPaint* fOriginalPaint{nullptr};  // This should be deleted soon.
100     // The text blob is needed to hookup the call back that the SkTextBlob destructor calls. It
101     // should be used for nothing else
102     const SkTextBlob*  fOriginalTextBlob{nullptr};
103     SkPoint fOrigin = {0, 0};
104 };
105 
106 class SkGlyphIDSet {
107 public:
108     SkSpan<const SkGlyphID> uniquifyGlyphIDs(
109             uint32_t universeSize, SkSpan<const SkGlyphID> glyphIDs,
110             SkGlyphID* uniqueGlyphIDs, uint16_t* denseindices);
111 private:
112     size_t fUniverseToUniqueSize{0};
113     SkAutoTMalloc<uint16_t> fUniverseToUnique;
114 };
115 
116 class SkGlyphRunBuilder {
117 public:
118     void drawTextUTF8(
119         const SkPaint& paint, const SkFont&, const void* bytes, size_t byteLength, SkPoint origin);
120     void drawGlyphsWithPositions(
121             const SkPaint&, const SkFont&, SkSpan<const SkGlyphID> glyphIDs, const SkPoint* pos);
122     void drawTextBlob(const SkPaint& paint, const SkTextBlob& blob, SkPoint origin, SkBaseDevice*);
123 
124     void textBlobToGlyphRunListIgnoringRSXForm(
125             const SkPaint& paint, const SkTextBlob& blob, SkPoint origin);
126 
127     const SkGlyphRunList& useGlyphRunList();
128 
empty()129     bool empty() const { return fGlyphRunListStorage.empty(); }
130 
131 private:
132     void initialize(size_t totalRunSize);
133     SkSpan<const SkGlyphID> textToGlyphIDs(
134             const SkFont& font, const void* bytes, size_t byteLength, SkTextEncoding);
135 
136     void makeGlyphRun(
137             const SkFont& font,
138             SkSpan<const SkGlyphID> glyphIDs,
139             SkSpan<const SkPoint> positions,
140             SkSpan<const char> text,
141             SkSpan<const uint32_t> clusters);
142 
143     void makeGlyphRunList(const SkPaint& paint, const SkTextBlob* blob, SkPoint origin);
144 
145     void simplifyDrawText(
146             const SkFont& font, SkSpan<const SkGlyphID> glyphIDs,
147             SkPoint origin, SkPoint* positions,
148             SkSpan<const char> text = SkSpan<const char>{},
149             SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{});
150     void simplifyDrawPosTextH(
151             const SkFont& font, SkSpan<const SkGlyphID> glyphIDs,
152             const SkScalar* xpos, SkScalar constY, SkPoint* positions,
153             SkSpan<const char> text = SkSpan<const char>{},
154             SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{});
155     void simplifyDrawPosText(
156             const SkFont& font, SkSpan<const SkGlyphID> glyphIDs,
157             const SkPoint* pos,
158             SkSpan<const char> text = SkSpan<const char>{},
159             SkSpan<const uint32_t> clusters = SkSpan<const uint32_t>{});
160     void simplifyTextBlobIgnoringRSXForm(
161             const SkTextBlobRunIterator& it,
162             SkPoint* positions);
163 
164     size_t fMaxTotalRunSize{0};
165     SkAutoTMalloc<SkPoint> fPositions;
166 
167     std::vector<SkGlyphRun> fGlyphRunListStorage;
168     SkGlyphRunList fGlyphRunList;
169 
170     // Used as a temporary for preparing using utfN text. This implies that only one run of
171     // glyph ids will ever be needed because blobs are already glyph based.
172     std::vector<SkGlyphID> fScratchGlyphIDs;
173 };
174 
175 #endif  // SkGlyphRun_DEFINED
176