xref: /third_party/skia/src/core/SkGlyphRun.h (revision cb93a386)
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
23class SkBaseDevice;
24class SkGlyph;
25class SkTextBlob;
26class SkTextBlobRunIterator;
27
28class SkGlyphRun {
29public:
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
40    size_t runSize() const { return fSource.size(); }
41    SkSpan<const SkPoint> positions() const { return fSource.get<1>(); }
42    SkSpan<const SkGlyphID> glyphsIDs() const { return fSource.get<0>(); }
43    SkZip<const SkGlyphID, const SkPoint> source() const { return fSource; }
44    const SkFont& font() const { return fFont; }
45    SkSpan<const uint32_t> clusters() const { return fClusters; }
46    SkSpan<const char> text() const { return fText; }
47    SkSpan<const SkVector> scaledRotations() const { return fScaledRotations; }
48    SkRect sourceBounds(const SkPaint& paint) const;
49
50private:
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
63class SkGlyphRunList {
64    SkSpan<const SkGlyphRun> fGlyphRuns;
65
66public:
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
83    bool canCache() const { return fOriginalTextBlob != nullptr; }
84    size_t runCount() const { return fGlyphRuns.size(); }
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
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
102    SkPoint origin() const { return fOrigin; }
103    SkRect sourceBounds() const { return fSourceBounds; }
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
114private:
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
122class SkGlyphRunBuilder {
123public:
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
134    bool empty() const { return fGlyphRunListStorage.empty(); }
135
136private:
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