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 59 inline bool isRtl(Bidi bidi) { 60 return static_cast<uint8_t>(bidi) & 0b0001; 61 } 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: 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 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 128 float getCharAdvance(size_t i) const { return mAdvances[i]; } 129 130 void getBounds(MinikinRect* rect) const; 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 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