Line data Source code
1 : /**
2 : Copyright (c) 2023 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 XENOLITH_FONT_XLFONTLABELBASE_H_
24 : #define XENOLITH_FONT_XLFONTLABELBASE_H_
25 :
26 : #include "XLApplicationInfo.h"
27 : #include "XLFontExtension.h"
28 : #include "SPMetastring.h"
29 : #include "SPFontFormatter.h"
30 :
31 : namespace STAPPLER_VERSIONIZED stappler::xenolith::font {
32 :
33 : class TextLayout : public RefBase<memory::StandartInterface>, public InterfaceObject<memory::StandartInterface> {
34 : public:
35 : virtual ~TextLayout();
36 : TextLayout(FontController *h, size_t = 0, size_t = 0);
37 :
38 : void reserve(size_t, size_t = 1);
39 : void clear();
40 :
41 6783 : bool empty() const { return _data.chars.empty(); }
42 :
43 189431 : TextLayoutData<Interface> *getData() { return &_data; }
44 : const TextLayoutData<Interface> *getData() const { return &_data; }
45 :
46 8200 : uint16_t getWidth() const { return _data.width; }
47 8224 : uint16_t getHeight() const { return _data.height; }
48 12 : uint16_t getMaxAdvance() const { return _data.maxAdvance; }
49 8106 : bool isOverflow() const { return _data.overflow; }
50 :
51 3465 : FontController *getController() const { return _handle; }
52 :
53 : Rc<FontFaceSet> getLayout(const FontParameters &f);
54 :
55 : RangeLineIterator begin() const;
56 : RangeLineIterator end() const;
57 :
58 : WideString str(bool filterAlign = true) const;
59 : WideString str(uint32_t, uint32_t, size_t maxWords = maxOf<size_t>(), bool ellipsis = true, bool filterAlign = true) const;
60 :
61 : // on error maxOf<uint32_t> returned
62 : Pair<uint32_t, CharSelectMode> getChar(int32_t x, int32_t y, CharSelectMode = CharSelectMode::Center) const;
63 : const LineLayoutData *getLine(uint32_t charIndex) const;
64 : uint32_t getLineForChar(uint32_t charIndex) const;
65 :
66 : Pair<uint32_t, uint32_t> selectWord(uint32_t originChar) const;
67 :
68 : geom::Rect getLineRect(uint32_t lineId, float density, const geom::Vec2 & = geom::Vec2()) const;
69 : geom::Rect getLineRect(const LineLayoutData &, float density, const geom::Vec2 & = geom::Vec2()) const;
70 :
71 : uint16_t getLineForCharId(uint32_t id) const;
72 :
73 : Vector<geom::Rect> getLabelRects(uint32_t first, uint32_t last, float density,
74 : const geom::Vec2 & = geom::Vec2(), const geom::Padding &p = geom::Padding()) const;
75 :
76 : void getLabelRects(Vector<geom::Rect> &, uint32_t first, uint32_t last, float density,
77 : const geom::Vec2 & = geom::Vec2(), const geom::Padding &p = geom::Padding()) const;
78 :
79 : protected:
80 : TextLayoutData<memory::StandartInterface> _data;
81 : Rc<FontController> _handle;
82 : Set<Rc<FontFaceSet>> _fonts;
83 : };
84 :
85 : class LabelBase {
86 : public:
87 : using FontFamily = ValueWrapper<uint32_t, class FontFamilyTag>;
88 : using Opacity = OpacityValue;
89 :
90 : struct Style {
91 : enum class Name : uint16_t {
92 : TextTransform,
93 : TextDecoration,
94 : Hyphens,
95 : VerticalAlign,
96 : Color,
97 : Opacity,
98 : FontSize,
99 : FontStyle,
100 : FontWeight,
101 : FontStretch,
102 : FontFamily,
103 : FontGrade,
104 : };
105 :
106 : union Value {
107 : TextTransform textTransform;
108 : TextDecoration textDecoration;
109 : Hyphens hyphens;
110 : VerticalAlign verticalAlign;
111 : Color3B color;
112 : uint8_t opacity;
113 : FontSize fontSize;
114 : FontStyle fontStyle;
115 : FontWeight fontWeight;
116 : FontStretch fontStretch;
117 : FontGrade fontGrade;
118 : uint32_t fontFamily;
119 :
120 : Value();
121 : };
122 :
123 : struct Param {
124 : Name name;
125 : Value value;
126 :
127 12 : Param(const TextTransform &val) : name(Name::TextTransform) { value.textTransform = val; }
128 6 : Param(const TextDecoration &val) : name(Name::TextDecoration) { value.textDecoration = val; }
129 4 : Param(const Hyphens &val) : name(Name::Hyphens) { value.hyphens = val; }
130 4 : Param(const VerticalAlign &val) : name(Name::VerticalAlign) { value.verticalAlign = val; }
131 : Param(const Color3B &val) : name(Name::Color) { value.color = val; }
132 4 : Param(const Color &val) : name(Name::Color) { value.color = val; }
133 4 : Param(const Opacity &val) : name(Name::Opacity) { value.opacity = val.get(); }
134 6 : Param(const FontSize &val) : name(Name::FontSize) { value.fontSize = val; }
135 4 : Param(const FontStyle &val) : name(Name::FontStyle) { value.fontStyle = val; }
136 6 : Param(const FontWeight &val) : name(Name::FontWeight) { value.fontWeight = val; }
137 6 : Param(const FontStretch &val) : name(Name::FontStretch) { value.fontStretch = val; }
138 4 : Param(const FontFamily &val) : name(Name::FontFamily) { value.fontFamily = val.get(); }
139 4 : Param(const FontGrade &val) : name(Name::FontGrade) { value.fontGrade = val; }
140 : };
141 :
142 4037 : Style() { }
143 9084 : Style(const Style &) = default;
144 930 : Style(Style &&) = default;
145 0 : Style & operator=(const Style &) = default;
146 248 : Style & operator=(Style &&) = default;
147 :
148 : Style(std::initializer_list<Param> il) : params(il) { }
149 :
150 56 : template <class T> Style(const T & value) { params.push_back(value); }
151 8 : template <class T> Style & set(const T &value) { set(Param(value), true); return *this; }
152 :
153 : void set(const Param &, bool force = false);
154 : void merge(const Style &);
155 : void clear();
156 :
157 : Vector<Param> params;
158 : };
159 :
160 : struct StyleSpec {
161 : size_t start = 0;
162 : size_t length = 0;
163 : Style style;
164 :
165 40 : StyleSpec(size_t s, size_t l, Style &&style)
166 40 : : start(s), length(l), style(std::move(style)) { }
167 :
168 8588 : StyleSpec(size_t s, size_t l, const Style &style)
169 8588 : : start(s), length(l), style(style) { }
170 : };
171 :
172 : struct DescriptionStyle {
173 : FontParameters font;
174 : TextParameters text;
175 :
176 : bool colorDirty = false;
177 : bool opacityDirty = false;
178 : uint32_t tag = 0;
179 :
180 : DescriptionStyle();
181 :
182 : String getConfigName(bool caps) const;
183 :
184 : DescriptionStyle merge(const Rc<font::FontController> &, const Style &style) const;
185 :
186 : bool operator == (const DescriptionStyle &) const;
187 : bool operator != (const DescriptionStyle &) const;
188 :
189 : template <typename ... Args>
190 : static DescriptionStyle construct(const StringView &family, FontSize size, Args && ... args) {
191 : DescriptionStyle p;
192 : p.font.fontFamily = family;
193 : p.font.fontSize = size;
194 : readParameters(p, std::forward<Args>(args)...);
195 : return p;
196 : }
197 :
198 : static void readParameter(DescriptionStyle &p, TextTransform value) { p.text.textTransform = value; }
199 : static void readParameter(DescriptionStyle &p, TextDecoration value) { p.text.textDecoration = value; }
200 : static void readParameter(DescriptionStyle &p, Hyphens value) { p.text.hyphens = value; }
201 : static void readParameter(DescriptionStyle &p, VerticalAlign value) { p.text.verticalAlign = value; }
202 : static void readParameter(DescriptionStyle &p, Opacity value) { p.text.opacity = value.get(); }
203 : static void readParameter(DescriptionStyle &p, const Color3B &value) { p.text.color = value; }
204 : static void readParameter(DescriptionStyle &p, FontSize value) { p.font.fontSize = value; }
205 : static void readParameter(DescriptionStyle &p, FontStyle value) { p.font.fontStyle = value; }
206 : static void readParameter(DescriptionStyle &p, FontWeight value) { p.font.fontWeight = value; }
207 : static void readParameter(DescriptionStyle &p, FontStretch value) { p.font.fontStretch = value; }
208 : static void readParameter(DescriptionStyle &p, FontGrade value) { p.font.fontGrade = value; }
209 :
210 : template <typename T, typename ... Args>
211 : static void readParameters(DescriptionStyle &p, T && t, Args && ... args) {
212 : readParameter(p, t);
213 : readParameters(p, std::forward<Args>(args)...);
214 : }
215 :
216 : template <typename T>
217 : static void readParameters(DescriptionStyle &p, T && t) {
218 : readParameter(p, t);
219 : }
220 :
221 : static void readParameters(DescriptionStyle &p) { }
222 : };
223 :
224 : class ExternalFormatter : public Ref {
225 : public:
226 : virtual ~ExternalFormatter();
227 :
228 : bool init(font::FontController *, float w = 0.0f, float density = 0.0f);
229 :
230 : void setLineHeightAbsolute(float value);
231 : void setLineHeightRelative(float value);
232 :
233 : void reserve(size_t chars, size_t ranges = 1);
234 :
235 : void addString(const DescriptionStyle &, const StringView &, bool localized = false);
236 : void addString(const DescriptionStyle &, const WideStringView &, bool localized = false);
237 :
238 : Size2 finalize();
239 :
240 : protected:
241 : bool begin = false;
242 : Rc<font::TextLayout> _spec;
243 : font::Formatter _formatter;
244 : float _density = 1.0f;
245 : };
246 :
247 : using StyleVec = Vector< StyleSpec >;
248 :
249 : public:
250 : static WideString getLocalizedString(const StringView &);
251 : static WideString getLocalizedString(const WideStringView &);
252 :
253 : static Size2 getLabelSize(font::FontController *, const DescriptionStyle &,
254 : const StringView &, float w = 0.0f, bool localized = false);
255 : static Size2 getLabelSize(font::FontController *, const DescriptionStyle &,
256 : const WideStringView &, float w = 0.0f, bool localized = false);
257 :
258 : static float getStringWidth(font::FontController *, const DescriptionStyle &,
259 : const StringView &, bool localized = false);
260 : static float getStringWidth(font::FontController *, const DescriptionStyle &,
261 : const WideStringView &, bool localized = false);
262 :
263 : virtual ~LabelBase();
264 :
265 : virtual bool isLabelDirty() const;
266 : virtual StyleVec compileStyle() const;
267 :
268 : template <char ... Chars>
269 : void setString(metastring::metastring<Chars ...> &&str) {
270 : setString(str.to_std_string());
271 : }
272 :
273 : virtual void setString(const StringView &);
274 : virtual void setString(const WideStringView &newString);
275 : virtual void setLocalizedString(size_t);
276 : virtual WideStringView getString() const;
277 : virtual StringView getString8() const;
278 :
279 : virtual void erase16(size_t start = 0, size_t len = WideString::npos);
280 : virtual void erase8(size_t start = 0, size_t len = String::npos);
281 :
282 : virtual void append(const StringView &value);
283 : virtual void append(const WideStringView &value);
284 :
285 : virtual void prepend(const StringView &value);
286 : virtual void prepend(const WideStringView &value);
287 :
288 : virtual void setTextRangeStyle(size_t start, size_t length, Style &&);
289 :
290 : virtual void appendTextWithStyle(const StringView &, Style &&);
291 : virtual void appendTextWithStyle(const WideStringView &, Style &&);
292 :
293 : virtual void prependTextWithStyle(const StringView &, Style &&);
294 : virtual void prependTextWithStyle(const WideStringView &, Style &&);
295 :
296 : virtual void clearStyles();
297 :
298 : virtual const StyleVec &getStyles() const;
299 : virtual const StyleVec &getCompiledStyles() const;
300 :
301 : virtual void setStyles(StyleVec &&);
302 : virtual void setStyles(const StyleVec &);
303 :
304 : virtual bool updateFormatSpec(TextLayout *, const StyleVec &, float density, uint8_t adjustValue);
305 :
306 3126 : virtual bool empty() const { return _string16.empty(); }
307 :
308 : void setAlignment(TextAlign alignment);
309 : TextAlign getAlignment() const;
310 :
311 : // line width for line wrapping
312 : void setWidth(float width);
313 : float getWidth() const;
314 :
315 : void setTextIndent(float value);
316 : float getTextIndent() const;
317 :
318 : void setTextTransform(const TextTransform &);
319 : TextTransform getTextTransform() const;
320 :
321 : void setTextDecoration(const TextDecoration &);
322 : TextDecoration getTextDecoration() const;
323 :
324 : void setHyphens(const Hyphens &);
325 : Hyphens getHyphens() const;
326 :
327 : void setVerticalAlign(const VerticalAlign &);
328 : VerticalAlign getVerticalAlign() const;
329 :
330 : void setFontSize(const uint16_t &);
331 : void setFontSize(const FontSize &);
332 : FontSize getFontSize() const;
333 :
334 : void setFontStyle(const FontStyle &);
335 : FontStyle getFontStyle() const;
336 :
337 : void setFontWeight(const FontWeight &);
338 : FontWeight getFontWeight() const;
339 :
340 : void setFontStretch(const FontStretch &);
341 : FontStretch getFontStretch() const;
342 :
343 : void setFontGrade(const FontGrade &);
344 : FontGrade getFontGrade() const;
345 :
346 : void setFontFamily(const StringView &);
347 : StringView getFontFamily() const;
348 :
349 : void setLineHeightAbsolute(float value);
350 : void setLineHeightRelative(float value);
351 : float getLineHeight() const;
352 : bool isLineHeightAbsolute() const;
353 :
354 : // line width for truncating label without wrapping
355 : void setMaxWidth(float);
356 : float getMaxWidth() const;
357 :
358 : void setMaxLines(size_t);
359 : size_t getMaxLines() const;
360 :
361 : void setMaxChars(size_t);
362 : size_t getMaxChars() const;
363 :
364 : void setOpticalAlignment(bool value);
365 : bool isOpticallyAligned() const;
366 :
367 : void setFillerChar(char16_t);
368 : char16_t getFillerChar() const;
369 :
370 : void setLocaleEnabled(bool);
371 : bool isLocaleEnabled() const;
372 :
373 : void setPersistentLayout(bool);
374 : bool isPersistentLayout() const;
375 :
376 : protected:
377 : virtual bool hasLocaleTags(const WideStringView &) const;
378 : virtual WideString resolveLocaleTags(const WideStringView &) const;
379 :
380 : virtual void specializeStyle(DescriptionStyle &style, float density) const;
381 :
382 : virtual void setLabelDirty();
383 :
384 : WideString _string16;
385 : String _string8;
386 :
387 : float _width = 0.0f;
388 : float _textIndent = 0.0f;
389 : float _labelDensity = 1.0f;
390 :
391 : TextAlign _alignment = TextAlign::Left;
392 :
393 : bool _localeEnabled = false;
394 : bool _labelDirty = true;
395 :
396 : bool _isLineHeightAbsolute = false;
397 : float _lineHeight = 0;
398 :
399 : String _fontFamilyStorage;
400 : DescriptionStyle _style;
401 : StyleVec _styles;
402 : StyleVec _compiledStyles;
403 :
404 : uint16_t _charsWidth;
405 : uint16_t _charsHeight;
406 :
407 : float _maxWidth = 0.0f;
408 : size_t _maxLines = 0;
409 : size_t _maxChars = 0;
410 :
411 : bool _opticalAlignment = false;
412 : bool _emplaceAllChars = false;
413 : char16_t _fillerChar = u'…';
414 :
415 : bool _persistentLayout = false;
416 : };
417 :
418 : }
419 :
420 : #endif /* XENOLITH_FONT_XLFONTLABELBASE_H_ */
|