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
26 #include "minikin/FontCollection.h"
27 #include "minikin/LayoutCore.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 {
LayoutGlyphLayoutGlyph37 LayoutGlyph(FakedFont font, uint32_t glyph_id, float x, float y)
38 : font(font), glyph_id(glyph_id), x(x), y(y) {}
39 FakedFont font;
40
41 uint32_t glyph_id;
42 float x;
43 float y;
44 };
45
46 // Must be the same value with Paint.java
47 enum class Bidi : uint8_t {
48 LTR = 0b0000, // Must be same with Paint.BIDI_LTR
49 RTL = 0b0001, // Must be same with Paint.BIDI_RTL
50 DEFAULT_LTR = 0b0010, // Must be same with Paint.BIDI_DEFAULT_LTR
51 DEFAULT_RTL = 0b0011, // Must be same with Paint.BIDI_DEFAULT_RTL
52 FORCE_LTR = 0b0100, // Must be same with Paint.BIDI_FORCE_LTR
53 FORCE_RTL = 0b0101, // Must be same with Paint.BIDI_FORCE_RTL
54 };
55
isRtl(Bidi bidi)56 inline bool isRtl(Bidi bidi) {
57 return static_cast<uint8_t>(bidi) & 0b0001;
58 }
isOverride(Bidi bidi)59 inline bool isOverride(Bidi bidi) {
60 return static_cast<uint8_t>(bidi) & 0b0100;
61 }
62
63 // Lifecycle and threading assumptions for Layout:
64 // The object is assumed to be owned by a single thread; multiple threads
65 // may not mutate it at the same time.
66 class Layout {
67 public:
Layout(const U16StringPiece & str,const Range & range,Bidi bidiFlags,const MinikinPaint & paint,StartHyphenEdit startHyphen,EndHyphenEdit endHyphen)68 Layout(const U16StringPiece& str, const Range& range, Bidi bidiFlags, const MinikinPaint& paint,
69 StartHyphenEdit startHyphen, EndHyphenEdit endHyphen)
70 : mAdvance(0) {
71 doLayout(str, range, bidiFlags, paint, startHyphen, endHyphen);
72 }
73
Layout(uint32_t count)74 Layout(uint32_t count) : mAdvance(0) {
75 mAdvances.resize(count, 0);
76 mGlyphs.reserve(count);
77 }
78
79 static float measureText(const U16StringPiece& str, const Range& range, Bidi bidiFlags,
80 const MinikinPaint& paint, StartHyphenEdit startHyphen,
81 EndHyphenEdit endHyphen, float* advances);
82
advances()83 const std::vector<float>& advances() const { return mAdvances; }
84
85 // public accessors
nGlyphs()86 size_t nGlyphs() const { return mGlyphs.size(); }
getFont(int i)87 const MinikinFont* getFont(int i) const { return mGlyphs[i].font.font->typeface().get(); }
getFakery(int i)88 FontFakery getFakery(int i) const { return mGlyphs[i].font.fakery; }
getGlyphId(int i)89 unsigned int getGlyphId(int i) const { return mGlyphs[i].glyph_id; }
getX(int i)90 float getX(int i) const { return mGlyphs[i].x; }
getY(int i)91 float getY(int i) const { return mGlyphs[i].y; }
getAdvance()92 float getAdvance() const { return mAdvance; }
getCharAdvance(size_t i)93 float getCharAdvance(size_t i) const { return mAdvances[i]; }
getAdvances()94 const std::vector<float>& getAdvances() const { return mAdvances; }
getBounds(MinikinRect * rect)95 void getBounds(MinikinRect* rect) const { rect->set(mBounds); }
getBounds()96 const MinikinRect& getBounds() const { return mBounds; }
97
98 // Purge all caches, useful in low memory conditions
99 static void purgeCaches();
100
101 // Dump minikin internal statistics, cache usage, cache hit ratio, etc.
102 static void dumpMinikinStats(int fd);
103
104 // Append another layout (for example, cached value) into this one
105 void appendLayout(const LayoutPiece& src, size_t start, float extraAdvance);
106
107 private:
108 FRIEND_TEST(LayoutTest, doLayoutWithPrecomputedPiecesTest);
109
110 void doLayout(const U16StringPiece& str, const Range& range, Bidi bidiFlags,
111 const MinikinPaint& paint, StartHyphenEdit startHyphen, EndHyphenEdit endHyphen);
112
113 // Lay out a single bidi run
114 // When layout is not null, layout info will be stored in the object.
115 // When advances is not null, measurement results will be stored in the array.
116 static float doLayoutRunCached(const U16StringPiece& textBuf, const Range& range, bool isRtl,
117 const MinikinPaint& paint, size_t dstStart,
118 StartHyphenEdit startHyphen, EndHyphenEdit endHyphen,
119 Layout* layout, float* advances);
120
121 // Lay out a single word
122 static float doLayoutWord(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
123 bool isRtl, const MinikinPaint& paint, size_t bufStart,
124 StartHyphenEdit startHyphen, EndHyphenEdit endHyphen, Layout* layout,
125 float* advances);
126
127 // Lay out a single bidi run
128 void doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t bufSize, bool isRtl,
129 const MinikinPaint& paint, StartHyphenEdit startHyphen,
130 EndHyphenEdit endHyphen);
131
132 std::vector<LayoutGlyph> mGlyphs;
133
134 // This vector defined per code unit, so their length is identical to the input text.
135 std::vector<float> mAdvances;
136
137 float mAdvance;
138 MinikinRect mBounds;
139 };
140
141 } // namespace minikin
142
143 #endif // MINIKIN_LAYOUT_H
144