1*834a2baaSAndroid Build Coastguard Worker /* 2*834a2baaSAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project 3*834a2baaSAndroid Build Coastguard Worker * 4*834a2baaSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*834a2baaSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*834a2baaSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*834a2baaSAndroid Build Coastguard Worker * 8*834a2baaSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*834a2baaSAndroid Build Coastguard Worker * 10*834a2baaSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*834a2baaSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*834a2baaSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*834a2baaSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*834a2baaSAndroid Build Coastguard Worker * limitations under the License. 15*834a2baaSAndroid Build Coastguard Worker */ 16*834a2baaSAndroid Build Coastguard Worker 17*834a2baaSAndroid Build Coastguard Worker #ifndef MINIKIN_ANDROID_LINE_BREAKER_HELPERS_H 18*834a2baaSAndroid Build Coastguard Worker #define MINIKIN_ANDROID_LINE_BREAKER_HELPERS_H 19*834a2baaSAndroid Build Coastguard Worker 20*834a2baaSAndroid Build Coastguard Worker #include <algorithm> 21*834a2baaSAndroid Build Coastguard Worker 22*834a2baaSAndroid Build Coastguard Worker #include "minikin/LineBreaker.h" 23*834a2baaSAndroid Build Coastguard Worker 24*834a2baaSAndroid Build Coastguard Worker namespace minikin { 25*834a2baaSAndroid Build Coastguard Worker namespace android { 26*834a2baaSAndroid Build Coastguard Worker 27*834a2baaSAndroid Build Coastguard Worker class AndroidLineWidth : public LineWidth { 28*834a2baaSAndroid Build Coastguard Worker public: AndroidLineWidth(float firstWidth,int32_t firstLineCount,float restWidth,const std::vector<float> & indents,int32_t indentsOffset)29*834a2baaSAndroid Build Coastguard Worker AndroidLineWidth(float firstWidth, int32_t firstLineCount, float restWidth, 30*834a2baaSAndroid Build Coastguard Worker const std::vector<float>& indents, int32_t indentsOffset) 31*834a2baaSAndroid Build Coastguard Worker : mFirstWidth(firstWidth), 32*834a2baaSAndroid Build Coastguard Worker mFirstLineCount(firstLineCount), 33*834a2baaSAndroid Build Coastguard Worker mRestWidth(restWidth), 34*834a2baaSAndroid Build Coastguard Worker mIndents(indents), 35*834a2baaSAndroid Build Coastguard Worker mOffset(indentsOffset) {} 36*834a2baaSAndroid Build Coastguard Worker getAt(size_t lineNo)37*834a2baaSAndroid Build Coastguard Worker float getAt(size_t lineNo) const override { 38*834a2baaSAndroid Build Coastguard Worker const float width = ((ssize_t)lineNo < (ssize_t)mFirstLineCount) ? mFirstWidth : mRestWidth; 39*834a2baaSAndroid Build Coastguard Worker return std::max(0.0f, width - get(mIndents, lineNo)); 40*834a2baaSAndroid Build Coastguard Worker } 41*834a2baaSAndroid Build Coastguard Worker getMin()42*834a2baaSAndroid Build Coastguard Worker float getMin() const override { 43*834a2baaSAndroid Build Coastguard Worker // A simpler algorithm would have been simply looping until the larger of 44*834a2baaSAndroid Build Coastguard Worker // mFirstLineCount and mIndents.size()-mOffset, but that does unnecessary calculations 45*834a2baaSAndroid Build Coastguard Worker // when mFirstLineCount is large. Instead, we measure the first line, all the lines that 46*834a2baaSAndroid Build Coastguard Worker // have an indent, and the first line after firstWidth ends and restWidth starts. 47*834a2baaSAndroid Build Coastguard Worker float minWidth = std::min(getAt(0), getAt(mFirstLineCount)); 48*834a2baaSAndroid Build Coastguard Worker for (size_t lineNo = 1; lineNo + mOffset < mIndents.size(); lineNo++) { 49*834a2baaSAndroid Build Coastguard Worker minWidth = std::min(minWidth, getAt(lineNo)); 50*834a2baaSAndroid Build Coastguard Worker } 51*834a2baaSAndroid Build Coastguard Worker return minWidth; 52*834a2baaSAndroid Build Coastguard Worker } 53*834a2baaSAndroid Build Coastguard Worker 54*834a2baaSAndroid Build Coastguard Worker private: get(const std::vector<float> & vec,size_t lineNo)55*834a2baaSAndroid Build Coastguard Worker float get(const std::vector<float>& vec, size_t lineNo) const { 56*834a2baaSAndroid Build Coastguard Worker if (vec.empty()) { 57*834a2baaSAndroid Build Coastguard Worker return 0; 58*834a2baaSAndroid Build Coastguard Worker } 59*834a2baaSAndroid Build Coastguard Worker const size_t index = lineNo + mOffset; 60*834a2baaSAndroid Build Coastguard Worker if (index < vec.size()) { 61*834a2baaSAndroid Build Coastguard Worker return vec[index]; 62*834a2baaSAndroid Build Coastguard Worker } else { 63*834a2baaSAndroid Build Coastguard Worker return vec.back(); 64*834a2baaSAndroid Build Coastguard Worker } 65*834a2baaSAndroid Build Coastguard Worker } 66*834a2baaSAndroid Build Coastguard Worker 67*834a2baaSAndroid Build Coastguard Worker const float mFirstWidth; 68*834a2baaSAndroid Build Coastguard Worker const int32_t mFirstLineCount; 69*834a2baaSAndroid Build Coastguard Worker const float mRestWidth; 70*834a2baaSAndroid Build Coastguard Worker const std::vector<float>& mIndents; 71*834a2baaSAndroid Build Coastguard Worker const int32_t mOffset; 72*834a2baaSAndroid Build Coastguard Worker }; 73*834a2baaSAndroid Build Coastguard Worker 74*834a2baaSAndroid Build Coastguard Worker class StaticLayoutNative { 75*834a2baaSAndroid Build Coastguard Worker public: StaticLayoutNative(BreakStrategy strategy,HyphenationFrequency frequency,bool isJustified,std::vector<float> && indents,bool useBoundsForWidth)76*834a2baaSAndroid Build Coastguard Worker StaticLayoutNative(BreakStrategy strategy, HyphenationFrequency frequency, bool isJustified, 77*834a2baaSAndroid Build Coastguard Worker std::vector<float>&& indents, bool useBoundsForWidth) 78*834a2baaSAndroid Build Coastguard Worker : mStrategy(strategy), 79*834a2baaSAndroid Build Coastguard Worker mFrequency(frequency), 80*834a2baaSAndroid Build Coastguard Worker mIsJustified(isJustified), 81*834a2baaSAndroid Build Coastguard Worker mIndents(std::move(indents)), 82*834a2baaSAndroid Build Coastguard Worker mUseBoundsForWidth(useBoundsForWidth) {} 83*834a2baaSAndroid Build Coastguard Worker StaticLayoutNative(BreakStrategy strategy,HyphenationFrequency frequency,bool isJustified,std::vector<float> && indents)84*834a2baaSAndroid Build Coastguard Worker StaticLayoutNative(BreakStrategy strategy, HyphenationFrequency frequency, bool isJustified, 85*834a2baaSAndroid Build Coastguard Worker std::vector<float>&& indents) 86*834a2baaSAndroid Build Coastguard Worker : StaticLayoutNative(strategy, frequency, isJustified, std::move(indents), 87*834a2baaSAndroid Build Coastguard Worker false /* useBoundsForWidth */) {} 88*834a2baaSAndroid Build Coastguard Worker 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*834a2baaSAndroid Build Coastguard Worker LineBreakResult computeBreaks(const U16StringPiece& textBuf, const MeasuredText& measuredText, 90*834a2baaSAndroid Build Coastguard Worker // Line width arguments 91*834a2baaSAndroid Build Coastguard Worker float firstWidth, int32_t firstWidthLineCount, float restWidth, 92*834a2baaSAndroid Build Coastguard Worker int32_t indentsOffset, 93*834a2baaSAndroid Build Coastguard Worker // Tab stop arguments 94*834a2baaSAndroid Build Coastguard Worker const float* tabStops, int32_t tabStopSize, 95*834a2baaSAndroid Build Coastguard Worker float defaultTabStopWidth) const { 96*834a2baaSAndroid Build Coastguard Worker AndroidLineWidth lineWidth(firstWidth, firstWidthLineCount, restWidth, mIndents, 97*834a2baaSAndroid Build Coastguard Worker indentsOffset); 98*834a2baaSAndroid Build Coastguard Worker return breakIntoLines(textBuf, mStrategy, mFrequency, mIsJustified, measuredText, lineWidth, 99*834a2baaSAndroid Build Coastguard Worker TabStops(tabStops, tabStopSize, defaultTabStopWidth), 100*834a2baaSAndroid Build Coastguard Worker mUseBoundsForWidth); 101*834a2baaSAndroid Build Coastguard Worker } 102*834a2baaSAndroid Build Coastguard Worker getStrategy()103*834a2baaSAndroid Build Coastguard Worker inline BreakStrategy getStrategy() const { return mStrategy; } getFrequency()104*834a2baaSAndroid Build Coastguard Worker inline HyphenationFrequency getFrequency() const { return mFrequency; } isJustified()105*834a2baaSAndroid Build Coastguard Worker inline bool isJustified() const { return mIsJustified; } 106*834a2baaSAndroid Build Coastguard Worker 107*834a2baaSAndroid Build Coastguard Worker private: 108*834a2baaSAndroid Build Coastguard Worker const BreakStrategy mStrategy; 109*834a2baaSAndroid Build Coastguard Worker const HyphenationFrequency mFrequency; 110*834a2baaSAndroid Build Coastguard Worker const bool mIsJustified; 111*834a2baaSAndroid Build Coastguard Worker const std::vector<float> mIndents; 112*834a2baaSAndroid Build Coastguard Worker const std::vector<float> mLeftPaddings; 113*834a2baaSAndroid Build Coastguard Worker const std::vector<float> mRightPaddings; 114*834a2baaSAndroid Build Coastguard Worker const bool mUseBoundsForWidth; 115*834a2baaSAndroid Build Coastguard Worker }; 116*834a2baaSAndroid Build Coastguard Worker 117*834a2baaSAndroid Build Coastguard Worker } // namespace android 118*834a2baaSAndroid Build Coastguard Worker } // namespace minikin 119*834a2baaSAndroid Build Coastguard Worker 120*834a2baaSAndroid Build Coastguard Worker #endif // MINIKIN_ANDROID_LINE_BREAKER_HELPERS_H 121