| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef MINIKIN_LAYOUT_SPLITTER_H |
| #define MINIKIN_LAYOUT_SPLITTER_H |
| |
| #define LOG_TAG "Minikin" |
| |
| #include "minikin/Layout.h" |
| |
| #include <memory> |
| |
| #include <unicode/ubidi.h> |
| |
| #include "minikin/Macros.h" |
| #include "minikin/U16StringPiece.h" |
| |
| #include "LayoutUtils.h" |
| |
| namespace minikin { |
| |
| // LayoutSplitter split the input text into recycle-able pieces. |
| // |
| // LayoutSplitter basically splits the text before and after space characters. |
| // |
| // Here is an example of how the LayoutSplitter split the text into layout pieces. |
| // Input: |
| // Text : T h i s _ i s _ a n _ e x a m p l e _ t e x t . |
| // Range : |-------------------| |
| // |
| // Output: |
| // Context Range : |---|-|---|-|-------------| |
| // Piece Range : |-|-|---|-|---------| |
| // |
| // Input: |
| // Text : T h i s _ i s _ a n _ e x a m p l e _ t e x t . |
| // Range : |-------| |
| // |
| // Output: |
| // Context Range : |-------------| |
| // Piece Range : |-------| |
| class LayoutSplitter { |
| public: |
| LayoutSplitter(const U16StringPiece& textBuf, const Range& range, bool isRtl) |
| : mTextBuf(textBuf), mRange(range), mIsRtl(isRtl) {} |
| |
| class iterator { |
| public: |
| bool operator==(const iterator& o) const { return mPos == o.mPos && mParent == o.mParent; } |
| |
| bool operator!=(const iterator& o) const { return !(*this == o); } |
| |
| std::pair<Range, Range> operator*() const { |
| return std::make_pair(mContextRange, mPieceRange); |
| } |
| |
| iterator& operator++() { |
| const U16StringPiece& textBuf = mParent->mTextBuf; |
| const Range& range = mParent->mRange; |
| if (mParent->mIsRtl) { |
| mPos = mPieceRange.getStart(); |
| mContextRange.setStart(getPrevWordBreakForCache(textBuf, mPos)); |
| mContextRange.setEnd(mPos); |
| mPieceRange.setStart(std::max(mContextRange.getStart(), range.getStart())); |
| mPieceRange.setEnd(mPos); |
| } else { |
| mPos = mPieceRange.getEnd(); |
| mContextRange.setStart(mPos); |
| mContextRange.setEnd(getNextWordBreakForCache(textBuf, mPos)); |
| mPieceRange.setStart(mPos); |
| mPieceRange.setEnd(std::min(mContextRange.getEnd(), range.getEnd())); |
| } |
| return *this; |
| } |
| |
| private: |
| friend class LayoutSplitter; |
| |
| iterator(const LayoutSplitter* parent, uint32_t pos) : mParent(parent), mPos(pos) { |
| const U16StringPiece& textBuf = mParent->mTextBuf; |
| const Range& range = mParent->mRange; |
| if (parent->mIsRtl) { |
| mContextRange.setStart(getPrevWordBreakForCache(textBuf, pos)); |
| mContextRange.setEnd(getNextWordBreakForCache(textBuf, pos == 0 ? 0 : pos - 1)); |
| mPieceRange.setStart(std::max(mContextRange.getStart(), range.getStart())); |
| mPieceRange.setEnd(pos); |
| } else { |
| mContextRange.setStart( |
| getPrevWordBreakForCache(textBuf, pos == range.getEnd() ? pos : pos + 1)); |
| mContextRange.setEnd(getNextWordBreakForCache(textBuf, pos)); |
| mPieceRange.setStart(pos); |
| mPieceRange.setEnd(std::min(mContextRange.getEnd(), range.getEnd())); |
| } |
| } |
| |
| const LayoutSplitter* mParent; |
| uint32_t mPos; |
| Range mContextRange; |
| Range mPieceRange; |
| }; |
| |
| iterator begin() const { return iterator(this, mIsRtl ? mRange.getEnd() : mRange.getStart()); } |
| iterator end() const { return iterator(this, mIsRtl ? mRange.getStart() : mRange.getEnd()); } |
| |
| private: |
| U16StringPiece mTextBuf; |
| Range mRange; // The range in the original buffer. Used for range check. |
| bool mIsRtl; // The paragraph direction. |
| |
| MINIKIN_PREVENT_COPY_AND_ASSIGN(LayoutSplitter); |
| }; |
| |
| } // namespace minikin |
| |
| #endif // MINIKIN_LAYOUT_SPLITTER_H |