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