1 /*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef MINIKIN_LAYOUT_H
18 #define MINIKIN_LAYOUT_H
19
20 #include <memory>
21 #include <unordered_map>
22 #include <vector>
23
24 #include <gtest/gtest_prod.h>
25 #include <utils/JenkinsHash.h>
26
27 #include "minikin/FontCollection.h"
28 #include "minikin/Range.h"
29 #include "minikin/U16StringPiece.h"
30
31 namespace minikin {
32
33 class Layout;
34 struct LayoutPieces;
35
36 struct LayoutGlyph {
37 // index into mFaces and mHbFonts vectors. We could imagine
38 // moving this into a run length representation, because it's
39 // more efficient for long strings, and we'll probably need
40 // something like that for paint attributes (color, underline,
41 // fake b/i, etc), as having those per-glyph is bloated.
42 int font_ix;
43
44 unsigned int glyph_id;
45 float x;
46 float y;
47 };
48
49 // Must be the same value with Paint.java
50 enum class Bidi : uint8_t {
51 LTR = 0b0000, // Must be same with Paint.BIDI_LTR
52 RTL = 0b0001, // Must be same with Paint.BIDI_RTL
53 DEFAULT_LTR = 0b0010, // Must be same with Paint.BIDI_DEFAULT_LTR
54 DEFAULT_RTL = 0b0011, // Must be same with Paint.BIDI_DEFAULT_RTL
55 FORCE_LTR = 0b0100, // Must be same with Paint.BIDI_FORCE_LTR
56 FORCE_RTL = 0b0101, // Must be same with Paint.BIDI_FORCE_RTL
57 };
58
isRtl(Bidi bidi)59 inline bool isRtl(Bidi bidi) {
60 return static_cast<uint8_t>(bidi) & 0b0001;
61 }
isOverride(Bidi bidi)62 inline bool isOverride(Bidi bidi) {
63 return static_cast<uint8_t>(bidi) & 0b0100;
64 }
65
66 // Lifecycle and threading assumptions for Layout:
67 // The object is assumed to be owned by a single thread; multiple threads
68 // may not mutate it at the same time.
69 class Layout {
70 public:
Layout()71 Layout()
72 : mGlyphs(),
73 mAdvances(),
74 mExtents(),
75 mFaces(),
76 mAdvance(0),
77 mBounds() {
78 mBounds.setEmpty();
79 }
80
81 Layout(Layout&& layout) = default;
82
83 Layout(const Layout&) = default;
84 Layout& operator=(const Layout&) = default;
85
86 void dump() const;
87
88 void doLayout(const U16StringPiece& str, const Range& range, Bidi bidiFlags,
89 const MinikinPaint& paint, StartHyphenEdit startHyphen, EndHyphenEdit endHyphen);
90
91 void doLayoutWithPrecomputedPieces(const U16StringPiece& str, const Range& range,
92 Bidi bidiFlags, const MinikinPaint& paint,
93 StartHyphenEdit startHyphen, EndHyphenEdit endHyphen,
94 const LayoutPieces& pieces);
95 static std::pair<float, MinikinRect> getBoundsWithPrecomputedPieces(const U16StringPiece& str,
96 const Range& range,
97 Bidi bidiFlags,
98 const MinikinPaint& paint,
99 const LayoutPieces& pieces);
100
101 static float measureText(const U16StringPiece& str, const Range& range, Bidi bidiFlags,
102 const MinikinPaint& paint, StartHyphenEdit startHyphen,
103 EndHyphenEdit endHyphen, float* advances, MinikinExtent* extents,
104 LayoutPieces* pieces);
105
advances()106 inline const std::vector<float>& advances() const { return mAdvances; }
107
108 // public accessors
109 size_t nGlyphs() const;
110 const MinikinFont* getFont(int i) const;
111 FontFakery getFakery(int i) const;
112 unsigned int getGlyphId(int i) const;
113 float getX(int i) const;
114 float getY(int i) const;
115
116 float getAdvance() const;
117
118 // Get advances, copying into caller-provided buffer. The size of this
119 // buffer must match the length of the string (count arg to doLayout).
120 void getAdvances(float* advances) const;
121
122 // Get extents, copying into caller-provided buffer. The size of this buffer must match the
123 // length of the string (count arg to doLayout).
124 void getExtents(MinikinExtent* extents) const;
125
126 // The i parameter is an offset within the buf relative to start, it is < count, where
127 // start and count are the parameters to doLayout
getCharAdvance(size_t i)128 float getCharAdvance(size_t i) const { return mAdvances[i]; }
129
130 void getBounds(MinikinRect* rect) const;
getBounds()131 const MinikinRect& getBounds() const { return mBounds; }
132
133 // Purge all caches, useful in low memory conditions
134 static void purgeCaches();
135
136 // Dump minikin internal statistics, cache usage, cache hit ratio, etc.
137 static void dumpMinikinStats(int fd);
138
getMemoryUsage()139 uint32_t getMemoryUsage() const {
140 return sizeof(LayoutGlyph) * nGlyphs() + sizeof(float) * mAdvances.size() +
141 sizeof(MinikinExtent) * mExtents.size() + sizeof(FakedFont) * mFaces.size() +
142 sizeof(float /* mAdvance */) + sizeof(MinikinRect /* mBounds */);
143 }
144
145 // Append another layout (for example, cached value) into this one
146 void appendLayout(const Layout& src, size_t start, float extraAdvance);
147
148 private:
149 friend class LayoutCacheKey;
150 friend class LayoutCache;
151
152 FRIEND_TEST(LayoutTest, doLayoutWithPrecomputedPiecesTest);
153
154 // Find a face in the mFaces vector. If not found, push back the entry to mFaces.
155 uint8_t findOrPushBackFace(const FakedFont& face);
156
157 // Clears layout, ready to be used again
158 void reset();
159
160 // Lay out a single bidi run
161 // When layout is not null, layout info will be stored in the object.
162 // When advances is not null, measurement results will be stored in the array.
163 static float doLayoutRunCached(const U16StringPiece& textBuf, const Range& range, bool isRtl,
164 const MinikinPaint& paint, size_t dstStart,
165 StartHyphenEdit startHyphen, EndHyphenEdit endHyphen,
166 const LayoutPieces* lpIn, Layout* layout, float* advances,
167 MinikinExtent* extents, MinikinRect* bounds,
168 LayoutPieces* lpOut);
169
170 // Lay out a single word
171 static float doLayoutWord(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
172 bool isRtl, const MinikinPaint& paint, size_t bufStart,
173 StartHyphenEdit startHyphen, EndHyphenEdit endHyphen,
174 const LayoutPieces* lpIn, Layout* layout, float* advances,
175 MinikinExtent* extents, MinikinRect* bounds, LayoutPieces* lpOut);
176
177 // Lay out a single bidi run
178 void doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t bufSize, bool isRtl,
179 const MinikinPaint& paint, StartHyphenEdit startHyphen,
180 EndHyphenEdit endHyphen);
181
182 std::vector<LayoutGlyph> mGlyphs;
183
184 // The following three vectors are defined per code unit, so their length is identical to the
185 // input text.
186 std::vector<float> mAdvances;
187 std::vector<MinikinExtent> mExtents;
188
189 std::vector<FakedFont> mFaces;
190 float mAdvance;
191 MinikinRect mBounds;
192 };
193
194 } // namespace minikin
195
196 #endif // MINIKIN_LAYOUT_H
197