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