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_ANDROID_LINE_BREAKER_HELPERS_H 18 #define MINIKIN_ANDROID_LINE_BREAKER_HELPERS_H 19 20 #include <algorithm> 21 22 #include "minikin/LineBreaker.h" 23 24 namespace minikin { 25 namespace android { 26 27 class AndroidLineWidth : public LineWidth { 28 public: AndroidLineWidth(float firstWidth,int32_t firstLineCount,float restWidth,const std::vector<float> & indents,const std::vector<float> & leftPaddings,const std::vector<float> & rightPaddings,int32_t indentsAndPaddingsOffset)29 AndroidLineWidth(float firstWidth, int32_t firstLineCount, float restWidth, 30 const std::vector<float>& indents, const std::vector<float>& leftPaddings, 31 const std::vector<float>& rightPaddings, int32_t indentsAndPaddingsOffset) 32 : mFirstWidth(firstWidth), 33 mFirstLineCount(firstLineCount), 34 mRestWidth(restWidth), 35 mIndents(indents), 36 mLeftPaddings(leftPaddings), 37 mRightPaddings(rightPaddings), 38 mOffset(indentsAndPaddingsOffset) {} 39 getAt(size_t lineNo)40 float getAt(size_t lineNo) const override { 41 const float width = ((ssize_t)lineNo < (ssize_t)mFirstLineCount) ? mFirstWidth : mRestWidth; 42 return std::max(0.0f, width - get(mIndents, lineNo)); 43 } 44 getMin()45 float getMin() const override { 46 // A simpler algorithm would have been simply looping until the larger of 47 // mFirstLineCount and mIndents.size()-mOffset, but that does unnecessary calculations 48 // when mFirstLineCount is large. Instead, we measure the first line, all the lines that 49 // have an indent, and the first line after firstWidth ends and restWidth starts. 50 float minWidth = std::min(getAt(0), getAt(mFirstLineCount)); 51 for (size_t lineNo = 1; lineNo + mOffset < mIndents.size(); lineNo++) { 52 minWidth = std::min(minWidth, getAt(lineNo)); 53 } 54 return minWidth; 55 } 56 getLeftPaddingAt(size_t lineNo)57 float getLeftPaddingAt(size_t lineNo) const override { return get(mLeftPaddings, lineNo); } 58 getRightPaddingAt(size_t lineNo)59 float getRightPaddingAt(size_t lineNo) const override { return get(mRightPaddings, lineNo); } 60 61 private: get(const std::vector<float> & vec,size_t lineNo)62 float get(const std::vector<float>& vec, size_t lineNo) const { 63 if (vec.empty()) { 64 return 0; 65 } 66 const size_t index = lineNo + mOffset; 67 if (index < vec.size()) { 68 return vec[index]; 69 } else { 70 return vec.back(); 71 } 72 } 73 74 const float mFirstWidth; 75 const int32_t mFirstLineCount; 76 const float mRestWidth; 77 const std::vector<float>& mIndents; 78 const std::vector<float>& mLeftPaddings; 79 const std::vector<float>& mRightPaddings; 80 const int32_t mOffset; 81 }; 82 83 class StaticLayoutNative { 84 public: StaticLayoutNative(BreakStrategy strategy,HyphenationFrequency frequency,bool isJustified,std::vector<float> && indents,std::vector<float> && leftPaddings,std::vector<float> && rightPaddings)85 StaticLayoutNative(BreakStrategy strategy, HyphenationFrequency frequency, bool isJustified, 86 std::vector<float>&& indents, std::vector<float>&& leftPaddings, 87 std::vector<float>&& rightPaddings) 88 : mStrategy(strategy), 89 mFrequency(frequency), 90 mIsJustified(isJustified), 91 mIndents(std::move(indents)), 92 mLeftPaddings(std::move(leftPaddings)), 93 mRightPaddings(std::move(rightPaddings)) {} 94 computeBreaks(const U16StringPiece & textBuf,const MeasuredText & measuredText,float firstWidth,int32_t firstWidthLineCount,float restWidth,int32_t indentsOffset,const int32_t * tabStops,int32_t tabStopSize,int32_t defaultTabStopWidth)95 LineBreakResult computeBreaks(const U16StringPiece& textBuf, const MeasuredText& measuredText, 96 // Line width arguments 97 float firstWidth, int32_t firstWidthLineCount, float restWidth, 98 int32_t indentsOffset, 99 // Tab stop arguments 100 const int32_t* tabStops, int32_t tabStopSize, 101 int32_t defaultTabStopWidth) const { 102 AndroidLineWidth lineWidth(firstWidth, firstWidthLineCount, restWidth, mIndents, 103 mLeftPaddings, mRightPaddings, indentsOffset); 104 return breakIntoLines(textBuf, mStrategy, mFrequency, mIsJustified, measuredText, lineWidth, 105 TabStops(tabStops, tabStopSize, defaultTabStopWidth)); 106 } 107 getStrategy()108 inline BreakStrategy getStrategy() const { return mStrategy; } getFrequency()109 inline HyphenationFrequency getFrequency() const { return mFrequency; } isJustified()110 inline bool isJustified() const { return mIsJustified; } 111 112 private: 113 const BreakStrategy mStrategy; 114 const HyphenationFrequency mFrequency; 115 const bool mIsJustified; 116 const std::vector<float> mIndents; 117 const std::vector<float> mLeftPaddings; 118 const std::vector<float> mRightPaddings; 119 }; 120 121 } // namespace android 122 } // namespace minikin 123 124 #endif // MINIKIN_ANDROID_LINE_BREAKER_HELPERS_H 125