1 /* 2 * Copyright (C) 2018 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_SPLITTER_H 18 #define MINIKIN_LAYOUT_SPLITTER_H 19 20 #include "minikin/Layout.h" 21 22 #include <memory> 23 24 #include <unicode/ubidi.h> 25 26 #include "minikin/Macros.h" 27 #include "minikin/U16StringPiece.h" 28 29 #include "LayoutUtils.h" 30 31 namespace minikin { 32 33 // LayoutSplitter split the input text into recycle-able pieces. 34 // 35 // LayoutSplitter basically splits the text before and after space characters. 36 // 37 // Here is an example of how the LayoutSplitter split the text into layout pieces. 38 // Input: 39 // Text : T h i s _ i s _ a n _ e x a m p l e _ t e x t . 40 // Range : |-------------------| 41 // 42 // Output: 43 // Context Range : |---|-|---|-|-------------| 44 // Piece Range : |-|-|---|-|---------| 45 // 46 // Input: 47 // Text : T h i s _ i s _ a n _ e x a m p l e _ t e x t . 48 // Range : |-------| 49 // 50 // Output: 51 // Context Range : |-------------| 52 // Piece Range : |-------| 53 class LayoutSplitter { 54 public: LayoutSplitter(const U16StringPiece & textBuf,const Range & range,bool isRtl)55 LayoutSplitter(const U16StringPiece& textBuf, const Range& range, bool isRtl) 56 : mTextBuf(textBuf), mRange(range), mIsRtl(isRtl) {} 57 58 class iterator { 59 public: 60 bool operator==(const iterator& o) const { return mPos == o.mPos && mParent == o.mParent; } 61 62 bool operator!=(const iterator& o) const { return !(*this == o); } 63 64 std::pair<Range, Range> operator*() const { 65 return std::make_pair(mContextRange, mPieceRange); 66 } 67 68 iterator& operator++() { 69 const U16StringPiece& textBuf = mParent->mTextBuf; 70 const Range& range = mParent->mRange; 71 if (mParent->mIsRtl) { 72 mPos = mPieceRange.getStart(); 73 mContextRange.setStart(getPrevWordBreakForCache(textBuf, mPos)); 74 mContextRange.setEnd(mPos); 75 mPieceRange.setStart(std::max(mContextRange.getStart(), range.getStart())); 76 mPieceRange.setEnd(mPos); 77 } else { 78 mPos = mPieceRange.getEnd(); 79 mContextRange.setStart(mPos); 80 mContextRange.setEnd(getNextWordBreakForCache(textBuf, mPos)); 81 mPieceRange.setStart(mPos); 82 mPieceRange.setEnd(std::min(mContextRange.getEnd(), range.getEnd())); 83 } 84 return *this; 85 } 86 87 private: 88 friend class LayoutSplitter; 89 iterator(const LayoutSplitter * parent,uint32_t pos)90 iterator(const LayoutSplitter* parent, uint32_t pos) : mParent(parent), mPos(pos) { 91 const U16StringPiece& textBuf = mParent->mTextBuf; 92 const Range& range = mParent->mRange; 93 if (parent->mIsRtl) { 94 mContextRange.setStart(getPrevWordBreakForCache(textBuf, pos)); 95 mContextRange.setEnd(getNextWordBreakForCache(textBuf, pos == 0 ? 0 : pos - 1)); 96 mPieceRange.setStart(std::max(mContextRange.getStart(), range.getStart())); 97 mPieceRange.setEnd(pos); 98 } else { 99 mContextRange.setStart( 100 getPrevWordBreakForCache(textBuf, pos == range.getEnd() ? pos : pos + 1)); 101 mContextRange.setEnd(getNextWordBreakForCache(textBuf, pos)); 102 mPieceRange.setStart(pos); 103 mPieceRange.setEnd(std::min(mContextRange.getEnd(), range.getEnd())); 104 } 105 } 106 107 const LayoutSplitter* mParent; 108 uint32_t mPos; 109 Range mContextRange; 110 Range mPieceRange; 111 }; 112 begin()113 iterator begin() const { return iterator(this, mIsRtl ? mRange.getEnd() : mRange.getStart()); } end()114 iterator end() const { return iterator(this, mIsRtl ? mRange.getStart() : mRange.getEnd()); } 115 116 private: 117 U16StringPiece mTextBuf; 118 Range mRange; // The range in the original buffer. Used for range check. 119 bool mIsRtl; // The paragraph direction. 120 121 MINIKIN_PREVENT_COPY_AND_ASSIGN(LayoutSplitter); 122 }; 123 124 } // namespace minikin 125 126 #endif // MINIKIN_LAYOUT_SPLITTER_H 127