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 : #include "MaterialLabel.h"
24 : #include "MaterialSurface.h"
25 : #include "MaterialStyleContainer.h"
26 : #include "MaterialSurfaceInterior.h"
27 : #include "XLFrameInfo.h"
28 :
29 : namespace STAPPLER_VERSIONIZED stappler::xenolith::material2d {
30 :
31 : struct TypescalePersistentStyle {
32 : font::FontSize size;
33 : font::FontWeight weight;
34 :
35 10 : constexpr TypescalePersistentStyle(TypescaleRole role) {
36 10 : switch (role) {
37 0 : case TypescaleRole::DisplayLarge: size = font::FontSize(57); weight = font::FontWeight(400); break; // 57 400
38 0 : case TypescaleRole::DisplayMedium: size = font::FontSize(45); weight = font::FontWeight(400); break; // 45 400
39 0 : case TypescaleRole::DisplaySmall: size = font::FontSize(36); weight = font::FontWeight(400); break; // 36 400
40 0 : case TypescaleRole::HeadlineLarge: size = font::FontSize(32); weight = font::FontWeight(400); break; // 32 400
41 0 : case TypescaleRole::HeadlineMedium: size = font::FontSize(28); weight = font::FontWeight(400); break; // 28 400
42 0 : case TypescaleRole::HeadlineSmall: size = font::FontSize(24); weight = font::FontWeight(400); break; // 24 400
43 0 : case TypescaleRole::TitleLarge: size = font::FontSize(22); weight = font::FontWeight(400); break; // 22 400
44 0 : case TypescaleRole::TitleMedium: size = font::FontSize(16); weight = font::FontWeight(500); break; // 16 500
45 0 : case TypescaleRole::TitleSmall: size = font::FontSize(14); weight = font::FontWeight(500); break; // 14 500
46 0 : case TypescaleRole::LabelLarge: size = font::FontSize(14); weight = font::FontWeight(500); break; // 14 500
47 0 : case TypescaleRole::LabelMedium: size = font::FontSize(12); weight = font::FontWeight(500); break; // 12 500
48 0 : case TypescaleRole::LabelSmall: size = font::FontSize(11); weight = font::FontWeight(500); break; // 11 500
49 0 : case TypescaleRole::BodyLarge: size = font::FontSize(16); weight = font::FontWeight(400); break; // 16 400 0.5
50 0 : case TypescaleRole::BodyMedium: size = font::FontSize(14); weight = font::FontWeight(400); break; // 14 400 0.25
51 0 : case TypescaleRole::BodySmall: size = font::FontSize(12); weight = font::FontWeight(400); break; // 12 400 0.4
52 10 : case TypescaleRole::Unknown: break;
53 : }
54 10 : }
55 :
56 0 : bool operator==(const font::FontParameters &f) const { return f.fontSize == size && f.fontWeight == weight; }
57 : };
58 :
59 : static TypescalePersistentStyle s_persistentVariants[] = {
60 : TypescalePersistentStyle(TypescaleRole::DisplayLarge), // 57 400
61 : TypescalePersistentStyle(TypescaleRole::DisplayMedium), // 45 400
62 : TypescalePersistentStyle(TypescaleRole::DisplaySmall), // 36 400
63 : TypescalePersistentStyle(TypescaleRole::HeadlineLarge), // 32 400
64 : TypescalePersistentStyle(TypescaleRole::HeadlineMedium), // 28 400
65 : TypescalePersistentStyle(TypescaleRole::HeadlineSmall), // 24 400
66 : TypescalePersistentStyle(TypescaleRole::TitleLarge), // 22 400
67 : TypescalePersistentStyle(TypescaleRole::TitleMedium), // 16 500
68 : TypescalePersistentStyle(TypescaleRole::TitleSmall), // 14 500
69 : TypescalePersistentStyle(TypescaleRole::LabelLarge), // 14 500
70 : TypescalePersistentStyle(TypescaleRole::LabelMedium), // 12 500
71 : TypescalePersistentStyle(TypescaleRole::LabelSmall), // 11 500
72 : TypescalePersistentStyle(TypescaleRole::BodyLarge), // 16 400 0.5
73 : TypescalePersistentStyle(TypescaleRole::BodyMedium), // 14 400 0.25
74 : TypescalePersistentStyle(TypescaleRole::BodySmall), // 12 400 0.4
75 : TypescalePersistentStyle(TypescaleRole::Unknown),
76 : };
77 :
78 6 : TypescaleLabel::DescriptionStyle TypescaleLabel::getTypescaleRoleStyle(TypescaleRole role, float density) {
79 6 : DescriptionStyle style;
80 6 : style.font.fontFamily = StringView("sans");
81 6 : style.font.density = density;
82 :
83 6 : if (role != TypescaleRole::Unknown) {
84 6 : auto &variant = s_persistentVariants[toInt(role)];
85 :
86 6 : style.font.fontSize = variant.size;
87 6 : style.font.fontWeight = variant.weight;
88 : }
89 :
90 6 : return style;
91 : }
92 :
93 472 : bool TypescaleLabel::init(TypescaleRole role) {
94 472 : if (!Label::init()) {
95 0 : return false;
96 : }
97 :
98 472 : setFontFamily("sans");
99 472 : setRole(role);
100 472 : return true;
101 : }
102 :
103 50 : bool TypescaleLabel::init(TypescaleRole role, StringView str) {
104 50 : if (!Label::init(str)) {
105 0 : return false;
106 : }
107 :
108 50 : setFontFamily("sans");
109 50 : setRole(role);
110 50 : return true;
111 : }
112 :
113 0 : bool TypescaleLabel::init(TypescaleRole role, StringView str, float w, TextAlign a) {
114 0 : if (!Label::init(str, w, a)) {
115 0 : return false;
116 : }
117 :
118 0 : setFontFamily("sans");
119 0 : setRole(role);
120 0 : return true;
121 : }
122 :
123 522 : void TypescaleLabel::setRole(TypescaleRole role) {
124 522 : _role = role;
125 :
126 522 : if (role != TypescaleRole::Unknown) {
127 522 : auto &variant = s_persistentVariants[toInt(role)];
128 :
129 522 : setFontSize(variant.size);
130 522 : setFontWeight(variant.weight);
131 : }
132 522 : }
133 :
134 190 : void TypescaleLabel::setBlendColor(ColorRole rule, float value) {
135 190 : if (_blendColorRule != rule || _blendValue != value) {
136 157 : _blendColorRule = rule;
137 157 : _blendValue = value;
138 : }
139 190 : }
140 :
141 30 : void TypescaleLabel::setBlendColor(const Color4F &c, float value) {
142 30 : setBlendColor(ColorRole::Undefined, 0.0f);
143 30 : _blendColor = c;
144 30 : _blendValue = value;
145 30 : }
146 :
147 0 : void TypescaleLabel::setPreserveOpacity(bool value) {
148 0 : _preserveOpacity = value;
149 0 : }
150 :
151 0 : bool TypescaleLabel::isPreserveOpacity() const {
152 0 : return _preserveOpacity;
153 : }
154 :
155 7522 : bool TypescaleLabel::visitDraw(FrameInfo &frame, NodeFlags parentFlags) {
156 7522 : if (!_visible || empty()) {
157 1743 : return false;
158 : }
159 :
160 5779 : auto style = frame.getComponent<SurfaceInterior>(SurfaceInterior::ComponentFrameTag);
161 5779 : auto styleContainer = frame.getComponent<StyleContainer>(StyleContainer::ComponentFrameTag);
162 5779 : if (style) {
163 5779 : auto &s = style->getStyle();
164 :
165 5779 : if (styleContainer) {
166 5779 : if (auto scheme = styleContainer->getScheme(s.schemeTag)) {
167 5779 : if (_blendValue > 0.0f && _blendColorRule != ColorRole::Undefined) {
168 350 : auto c = scheme->get(_blendColorRule);
169 350 : if (c != _blendColor) {
170 10 : _blendColor = c;
171 : }
172 : }
173 :
174 5779 : setSelectionColor(scheme->get(material2d::ColorRole::Secondary));
175 : }
176 : }
177 :
178 5779 : auto color = s.colorOn.asColor4F();
179 5779 : if (_blendValue > 0.0f) {
180 350 : color = color * (1.0f - _blendValue) + _blendColor * _blendValue;
181 : }
182 :
183 5779 : if (color != getColor()) {
184 2589 : setColor(color, !_preserveOpacity);
185 : }
186 :
187 5779 : if (getRenderingLevel() != RenderingLevel::Default) {
188 5779 : if (s.colorElevation.a < 1.0f && style->getStyle().colorElevation.a > 0.0f) {
189 270 : setRenderingLevel(RenderingLevel::Transparent);
190 : } else {
191 5509 : setRenderingLevel(RenderingLevel::Surface);
192 : }
193 : }
194 :
195 5779 : if (_themeType != style->getStyle().themeType) {
196 0 : _themeType = style->getStyle().themeType;
197 0 : setLabelDirty();
198 : }
199 : }
200 :
201 5779 : return Label::visitDraw(frame, parentFlags);
202 5779 : }
203 :
204 988 : void TypescaleLabel::specializeStyle(DescriptionStyle &style, float density) const {
205 988 : if (_themeType == ThemeType::DarkTheme) {
206 0 : style.font.fontGrade = font::FontGrade(style.font.fontGrade.get() - 50);
207 : }
208 :
209 988 : Label::specializeStyle(style, density);
210 988 : if (!_persistentLayout) {
211 598 : if ((style.font.fontGrade == font::FontGrade::Normal || style.font.fontGrade == font::FontGrade::Normal)
212 598 : && style.font.fontStretch.get() % 100 == 0
213 1196 : && (style.font.fontStyle == font::FontStyle::Italic || style.font.fontStyle == font::FontStyle::Oblique)) {
214 :
215 0 : for (auto &it : s_persistentVariants) {
216 0 : if (it == style.font) {
217 0 : style.font.persistent = true;
218 : }
219 : }
220 : }
221 : }
222 988 : }
223 :
224 : }
|