xref: /aosp_15_r20/frameworks/minikin/include/minikin/AndroidLineBreakerHelper.h (revision 834a2baab5fdfc28e9a428ee87c7ea8f6a06a53d)
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