Line data Source code
1 : /**
2 : Copyright (c) 2024 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #ifndef CORE_FONT_SPFONTLAYOUTDATA_H_
24 : #define CORE_FONT_SPFONTLAYOUTDATA_H_
25 :
26 : #include "SPFontStyle.h"
27 : #include "SPPadding.h"
28 :
29 : namespace STAPPLER_VERSIONIZED stappler::font {
30 :
31 : class FontFaceSet;
32 :
33 : enum class CharSelectMode {
34 : Center,
35 : Prefix,
36 : Suffix,
37 : Best,
38 : };
39 :
40 : struct CharLayoutData final {
41 : char16_t charID = 0;
42 : int16_t pos = 0;
43 : uint16_t advance = 0;
44 : uint16_t face = 0;
45 : };
46 :
47 : struct LineLayoutData final {
48 : uint32_t start = 0;
49 : uint32_t count = 0;
50 : uint16_t pos = 0;
51 : uint16_t height = 0;
52 : };
53 :
54 : struct RangeLayoutData final {
55 : bool colorDirty = false;
56 : bool opacityDirty = false;
57 : TextDecoration decoration = TextDecoration::None;
58 : VerticalAlign align = VerticalAlign::Baseline;
59 :
60 : uint32_t start = 0;
61 : uint32_t count = 0;
62 :
63 : geom::Color4B color;
64 : uint16_t height = 0;
65 :
66 : Metrics metrics;
67 : FontFaceSet *layout = nullptr;
68 : };
69 :
70 : struct RangeLineIterator {
71 : const RangeLayoutData *range;
72 : const LineLayoutData *line;
73 :
74 316273 : uint32_t start() const {
75 316273 : return std::max(range->start, line->start);
76 : }
77 209792 : uint32_t count() const {
78 209792 : return std::min(range->start + range->count, line->start + line->count) - start();
79 : }
80 75 : uint32_t end() const {
81 75 : return std::min(range->start + range->count, line->start + line->count);
82 : }
83 :
84 74785 : RangeLineIterator &operator++() {
85 74785 : const auto rangeEnd = range->start + range->count;
86 74785 : const auto lineEnd = line->start + line->count;
87 74785 : if (rangeEnd < lineEnd) {
88 24 : ++ range;
89 74761 : } else if (rangeEnd > lineEnd) {
90 52180 : ++ line;
91 : } else {
92 22581 : ++ range;
93 22581 : ++ line;
94 : }
95 :
96 74785 : return *this;
97 : }
98 :
99 97341 : bool operator==(const RangeLineIterator &other) const {
100 97341 : return other.line == line && other.range == range;
101 : }
102 97339 : bool operator!=(const RangeLineIterator &other) const {
103 97339 : return !(*this == other);
104 : }
105 : };
106 :
107 : template <typename Interface>
108 : struct TextLayoutData : public Interface::AllocBaseType {
109 : template <typename Value>
110 : using Vector = typename Interface::template VectorType<Value>;
111 :
112 : Vector< RangeLayoutData > ranges;
113 : Vector< CharLayoutData > chars;
114 : Vector< LineLayoutData > lines;
115 :
116 : uint16_t width = 0;
117 : uint16_t height = 0;
118 : uint16_t maxAdvance = 0;
119 : bool overflow = false;
120 :
121 : void reserve(size_t nchars, size_t nranges = 0);
122 :
123 15730 : RangeLineIterator begin() const {
124 15730 : return RangeLineIterator{&*ranges.begin(), &*lines.begin()};
125 : }
126 :
127 70092 : RangeLineIterator end() const {
128 70092 : return RangeLineIterator{&*ranges.end(), &*lines.end()};
129 : }
130 :
131 : void clear() {
132 : ranges.clear();
133 : chars.clear();
134 : lines.clear();
135 : width = 0;
136 : height = 0;
137 : maxAdvance = 0;
138 : overflow = false;
139 : }
140 :
141 : void str(const Callback<void(char16_t)> &, bool filterAlign = true) const;
142 : void str(const Callback<void(char16_t)> &, uint32_t, uint32_t, size_t maxWords = maxOf<size_t>(), bool ellipsis = true, bool filterAlign = true) const;
143 :
144 : float getTextIndent(float density) const {
145 : return chars.front().pos / density;
146 : }
147 :
148 : // on error maxOf<uint32_t> returned
149 : Pair<uint32_t, CharSelectMode> getChar(int32_t x, int32_t y, CharSelectMode = CharSelectMode::Center) const;
150 : const LineLayoutData *getLine(uint32_t charIndex) const;
151 : uint32_t getLineForChar(uint32_t charIndex) const;
152 :
153 : float getLinePosition(uint32_t firstCharId, uint32_t lastCharId, float density) const;
154 :
155 : Pair<uint32_t, uint32_t> selectWord(uint32_t originChar) const;
156 :
157 : geom::Rect getLineRect(uint32_t lineId, float density, const geom::Vec2 & = geom::Vec2()) const;
158 : geom::Rect getLineRect(const LineLayoutData &, float density, const geom::Vec2 & = geom::Vec2()) const;
159 :
160 : void getLabelRects(const Callback<void(geom::Rect)> &, uint32_t first, uint32_t last, float density,
161 : const geom::Vec2 & = geom::Vec2(), const geom::Padding &p = geom::Padding()) const;
162 : };
163 :
164 : }
165 :
166 : #endif /* CORE_FONT_SPFONTLAYOUTDATA_H_ */
|