1 /* 2 * Copyright (C) 2017 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_MEASURED_TEXT_H 18 #define MINIKIN_MEASURED_TEXT_H 19 20 #include <deque> 21 #include <vector> 22 23 #include "minikin/FontCollection.h" 24 #include "minikin/Layout.h" 25 #include "minikin/LayoutPieces.h" 26 #include "minikin/Macros.h" 27 #include "minikin/MinikinFont.h" 28 #include "minikin/Range.h" 29 #include "minikin/U16StringPiece.h" 30 31 namespace minikin { 32 33 class Run { 34 public: Run(const Range & range)35 Run(const Range& range) : mRange(range) {} ~Run()36 virtual ~Run() {} 37 38 // Returns true if this run is RTL. Otherwise returns false. 39 virtual bool isRtl() const = 0; 40 41 // Returns true if this run can be broken into multiple pieces for line breaking. 42 virtual bool canBreak() const = 0; 43 44 // Returns the locale list ID for this run. 45 virtual uint32_t getLocaleListId() const = 0; 46 47 // Fills the each character's advances, extents and overhangs. 48 virtual void getMetrics(const U16StringPiece& text, std::vector<float>* advances, 49 LayoutPieces* precomputed, LayoutPieces* outPieces) const = 0; 50 51 virtual std::pair<float, MinikinRect> getBounds(const U16StringPiece& text, const Range& range, 52 const LayoutPieces& pieces) const = 0; 53 virtual MinikinExtent getExtent(const U16StringPiece& text, const Range& range, 54 const LayoutPieces& pieces) const = 0; 55 56 virtual void appendLayout(const U16StringPiece& text, const Range& range, 57 const Range& contextRange, const LayoutPieces& pieces, 58 const MinikinPaint& paint, uint32_t outOrigin, 59 StartHyphenEdit startHyphen, EndHyphenEdit endHyphen, 60 Layout* outLayout) const = 0; 61 62 // Following two methods are only called when the implementation returns true for 63 // canBreak method. 64 65 // Returns the paint pointer used for this run. 66 // Returns null if canBreak has not returned true. getPaint()67 virtual const MinikinPaint* getPaint() const { return nullptr; } 68 69 // Measures the hyphenation piece and fills each character's advances and overhangs. measureHyphenPiece(const U16StringPiece &,const Range &,StartHyphenEdit,EndHyphenEdit,LayoutPieces *)70 virtual float measureHyphenPiece(const U16StringPiece& /* text */, 71 const Range& /* hyphenPieceRange */, 72 StartHyphenEdit /* startHyphen */, 73 EndHyphenEdit /* endHyphen */, 74 LayoutPieces* /* pieces */) const { 75 return 0.0; 76 } 77 getRange()78 inline const Range& getRange() const { return mRange; } 79 80 protected: 81 const Range mRange; 82 }; 83 84 class StyleRun : public Run { 85 public: StyleRun(const Range & range,MinikinPaint && paint,bool isRtl)86 StyleRun(const Range& range, MinikinPaint&& paint, bool isRtl) 87 : Run(range), mPaint(std::move(paint)), mIsRtl(isRtl) {} 88 canBreak()89 bool canBreak() const override { return true; } getLocaleListId()90 uint32_t getLocaleListId() const override { return mPaint.localeListId; } isRtl()91 bool isRtl() const override { return mIsRtl; } 92 93 void getMetrics(const U16StringPiece& text, std::vector<float>* advances, 94 LayoutPieces* precomputed, LayoutPieces* outPieces) const override; 95 96 std::pair<float, MinikinRect> getBounds(const U16StringPiece& text, const Range& range, 97 const LayoutPieces& pieces) const override; 98 99 MinikinExtent getExtent(const U16StringPiece& text, const Range& range, 100 const LayoutPieces& pieces) const override; 101 102 void appendLayout(const U16StringPiece& text, const Range& range, const Range& contextRange, 103 const LayoutPieces& pieces, const MinikinPaint& paint, uint32_t outOrigin, 104 StartHyphenEdit startHyphen, EndHyphenEdit endHyphen, 105 Layout* outLayout) const override; 106 getPaint()107 const MinikinPaint* getPaint() const override { return &mPaint; } 108 109 float measureHyphenPiece(const U16StringPiece& text, const Range& range, 110 StartHyphenEdit startHyphen, EndHyphenEdit endHyphen, 111 LayoutPieces* pieces) const override; 112 113 private: 114 MinikinPaint mPaint; 115 const bool mIsRtl; 116 }; 117 118 class ReplacementRun : public Run { 119 public: ReplacementRun(const Range & range,float width,uint32_t localeListId)120 ReplacementRun(const Range& range, float width, uint32_t localeListId) 121 : Run(range), mWidth(width), mLocaleListId(localeListId) {} 122 isRtl()123 bool isRtl() const { return false; } canBreak()124 bool canBreak() const { return false; } getLocaleListId()125 uint32_t getLocaleListId() const { return mLocaleListId; } 126 getMetrics(const U16StringPiece &,std::vector<float> * advances,LayoutPieces *,LayoutPieces *)127 void getMetrics(const U16StringPiece& /* text */, std::vector<float>* advances, 128 LayoutPieces* /* precomputed */, LayoutPieces* /* outPieces */) const override { 129 (*advances)[mRange.getStart()] = mWidth; 130 // TODO: Get the extents information from the caller. 131 } 132 getBounds(const U16StringPiece &,const Range &,const LayoutPieces &)133 std::pair<float, MinikinRect> getBounds(const U16StringPiece& /* text */, 134 const Range& /* range */, 135 const LayoutPieces& /* pieces */) const override { 136 // Bounding Box is not used in replacement run. 137 return std::make_pair(mWidth, MinikinRect()); 138 } 139 getExtent(const U16StringPiece &,const Range &,const LayoutPieces &)140 MinikinExtent getExtent(const U16StringPiece& /* text */, const Range& /* range */, 141 const LayoutPieces& /* pieces */) const override { 142 return MinikinExtent(); 143 } 144 appendLayout(const U16StringPiece &,const Range &,const Range &,const LayoutPieces &,const MinikinPaint &,uint32_t,StartHyphenEdit,EndHyphenEdit,Layout *)145 void appendLayout(const U16StringPiece& /* text */, const Range& /* range */, 146 const Range& /* contextRange */, const LayoutPieces& /* pieces */, 147 const MinikinPaint& /* paint */, uint32_t /* outOrigin */, 148 StartHyphenEdit /* startHyphen */, EndHyphenEdit /* endHyphen */, 149 Layout* /* outLayout*/) const override {} 150 151 private: 152 const float mWidth; 153 const uint32_t mLocaleListId; 154 }; 155 156 // Represents a hyphenation break point. 157 struct HyphenBreak { 158 // The break offset. 159 uint32_t offset; 160 161 // The hyphenation type. 162 HyphenationType type; 163 164 // The width of preceding piece after break at hyphenation point. 165 float first; 166 167 // The width of following piece after break at hyphenation point. 168 float second; 169 HyphenBreakHyphenBreak170 HyphenBreak(uint32_t offset, HyphenationType type, float first, float second) 171 : offset(offset), type(type), first(first), second(second) {} 172 }; 173 174 class MeasuredText { 175 public: 176 // Character widths. 177 std::vector<float> widths; 178 179 // Hyphenation points. 180 std::vector<HyphenBreak> hyphenBreaks; 181 182 // The style information. 183 std::vector<std::unique_ptr<Run>> runs; 184 185 // The copied layout pieces for construcing final layouts. 186 // TODO: Stop assigning width/extents if layout pieces are available for reducing memory impact. 187 LayoutPieces layoutPieces; 188 getMemoryUsage()189 uint32_t getMemoryUsage() const { 190 return sizeof(float) * widths.size() + sizeof(HyphenBreak) * hyphenBreaks.size() + 191 layoutPieces.getMemoryUsage(); 192 } 193 194 Layout buildLayout(const U16StringPiece& textBuf, const Range& range, const Range& contextRange, 195 const MinikinPaint& paint, StartHyphenEdit startHyphen, 196 EndHyphenEdit endHyphen); 197 MinikinRect getBounds(const U16StringPiece& textBuf, const Range& range) const; 198 MinikinExtent getExtent(const U16StringPiece& textBuf, const Range& range) const; 199 200 MeasuredText(MeasuredText&&) = default; 201 MeasuredText& operator=(MeasuredText&&) = default; 202 203 MINIKIN_PREVENT_COPY_AND_ASSIGN(MeasuredText); 204 205 private: 206 friend class MeasuredTextBuilder; 207 208 void measure(const U16StringPiece& textBuf, bool computeHyphenation, bool computeLayout, 209 MeasuredText* hint); 210 211 // Use MeasuredTextBuilder instead. MeasuredText(const U16StringPiece & textBuf,std::vector<std::unique_ptr<Run>> && runs,bool computeHyphenation,bool computeLayout,MeasuredText * hint)212 MeasuredText(const U16StringPiece& textBuf, std::vector<std::unique_ptr<Run>>&& runs, 213 bool computeHyphenation, bool computeLayout, MeasuredText* hint) 214 : widths(textBuf.size()), runs(std::move(runs)) { 215 measure(textBuf, computeHyphenation, computeLayout, hint); 216 } 217 }; 218 219 class MeasuredTextBuilder { 220 public: MeasuredTextBuilder()221 MeasuredTextBuilder() {} 222 addStyleRun(int32_t start,int32_t end,MinikinPaint && paint,bool isRtl)223 void addStyleRun(int32_t start, int32_t end, MinikinPaint&& paint, bool isRtl) { 224 mRuns.emplace_back(std::make_unique<StyleRun>(Range(start, end), std::move(paint), isRtl)); 225 } 226 addReplacementRun(int32_t start,int32_t end,float width,uint32_t localeListId)227 void addReplacementRun(int32_t start, int32_t end, float width, uint32_t localeListId) { 228 mRuns.emplace_back( 229 std::make_unique<ReplacementRun>(Range(start, end), width, localeListId)); 230 } 231 232 template <class T, typename... Args> addCustomRun(Args &&...args)233 void addCustomRun(Args&&... args) { 234 mRuns.emplace_back(std::make_unique<T>(std::forward<Args>(args)...)); 235 } 236 build(const U16StringPiece & textBuf,bool computeHyphenation,bool computeLayout,MeasuredText * hint)237 std::unique_ptr<MeasuredText> build(const U16StringPiece& textBuf, bool computeHyphenation, 238 bool computeLayout, MeasuredText* hint) { 239 // Unable to use make_unique here since make_unique is not a friend of MeasuredText. 240 return std::unique_ptr<MeasuredText>(new MeasuredText( 241 textBuf, std::move(mRuns), computeHyphenation, computeLayout, hint)); 242 } 243 244 MINIKIN_PREVENT_COPY_ASSIGN_AND_MOVE(MeasuredTextBuilder); 245 246 private: 247 std::vector<std::unique_ptr<Run>> mRuns; 248 }; 249 250 } // namespace minikin 251 252 #endif // MINIKIN_MEASURED_TEXT_H 253