• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/SkRSXform.h"
18 #include "include/core/SkSpan.h"
19 #include "include/core/SkTypes.h"
20 #include "include/private/SkTemplates.h"
21 #include "src/core/SkZip.h"
22 
23 class SkBaseDevice;
24 class SkGlyph;
25 class SkTextBlob;
26 class SkTextBlobRunIterator;
27 
28 class SkGlyphRun {
29 public:
30     SkGlyphRun() = default;
31     SkGlyphRun(const SkFont& font,
32                SkSpan<const SkPoint> positions,
33                SkSpan<const SkGlyphID> glyphIDs,
34                SkSpan<const char> text,
35                SkSpan<const uint32_t> clusters,
36                SkSpan<const SkVector> scaledRotations);
37 
38     SkGlyphRun(const SkGlyphRun& glyphRun, const SkFont& font);
39 
runSize()40     size_t runSize() const { return fSource.size(); }
positions()41     SkSpan<const SkPoint> positions() const { return fSource.get<1>(); }
glyphsIDs()42     SkSpan<const SkGlyphID> glyphsIDs() const { return fSource.get<0>(); }
source()43     SkZip<const SkGlyphID, const SkPoint> source() const { return fSource; }
font()44     const SkFont& font() const { return fFont; }
clusters()45     SkSpan<const uint32_t> clusters() const { return fClusters; }
text()46     SkSpan<const char> text() const { return fText; }
scaledRotations()47     SkSpan<const SkVector> scaledRotations() const { return fScaledRotations; }
48     SkRect sourceBounds(const SkPaint& paint) const;
49 
50 private:
51     // GlyphIDs and positions.
52     const SkZip<const SkGlyphID, const SkPoint> fSource;
53     // Original text from SkTextBlob if present. Will be empty of not present.
54     const SkSpan<const char> fText;
55     // Original clusters from SkTextBlob if present. Will be empty if not present.
56     const SkSpan<const uint32_t>   fClusters;
57     // Possible RSXForm information
58     const SkSpan<const SkVector> fScaledRotations;
59     // Font for this run modified to have glyph encoding and left alignment.
60     SkFont fFont;
61 };
62 
63 class SkGlyphRunList {
64     SkSpan<const SkGlyphRun> fGlyphRuns;
65 
66 public:
67     SkGlyphRunList();
68     // Blob maybe null.
69     SkGlyphRunList(
70             const SkTextBlob* blob,
71             SkRect bounds,
72             SkPoint origin,
73             SkSpan<const SkGlyphRun> glyphRunList);
74 
75     SkGlyphRunList(const SkGlyphRun& glyphRun, const SkRect& bounds, SkPoint origin);
76 
77 
78 
79     uint64_t uniqueID() const;
80     bool anyRunsLCD() const;
81     void temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const;
82 
canCache()83     bool canCache() const { return fOriginalTextBlob != nullptr; }
runCount()84     size_t runCount() const { return fGlyphRuns.size(); }
totalGlyphCount()85     size_t totalGlyphCount() const {
86         size_t glyphCount = 0;
87         for (const SkGlyphRun& run : *this) {
88             glyphCount += run.runSize();
89         }
90         return glyphCount;
91     }
92 
hasRSXForm()93     bool hasRSXForm() const {
94         for (const SkGlyphRun& run : *this) {
95             if (!run.scaledRotations().empty()) { return true; }
96         }
97         return false;
98     }
99 
100     sk_sp<SkTextBlob> makeBlob() const;
101 
origin()102     SkPoint origin() const { return fOrigin; }
sourceBounds()103     SkRect sourceBounds() const { return fSourceBounds; }
blob()104     const SkTextBlob* blob() const { return fOriginalTextBlob; }
105 
106     auto begin() -> decltype(fGlyphRuns.begin())               { return fGlyphRuns.begin();      }
107     auto end()   -> decltype(fGlyphRuns.end())                 { return fGlyphRuns.end();        }
108     auto begin() const -> decltype(std::cbegin(fGlyphRuns))    { return std::cbegin(fGlyphRuns); }
109     auto end()   const -> decltype(std::cend(fGlyphRuns))      { return std::cend(fGlyphRuns);   }
110     auto size()  const -> decltype(fGlyphRuns.size())          { return fGlyphRuns.size();       }
111     auto empty() const -> decltype(fGlyphRuns.empty())         { return fGlyphRuns.empty();      }
112     auto operator [] (size_t i) const -> decltype(fGlyphRuns[i]) { return fGlyphRuns[i];         }
113 
114 private:
115     // The text blob is needed to hookup the call back that the SkTextBlob destructor calls. It
116     // should be used for nothing else
117     const SkTextBlob* fOriginalTextBlob{nullptr};
118     const SkRect fSourceBounds{SkRect::MakeEmpty()};
119     const SkPoint fOrigin = {0, 0};
120 };
121 
122 class SkGlyphRunBuilder {
123 public:
124     const SkGlyphRunList& textToGlyphRunList(const SkFont& font,
125                                              const SkPaint& paint,
126                                              const void* bytes,
127                                              size_t byteLength,
128                                              SkPoint origin,
129                                              SkTextEncoding encoding = SkTextEncoding::kUTF8);
130     const SkGlyphRunList& blobToGlyphRunList(const SkTextBlob& blob, SkPoint origin);
131     std::tuple<SkSpan<const SkPoint>, SkSpan<const SkVector>>
132             convertRSXForm(SkSpan<const SkRSXform> xforms);
133 
empty()134     bool empty() const { return fGlyphRunListStorage.empty(); }
135 
136 private:
137     void initialize(const SkTextBlob& blob);
138     void prepareBuffers(int positionCount, int RSXFormCount);
139 
140     SkSpan<const SkGlyphID> textToGlyphIDs(
141             const SkFont& font, const void* bytes, size_t byteLength, SkTextEncoding);
142 
143     void makeGlyphRun(
144             const SkFont& font,
145             SkSpan<const SkGlyphID> glyphIDs,
146             SkSpan<const SkPoint> positions,
147             SkSpan<const char> text,
148             SkSpan<const uint32_t> clusters,
149             SkSpan<const SkVector> scaledRotations);
150 
151     const SkGlyphRunList& makeGlyphRunList(
152             const SkTextBlob* blob, const SkRect& bounds, SkPoint origin);
153 
154     int fMaxTotalRunSize{0};
155     SkAutoTMalloc<SkPoint> fPositions;
156     int fMaxScaledRotations{0};
157     SkAutoTMalloc<SkVector> fScaledRotations;
158 
159     std::vector<SkGlyphRun> fGlyphRunListStorage;
160     SkGlyphRunList fGlyphRunList;
161 
162     // Used as a temporary for preparing using utfN text. This implies that only one run of
163     // glyph ids will ever be needed because blobs are already glyph based.
164     std::vector<SkGlyphID> fScratchGlyphIDs;
165 };
166 
167 #endif  // SkGlyphRun_DEFINED
168