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