1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "variant_span.h"
17
18 #include "texgine_exception.h"
19 #include "texgine/utils/exlog.h"
20 #include "text_converter.h"
21
22 namespace OHOS {
23 namespace Rosen {
24 namespace TextEngine {
VariantSpan(const std::shared_ptr<TextSpan> & ts)25 VariantSpan::VariantSpan(const std::shared_ptr<TextSpan> &ts) noexcept(true): ts_(ts) {}
26
VariantSpan(const std::shared_ptr<AnySpan> & as)27 VariantSpan::VariantSpan(const std::shared_ptr<AnySpan> &as) noexcept(true): as_(as) {}
28
VariantSpan(std::shared_ptr<TextSpan> && ts)29 VariantSpan::VariantSpan(std::shared_ptr<TextSpan> &&ts) noexcept(true): ts_(std::move(ts)) {}
30
VariantSpan(std::shared_ptr<AnySpan> && as)31 VariantSpan::VariantSpan(std::shared_ptr<AnySpan> &&as) noexcept(true): as_(std::move(as)) {}
32
VariantSpan(std::nullptr_t)33 VariantSpan::VariantSpan(std::nullptr_t) noexcept(true) {}
34
operator bool() const35 VariantSpan::operator bool() const noexcept(false)
36 {
37 CheckPointer(true);
38 return *this != nullptr;
39 }
40
operator ==(std::nullptr_t) const41 bool VariantSpan::operator ==(std::nullptr_t) const noexcept(false)
42 {
43 CheckPointer(true);
44 return (ts_ == nullptr) && (as_ == nullptr);
45 }
46
operator ==(const VariantSpan & rhs) const47 bool VariantSpan::operator ==(const VariantSpan &rhs) const noexcept(false)
48 {
49 CheckPointer(true);
50 return (ts_ == rhs.ts_) && (as_ == rhs.as_);
51 }
52
operator !=(std::nullptr_t) const53 bool VariantSpan::operator !=(std::nullptr_t) const noexcept(false)
54 {
55 CheckPointer(true);
56 return !(*this == nullptr);
57 }
58
operator !=(const VariantSpan & rhs) const59 bool VariantSpan::operator !=(const VariantSpan &rhs) const noexcept(false)
60 {
61 CheckPointer(true);
62 return !(*this == rhs);
63 }
64
GetWidth() const65 double VariantSpan::GetWidth() const
66 {
67 CheckPointer();
68 if (as_) {
69 return as_->GetWidth();
70 }
71
72 if (ts_) {
73 return ts_->GetWidth();
74 }
75
76 return 0.0;
77 }
78
GetHeight() const79 double VariantSpan::GetHeight() const noexcept(false)
80 {
81 CheckPointer();
82 if (as_) {
83 return as_->GetHeight();
84 }
85
86 if (ts_) {
87 return ts_->GetHeight();
88 }
89
90 return 0.0;
91 }
92
GetNumberOfCharGroup() const93 size_t VariantSpan::GetNumberOfCharGroup() const noexcept(false)
94 {
95 CheckPointer();
96 if (ts_) {
97 return ts_->cgs_.GetNumberOfCharGroup();
98 }
99
100 if (as_) {
101 return 1;
102 }
103
104 return 0;
105 }
106
GetGlyphWidths() const107 std::vector<double> VariantSpan::GetGlyphWidths() const noexcept(false)
108 {
109 CheckPointer();
110 std::vector<double> widths;
111 if (ts_) {
112 for (const auto &cg : ts_->cgs_) {
113 if (cg.IsEmoji()) {
114 widths.push_back(cg.GetWidth());
115 continue;
116 }
117 for (int i = 0; i < static_cast<int>(cg.chars.size()); i++) {
118 widths.push_back(cg.GetWidth() / static_cast<int>(cg.chars.size()));
119 }
120 }
121 }
122
123 if (as_) {
124 widths.push_back(GetWidth());
125 }
126
127 return widths;
128 }
129
GetVisibleWidth() const130 double VariantSpan::GetVisibleWidth() const noexcept(false)
131 {
132 CheckPointer();
133 if (ts_) {
134 double width = 0;
135 double continuousInvisibleWidth = 0;
136 for (const auto &cg : ts_->cgs_) {
137 width += (cg.visibleWidth + cg.invisibleWidth);
138 if (cg.visibleWidth > 0) {
139 continuousInvisibleWidth = 0;
140 }
141 continuousInvisibleWidth += cg.invisibleWidth;
142 }
143 return width - continuousInvisibleWidth;
144 }
145
146 if (as_) {
147 return as_->GetWidth();
148 }
149
150 return 0.0;
151 }
152
GetNumberOfChar() const153 size_t VariantSpan::GetNumberOfChar() const noexcept(false)
154 {
155 CheckPointer();
156 size_t count = 0;
157 if (ts_) {
158 for (const auto &cg : ts_->cgs_) {
159 if (cg.IsEmoji()) {
160 count++;
161 continue;
162 }
163 count += cg.chars.size();
164 }
165 }
166
167 if (as_) {
168 // Set the number of AnySpan`s char to 1
169 return 1;
170 }
171
172 return count;
173 }
174
Dump(const DumpType & dtype) const175 void VariantSpan::Dump(const DumpType &dtype) const noexcept(false)
176 {
177 CheckPointer(true);
178 if (as_) {
179 switch (dtype) {
180 case DumpType::NORMAL:
181 LOGEX_FUNC_LINE_DEBUG() << "VariantSpan";
182 break;
183 case DumpType::DONT_RETURN:
184 LOGEX_FUNC_LINE_DEBUG(Logger::SetToNoReturn) << "VariantSpan ";
185 break;
186 }
187 return;
188 }
189
190 if (ts_ == nullptr) {
191 return;
192 }
193
194 switch (dtype) {
195 case DumpType::NORMAL:
196 LOGEX_FUNC_LINE_DEBUG() << "(" << offsetX_ << ", " << offsetY_ << ") " <<
197 (ts_->rtl_ ? "<-" : "->") << " " << ts_->cgs_.GetRange() <<
198 ": '\033[40m" << TextConverter::ToStr(ts_->cgs_.ToUTF16()) << "\033[0m'";
199 break;
200 case DumpType::DONT_RETURN:
201 LOGEX_FUNC_LINE_DEBUG(Logger::SetToNoReturn) << "(" << offsetX_ << ", " << offsetY_ << ") "<<
202 (ts_->rtl_ ? "<-" : "->") << " " << ts_->cgs_.GetRange() <<
203 ": '\033[40m" << TextConverter::ToStr(ts_->cgs_.ToUTF16()) << "\033[0m'" << " ";
204 break;
205 }
206 }
207
TryToTextSpan() const208 std::shared_ptr<TextSpan> VariantSpan::TryToTextSpan() const noexcept(false)
209 {
210 CheckPointer(true);
211 return ts_;
212 }
213
TryToAnySpan() const214 std::shared_ptr<AnySpan> VariantSpan::TryToAnySpan() const noexcept(false)
215 {
216 CheckPointer(true);
217 return as_;
218 }
219
SetTextStyle(const TextStyle & xs)220 void VariantSpan::SetTextStyle(const TextStyle &xs) noexcept(true)
221 {
222 xs_ = std::move(xs);
223 }
224
GetTextStyle()225 TextStyle &VariantSpan::GetTextStyle() noexcept(true)
226 {
227 return xs_;
228 }
229
GetTextStyle() const230 const TextStyle &VariantSpan::GetTextStyle() const noexcept(true)
231 {
232 return xs_;
233 }
234
GetOffsetX() const235 double VariantSpan::GetOffsetX() const noexcept(true)
236 {
237 return offsetX_;
238 }
239
GetOffsetY() const240 double VariantSpan::GetOffsetY() const noexcept(true)
241 {
242 return offsetY_;
243 }
244
AdjustOffsetX(double offset)245 void VariantSpan::AdjustOffsetX(double offset) noexcept(true)
246 {
247 offsetX_ += offset;
248 }
249
AdjustOffsetY(double offset)250 void VariantSpan::AdjustOffsetY(double offset) noexcept(true)
251 {
252 offsetY_ += offset;
253 }
254
Paint(TexgineCanvas & canvas,double offsetX,double offsetY)255 void VariantSpan::Paint(TexgineCanvas &canvas, double offsetX, double offsetY) noexcept(false)
256 {
257 CheckPointer();
258 if (as_) {
259 as_->SetTextStyle(xs_);
260 as_->SetRoundRectType(roundRectType_);
261 as_->Paint(canvas, offsetX, offsetY);
262 }
263
264 if (ts_) {
265 ts_->Paint(canvas, offsetX, offsetY, xs_, roundRectType_);
266 }
267 }
268
PaintShadow(TexgineCanvas & canvas,double offsetX,double offsetY)269 void VariantSpan::PaintShadow(TexgineCanvas &canvas, double offsetX, double offsetY) noexcept(false)
270 {
271 CheckPointer();
272 if (ts_) {
273 ts_->PaintShadow(canvas, offsetX, offsetY, xs_.shadows);
274 }
275 }
276
IsRTL() const277 bool VariantSpan::IsRTL() const noexcept(false)
278 {
279 CheckPointer();
280 if (ts_) {
281 return ts_->IsRTL();
282 }
283
284 return false;
285 }
286
IsHardBreak() const287 bool VariantSpan::IsHardBreak() const noexcept(false)
288 {
289 CheckPointer();
290 return (ts_ && ts_->cgs_.GetBack().IsHardBreak());
291 }
292
GetJustifyGap() const293 double VariantSpan::GetJustifyGap() const noexcept(true)
294 {
295 return justifyGap_;
296 }
297
SetJustifyGap(double justifyGap)298 void VariantSpan::SetJustifyGap(double justifyGap) noexcept(true)
299 {
300 justifyGap_ = justifyGap;
301 }
302
CheckPointer(bool nullable) const303 void VariantSpan::CheckPointer(bool nullable) const
304 {
305 if (!nullable && as_ == nullptr && ts_ == nullptr) {
306 throw TEXGINE_EXCEPTION(NULLPTR);
307 }
308
309 if (as_ != nullptr && ts_ != nullptr) {
310 throw TEXGINE_EXCEPTION(ERROR_STATUS);
311 }
312 }
313
HasBackgroundRect() const314 bool VariantSpan::HasBackgroundRect() const
315 {
316 return xs_.backgroundRect.color != 0 && GetWidth() > 0;
317 }
318
GetRoundRectType() const319 RoundRectType VariantSpan::GetRoundRectType() const noexcept(true)
320 {
321 return roundRectType_;
322 }
323
SetRoundRectType(RoundRectType type)324 void VariantSpan::SetRoundRectType(RoundRectType type) noexcept(true)
325 {
326 roundRectType_ = type;
327 }
328
SetTopInGroup(double top)329 void VariantSpan::SetTopInGroup(double top)
330 {
331 CheckPointer();
332 if (as_) {
333 as_->SetTopInGroup(top);
334 }
335
336 if (ts_) {
337 ts_->topInGroup_ = top;
338 }
339 }
340
GetTopInGroup() const341 double VariantSpan::GetTopInGroup() const
342 {
343 double top = 0.0;
344 CheckPointer();
345 if (as_) {
346 top = as_->GetTopInGroup();
347 } else if (ts_) {
348 top = ts_->topInGroup_;
349 }
350 return top;
351 }
352
SetBottomInGroup(double bottom)353 void VariantSpan::SetBottomInGroup(double bottom)
354 {
355 CheckPointer();
356 if (as_) {
357 as_->SetBottomInGroup(bottom);
358 }
359
360 if (ts_) {
361 ts_->bottomInGroup_ = bottom;
362 }
363 }
364
GetBottomInGroup() const365 double VariantSpan::GetBottomInGroup() const
366 {
367 double bottom = 0.0;
368 CheckPointer();
369 if (as_) {
370 bottom = as_->GetBottomInGroup();
371 } else if (ts_) {
372 bottom = ts_->bottomInGroup_;
373 }
374 return bottom;
375 }
376
SetMaxRoundRectRadius(double radius)377 void VariantSpan::SetMaxRoundRectRadius(double radius)
378 {
379 CheckPointer();
380 if (as_) {
381 as_->SetMaxRoundRectRadius(radius);
382 }
383
384 if (ts_) {
385 ts_->maxRoundRectRadius_ = radius;
386 }
387 }
388
GetMaxRoundRectRadius() const389 double VariantSpan::GetMaxRoundRectRadius() const
390 {
391 double maxRoundRectRadius = 0.0;
392 CheckPointer();
393 if (as_) {
394 maxRoundRectRadius = as_->GetMaxRoundRectRadius();
395 } else if (ts_) {
396 maxRoundRectRadius = ts_->maxRoundRectRadius_;
397 }
398 return maxRoundRectRadius;
399 }
400
GetTop() const401 double VariantSpan::GetTop() const noexcept(true)
402 {
403 double top = offsetY_;
404 if (ts_) {
405 top += *(ts_->tmetrics_->fAscent_);
406 }
407 return top;
408 }
409
GetBottom() const410 double VariantSpan::GetBottom() const noexcept(true)
411 {
412 double bottom = GetTop();
413 if (ts_) {
414 bottom += (*(ts_->tmetrics_->fDescent_) - *(ts_->tmetrics_->fAscent_));
415 } else if (as_) {
416 bottom += as_->GetHeight();
417 }
418 return bottom;
419 }
420 } // namespace TextEngine
421 } // namespace Rosen
422 } // namespace OHOS
423