1 /*
2 * Copyright (c) 2021-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 "core/components/text/rosen_render_text.h"
17
18 #include <cmath>
19
20 #ifndef USE_GRAPHIC_TEXT_GINE
21 #include "txt/paragraph_builder.h"
22 #include "txt/paragraph_txt.h"
23 #else
24 #include "rosen_text/typography.h"
25 #include "rosen_text/typography_create.h"
26 #endif
27 #include "render_service_client/core/ui/rs_node.h"
28 #include "unicode/uchar.h"
29
30 #include "base/geometry/dimension.h"
31 #include "base/geometry/offset.h"
32 #include "base/i18n/localization.h"
33 #include "base/utils/string_utils.h"
34 #include "base/utils/utils.h"
35 #include "core/common/font_manager.h"
36 #include "core/components/font/constants_converter.h"
37 #include "core/components/font/rosen_font_collection.h"
38 #include "core/components/text/text_component.h"
39 #include "core/components/text_span/rosen_render_text_span.h"
40 #include "core/pipeline/base/rosen_render_context.h"
41 #include "core/pipeline/pipeline_context.h"
42
43 namespace OHOS::Ace {
44 namespace {
45
46 const std::u16string ELLIPSIS = u"\u2026";
47 constexpr Dimension ADAPT_UNIT = 1.0_fp;
48 constexpr int32_t COMPATIBLE_VERSION = 6;
49
50 } // namespace
51
Update(const RefPtr<Component> & component)52 void RosenRenderText::Update(const RefPtr<Component>& component)
53 {
54 RenderText::Update(component);
55 if (auto rsNode = GetRSNode()) {
56 bool shouldClipToContent = (textStyle_.GetTextOverflow() == TextOverflow::CLIP);
57 rsNode->SetClipToFrame(shouldClipToContent);
58 if (isCustomFont_) {
59 rsNode->SetIsCustomTextType(isCustomFont_);
60 }
61 }
62 }
63
GetBaselineDistance(TextBaseline textBaseline)64 double RosenRenderText::GetBaselineDistance(TextBaseline textBaseline)
65 {
66 if (textBaseline == TextBaseline::IDEOGRAPHIC) {
67 return paragraph_->GetIdeographicBaseline() + std::max(NormalizeToPx(textStyle_.GetBaselineOffset()), 0.0);
68 }
69 return paragraph_->GetAlphabeticBaseline() + std::max(NormalizeToPx(textStyle_.GetBaselineOffset()), 0.0);
70 }
71
Paint(RenderContext & context,const Offset & offset)72 void RosenRenderText::Paint(RenderContext& context, const Offset& offset)
73 {
74 if (!NeedPaint()) {
75 return;
76 }
77
78 if (needMeasure_) {
79 LOGW("Text can not paint before measure.");
80 return;
81 }
82 auto canvas = static_cast<RosenRenderContext*>(&context)->GetCanvas();
83 auto rsNode = static_cast<RosenRenderContext*>(&context)->GetRSNode();
84 if (!canvas || !rsNode || !paragraph_) {
85 LOGE("Paint canvas or paragraph is null");
86 return;
87 }
88 rsNode->SetPaintOrder(true);
89
90 RenderNode::Paint(context, offset);
91
92 auto baselineOffset = std::min(NormalizeToPx(textStyle_.GetBaselineOffset()), 0.0);
93 auto paintOffset = offset - Offset(0.0, baselineOffset);
94 auto textRealWidth = paragraph_->GetMaxWidth();
95 auto textRealHeight = paragraph_->GetHeight();
96 SetParagraphWidth(textRealWidth);
97 SetParagraphHeight(textRealHeight);
98 float newX = paintOffset.GetX();
99 float newY = paintOffset.GetY();
100
101 if (text_->GetDeclarationHeight().IsValid()) {
102 switch (textStyle_.GetTextVerticalAlign()) {
103 case VerticalAlign::TOP:
104 break;
105 case VerticalAlign::BOTTOM:
106 newY = offset.GetY() + (GetLayoutSize().Height() - textRealHeight) -
107 std::max(NormalizeToPx(textStyle_.GetBaselineOffset()), 0.0);
108 break;
109 case VerticalAlign::CENTER:
110 newY = offset.GetY() - NormalizeToPx(textStyle_.GetBaselineOffset()) +
111 (GetLayoutSize().Height() - textRealHeight) / 2.0;
112 break;
113 default:
114 break;
115 }
116 }
117
118 switch (textStyle_.GetTextAlign()) {
119 case TextAlign::LEFT:
120 break;
121 case TextAlign::START:
122 if (TextDirection::RTL == defaultTextDirection_) {
123 newX = paintOffset.GetX() + (GetLayoutSize().Width() - textRealWidth);
124 }
125 break;
126 case TextAlign::RIGHT:
127 newX = paintOffset.GetX() + (GetLayoutSize().Width() - textRealWidth);
128 break;
129 case TextAlign::END:
130 if (TextDirection::RTL != defaultTextDirection_) {
131 newX = paintOffset.GetX() + (GetLayoutSize().Width() - textRealWidth);
132 }
133 break;
134 case TextAlign::CENTER:
135 newX = paintOffset.GetX() + (GetLayoutSize().Width() - textRealWidth) / 2.0;
136 break;
137 case TextAlign::JUSTIFY:
138 break;
139 default:
140 break;
141 }
142
143 PaintSelection(canvas, GetGlobalOffset());
144 paragraph_->Paint(canvas, newX, newY);
145 }
146
NeedPaint()147 bool RosenRenderText::NeedPaint()
148 {
149 // If font is custom font, paint text until font is ready.
150 auto pipelineContext = context_.Upgrade();
151 if (pipelineContext && pipelineContext->GetFontManager()) {
152 auto fontNames = pipelineContext->GetFontManager()->GetFontNames();
153 for (const auto& familyName : textStyle_.GetFontFamilies()) {
154 if (std::find(std::begin(fontNames), std::end(fontNames), familyName) != std::end(fontNames) &&
155 !isCallbackCalled_) {
156 return false;
157 }
158 }
159 for (const auto& child : GetChildren()) {
160 auto span = AceType::DynamicCast<RenderTextSpan>(child);
161 if (!span) {
162 continue;
163 }
164 for (const auto& familyName : span->GetSpanStyle().GetFontFamilies()) {
165 if (std::find(std::begin(fontNames), std::end(fontNames), familyName) != std::end(fontNames) &&
166 !span->IsCallbackCalled()) {
167 return false;
168 }
169 }
170 }
171 }
172 return true;
173 }
174
Measure()175 Size RosenRenderText::Measure()
176 {
177 if (!text_ || CheckMeasureFlag()) {
178 return GetSize();
179 }
180
181 textStyle_.SetMaxLines(maxLines_);
182 lastLayoutMaxWidth_ = GetLayoutParam().GetMaxSize().Width();
183 lastLayoutMinWidth_ = GetLayoutParam().GetMinSize().Width();
184 lastLayoutMaxHeight_ = GetLayoutParam().GetMaxSize().Height();
185 lastLayoutMinHeight_ = GetLayoutParam().GetMinSize().Height();
186 if (!textStyle_.GetAdaptTextSize()) {
187 if (!UpdateParagraph()) {
188 LOGE("fail to initialize text paragraph");
189 return Size();
190 }
191 paragraph_->Layout(lastLayoutMaxWidth_);
192 } else {
193 if (!AdaptTextSize(lastLayoutMaxWidth_)) {
194 LOGE("fail to initialize text paragraph in adapt text size step");
195 return Size();
196 }
197 }
198 needMeasure_ = false;
199 // If you need to lay out the text according to the maximum layout width given by the parent, use it.
200 if (text_->GetMaxWidthLayout()) {
201 paragraphNewWidth_ = GetLayoutParam().GetMaxSize().Width();
202 return GetSize();
203 }
204 // The reason for the second layout is because the TextAlign property needs the width of the layout,
205 // and the width of the second layout is used as the width of the TextAlign layout.
206 if (!NearEqual(lastLayoutMinWidth_, lastLayoutMaxWidth_)) {
207 paragraphNewWidth_ = std::clamp(GetTextWidth(), lastLayoutMinWidth_, lastLayoutMaxWidth_);
208 if (!NearEqual(paragraphNewWidth_, paragraph_->GetMaxWidth())) {
209 ApplyIndents(paragraphNewWidth_);
210 paragraph_->Layout(std::ceil(paragraphNewWidth_));
211 }
212 }
213 EffectAutoMaxLines();
214 return GetSize();
215 }
216
IsCompatibleVersion()217 bool RosenRenderText::IsCompatibleVersion()
218 {
219 auto context = context_.Upgrade();
220 if (!context) {
221 return false;
222 }
223 return context->GetMinPlatformVersion() >= COMPATIBLE_VERSION;
224 }
225
CheckMeasureFlag()226 bool RosenRenderText::CheckMeasureFlag()
227 {
228 if (isCallbackCalled_) {
229 needMeasure_ = true;
230 }
231 for (const auto& child : GetChildren()) {
232 auto span = AceType::DynamicCast<RenderTextSpan>(child);
233 if (span && (span->IsCallbackCalled() || span->NeedLayout())) {
234 paragraph_.reset();
235 needMeasure_ = true;
236 break;
237 }
238 }
239
240 double paragraphMaxWidth = GetLayoutParam().GetMaxSize().Width();
241 double paragraphMinWidth = GetLayoutParam().GetMinSize().Width();
242 double paragraphMaxHeight = GetLayoutParam().GetMaxSize().Height();
243 double paragraphMinHeight = GetLayoutParam().GetMinSize().Height();
244
245 if (!needMeasure_) {
246 // Layout when constrains of height is changed.
247 if (!NearEqual(paragraphMaxHeight, lastLayoutMaxHeight_) ||
248 !NearEqual(paragraphMinHeight, lastLayoutMinHeight_)) {
249 return false;
250 }
251 bool constrainsAffect = true;
252 auto layoutWidth = GetSize().Width();
253 if (NearEqual(paragraphMaxWidth, lastLayoutMaxWidth_) && NearEqual(paragraphMinWidth, lastLayoutMinWidth_)) {
254 // Width constrains not changed.
255 constrainsAffect = false;
256 } else if (!IsCompatibleVersion() && GreatOrEqual(layoutWidth, paragraphMinWidth) &&
257 LessOrEqual(layoutWidth, paragraphMaxWidth) && (lastLayoutMaxWidth_ - layoutWidth > 1.0)) {
258 // Constrains changed but has no effect. For example, text width is 100 when constrains [0, 200].
259 // When constrains changed to [100, 300], there's no need to do layout.
260 // An exception is that given [0, 100], resulting in layout 100. We assume the actual layout size is more
261 // than 100 due to soft-wrap.
262 if (!textStyle_.GetAdaptTextSize()) {
263 constrainsAffect = false;
264 }
265 }
266 if (!constrainsAffect) {
267 return true;
268 }
269 }
270 return false;
271 }
272
EffectAutoMaxLines()273 void RosenRenderText::EffectAutoMaxLines()
274 {
275 // Effect when max-lines set auto.
276 if (!paragraph_ || !text_ || !text_->GetAutoMaxLines()) {
277 return;
278 }
279
280 auto lineCount = GetTextLines();
281 while (lineCount > 0 && GreatNotEqual(paragraph_->GetHeight(), GetLayoutParam().GetMaxSize().Height())) {
282 textStyle_.SetMaxLines(--lineCount);
283 UpdateParagraphAndLayout(lastLayoutMaxWidth_);
284 }
285 }
286
AdaptTextSize(double paragraphMaxWidth)287 bool RosenRenderText::AdaptTextSize(double paragraphMaxWidth)
288 {
289 const auto& preferTextSizeGroups = textStyle_.GetPreferTextSizeGroups();
290 if (!preferTextSizeGroups.empty()) {
291 return AdaptPreferTextSizeGroup(paragraphMaxWidth);
292 }
293 const auto& preferFontSizes = textStyle_.GetPreferFontSizes();
294 if (!preferFontSizes.empty()) {
295 return AdaptPreferTextSize(paragraphMaxWidth);
296 }
297 return AdaptMinTextSize(paragraphMaxWidth);
298 }
299
AdaptMinTextSize(double paragraphMaxWidth)300 bool RosenRenderText::AdaptMinTextSize(double paragraphMaxWidth)
301 {
302 double maxFontSize = NormalizeToPx(textStyle_.GetAdaptMaxFontSize());
303 double minFontSize = NormalizeToPx(textStyle_.GetAdaptMinFontSize());
304 if (LessNotEqual(maxFontSize, minFontSize) || LessOrEqual(textStyle_.GetAdaptMinFontSize().Value(), 0.0)) {
305 if (!UpdateParagraph()) {
306 LOGE("fail to initialize text paragraph when adapt min text size.");
307 return false;
308 }
309 paragraph_->Layout(lastLayoutMaxWidth_);
310 return true;
311 }
312 Dimension step = ADAPT_UNIT;
313 if (GreatNotEqual(textStyle_.GetAdaptFontSizeStep().Value(), 0.0)) {
314 step = textStyle_.GetAdaptFontSizeStep();
315 }
316 double stepSize = NormalizeToPx(step);
317 while (GreatOrEqual(maxFontSize, minFontSize)) {
318 textStyle_.SetFontSize(Dimension(maxFontSize));
319 if (!UpdateParagraphAndLayout(paragraphMaxWidth)) {
320 return false;
321 }
322 if (!DidExceedMaxLines(paragraphMaxWidth)) {
323 break;
324 }
325 maxFontSize -= stepSize;
326 }
327 return true;
328 }
329
AdaptPreferTextSize(double paragraphMaxWidth)330 bool RosenRenderText::AdaptPreferTextSize(double paragraphMaxWidth)
331 {
332 // Use preferFontSizes to adapt lines.
333 const auto& preferFontSizes = textStyle_.GetPreferFontSizes();
334 for (const auto& fontSize : preferFontSizes) {
335 textStyle_.SetFontSize(fontSize);
336 if (!UpdateParagraphAndLayout(paragraphMaxWidth)) {
337 return false;
338 }
339 if (!DidExceedMaxLines(paragraphMaxWidth)) {
340 break;
341 }
342 }
343 return true;
344 }
345
AdaptPreferTextSizeGroup(double paragraphMaxWidth)346 bool RosenRenderText::AdaptPreferTextSizeGroup(double paragraphMaxWidth)
347 {
348 // Use preferTextSizeGroup.
349 const auto& preferTextSizeGroups = textStyle_.GetPreferTextSizeGroups();
350 for (const auto& preferTextSizeGroup : preferTextSizeGroups) {
351 textStyle_.SetFontSize(preferTextSizeGroup.fontSize);
352 textStyle_.SetMaxLines(preferTextSizeGroup.maxLines);
353 textStyle_.SetTextOverflow(preferTextSizeGroup.textOverflow);
354 if (!UpdateParagraphAndLayout(paragraphMaxWidth)) {
355 return false;
356 }
357 if ((preferTextSizeGroup.textOverflow == TextOverflow::NONE) || (!DidExceedMaxLines(paragraphMaxWidth))) {
358 break;
359 }
360 }
361 return true;
362 }
363
UpdateParagraphAndLayout(double paragraphMaxWidth)364 bool RosenRenderText::UpdateParagraphAndLayout(double paragraphMaxWidth)
365 {
366 if (!UpdateParagraph()) {
367 return false;
368 }
369 if (paragraph_) {
370 paragraph_->Layout(paragraphMaxWidth);
371 }
372 return true;
373 }
374
GetTextLines()375 uint32_t RosenRenderText::GetTextLines()
376 {
377 uint32_t textLines = 0;
378 #ifndef USE_GRAPHIC_TEXT_GINE
379 auto paragraphTxt = static_cast<txt::ParagraphTxt*>(paragraph_.get());
380 if (paragraphTxt != nullptr) {
381 textLines = paragraphTxt->GetLineCount();
382 }
383 #else
384 if (paragraph_ != nullptr) {
385 textLines = paragraph_->GetLineCount();
386 }
387 #endif
388 return textLines;
389 }
390
GetTouchPosition(const Offset & offset)391 int32_t RosenRenderText::GetTouchPosition(const Offset& offset)
392 {
393 if (!paragraph_) {
394 return 0;
395 }
396 #ifndef USE_GRAPHIC_TEXT_GINE
397 return static_cast<int32_t>(paragraph_->GetGlyphPositionAtCoordinate(offset.GetX(), offset.GetY()).position);
398 #else
399 return static_cast<int32_t>(paragraph_->GetGlyphIndexByCoordinate(offset.GetX(), offset.GetY()).index);
400 #endif
401 }
402
GetSize()403 Size RosenRenderText::GetSize()
404 {
405 double height = paragraph_ ? paragraph_->GetHeight() : 0.0;
406 double heightFinal = std::min(
407 height + std::fabs(NormalizeToPx(textStyle_.GetBaselineOffset())), GetLayoutParam().GetMaxSize().Height());
408 const auto& VerticalAlign = textStyle_.GetTextVerticalAlign();
409 if (((VerticalAlign == VerticalAlign::TOP || VerticalAlign == VerticalAlign::CENTER ||
410 VerticalAlign == VerticalAlign::BOTTOM)) &&
411 text_->GetDeclarationHeight().IsValid()) {
412 heightFinal = GetLayoutParam().GetMaxSize().Height();
413 }
414
415 return Size(text_->GetMaxWidthLayout() ? paragraphNewWidth_ : std::ceil(paragraphNewWidth_), heightFinal);
416 }
417
ApplyWhiteSpace()418 std::string RosenRenderText::ApplyWhiteSpace()
419 {
420 std::string data = text_->GetData();
421 switch (textStyle_.GetWhiteSpace()) {
422 case WhiteSpace::NORMAL:
423 StringUtils::ReplaceTabAndNewLine(data);
424 break;
425 case WhiteSpace::PRE:
426 break;
427 case WhiteSpace::NOWRAP:
428 textStyle_.SetMaxLines(1);
429 StringUtils::ReplaceTabAndNewLine(data);
430 break;
431 case WhiteSpace::PRE_WRAP:
432 break;
433 case WhiteSpace::PRE_LINE:
434 StringUtils::ReplaceSpace(data);
435 break;
436 default:
437 break;
438 }
439 return data;
440 }
441
ApplyIndents(double width)442 void RosenRenderText::ApplyIndents(double width)
443 {
444 std::vector<float> indents;
445 double indent;
446 if (textStyle_.GetTextIndent().Unit() != DimensionUnit::PERCENT) {
447 indent = NormalizeToPx(textStyle_.GetTextIndent());
448 } else {
449 indent = width * textStyle_.GetTextIndent().Value();
450 }
451
452 if (indent > 0.0) {
453 indents.push_back(indent);
454 indents.push_back(0.0);
455 } else {
456 indents.push_back(0.0);
457 indents.push_back(-indent);
458 }
459 }
460
UpdateParagraph()461 bool RosenRenderText::UpdateParagraph()
462 {
463 if (!text_) {
464 return false;
465 }
466
467 using namespace Constants;
468
469 #ifndef USE_GRAPHIC_TEXT_GINE
470 txt::ParagraphStyle style;
471 #else
472 Rosen::TypographyStyle style;
473 #endif
474
475 if (alignment_.has_value()) {
476 textStyle_.SetTextAlign(alignment_.value());
477 }
478 const auto& textAlign = textStyle_.GetTextAlign();
479 if (textAlign == TextAlign::START || textAlign == TextAlign::END) {
480 std::string data = text_->GetData();
481 if (!GetChildren().empty()) {
482 for (const auto& child : GetChildren()) {
483 auto span = DynamicCast<RenderTextSpan>(child);
484 if (span && !span->GetSpanData().empty()) {
485 data = span->GetSpanData();
486 break;
487 }
488 }
489 }
490 if (!ChangeDirectionIfNeeded(data)) {
491 defaultTextDirection_ = text_->GetTextDirection();
492 }
493 }
494 std::string displayData = ApplyWhiteSpace();
495 #ifndef USE_GRAPHIC_TEXT_GINE
496 style.text_direction = ConvertTxtTextDirection(defaultTextDirection_);
497 style.text_align = ConvertTxtTextAlign(textAlign);
498 style.max_lines = textStyle_.GetMaxLines();
499 #else
500 style.textDirection = ConvertTxtTextDirection(defaultTextDirection_);
501 style.textAlign = ConvertTxtTextAlign(textAlign);
502 style.maxLines = textStyle_.GetMaxLines();
503 #endif
504 style.locale = Localization::GetInstance()->GetFontLocale();
505 if (textStyle_.GetTextOverflow() == TextOverflow::ELLIPSIS) {
506 if (!IsCompatibleVersion() && textStyle_.GetMaxLines() == UINT32_MAX && !text_->GetAutoMaxLines()) {
507 #ifndef USE_GRAPHIC_TEXT_GINE
508 style.max_lines = 1;
509 #else
510 style.maxLines = 1;
511 #endif
512 }
513 style.ellipsis = ELLIPSIS;
514 auto context = GetContext().Upgrade();
515 if (context && context->UseLiteStyle()) {
516 #ifndef USE_GRAPHIC_TEXT_GINE
517 style.max_lines = 1;
518 #else
519 style.maxLines = 1;
520 #endif
521 }
522 }
523
524 #ifndef USE_GRAPHIC_TEXT_GINE
525 std::unique_ptr<txt::ParagraphBuilder> builder;
526 #endif
527
528 auto fontCollection = RosenFontCollection::GetInstance().GetFontCollection();
529 if (!fontCollection) {
530 LOGW("UpdateParagraph: fontCollection is null");
531 return false;
532 }
533 #ifndef USE_GRAPHIC_TEXT_GINE
534 builder = txt::ParagraphBuilder::CreateTxtBuilder(style, fontCollection);
535 #else
536 auto builder = Rosen::TypographyCreate::Create(style, fontCollection);
537 #endif
538 std::string textValue = "";
539
540 #ifndef USE_GRAPHIC_TEXT_GINE
541 txt::TextStyle txtStyle;
542 #else
543 Rosen::TextStyle txtStyle;
544 #endif
545 ConvertTxtStyle(textStyle_, context_, txtStyle);
546 builder->PushStyle(txtStyle);
547 const auto& children = GetChildren();
548 if (!children.empty()) {
549 touchRegions_.clear();
550 for (const auto& child : children) {
551 auto textSpan = AceType::DynamicCast<RosenRenderTextSpan>(child);
552 if (textSpan) {
553 textSpan->UpdateText(*builder, touchRegions_, textValue);
554 }
555 }
556 textValue_.text = textValue;
557 textForDisplay_ = textValue;
558 } else {
559 StringUtils::TransformStrCase(displayData, (int32_t)textStyle_.GetTextCase());
560 #ifndef USE_GRAPHIC_TEXT_GINE
561 builder->AddText(StringUtils::Str8ToStr16(displayData));
562 #else
563 builder->AppendText(StringUtils::Str8ToStr16(displayData));
564 #endif
565 }
566 #ifndef USE_GRAPHIC_TEXT_GINE
567 paragraph_ = builder->Build();
568 #else
569 paragraph_ = builder->CreateTypography();
570 #endif
571
572 ApplyIndents(GetLayoutParam().GetMaxSize().Width());
573 return true;
574 }
575
GetTextWidth()576 double RosenRenderText::GetTextWidth()
577 {
578 if (!paragraph_) {
579 return 0.0;
580 }
581 if (!IsCompatibleVersion()) {
582 return paragraph_->GetMaxIntrinsicWidth();
583 }
584 #ifndef USE_GRAPHIC_TEXT_GINE
585 auto* paragraphTxt = static_cast<txt::ParagraphTxt*>(paragraph_.get());
586 if (paragraphTxt != nullptr && paragraphTxt->GetLineCount() == 1) {
587 return std::max(paragraph_->GetLongestLine(), paragraph_->GetMaxIntrinsicWidth());
588 }
589 return paragraph_->GetLongestLine();
590 #else
591 if (paragraph_ != nullptr && paragraph_->GetLineCount() == 1) {
592 return std::max(paragraph_->GetActualWidth(), paragraph_->GetMaxIntrinsicWidth());
593 }
594 return paragraph_->GetActualWidth();
595 #endif
596 }
597
DidExceedMaxLines(double paragraphMaxWidth)598 bool RosenRenderText::DidExceedMaxLines(double paragraphMaxWidth)
599 {
600 #ifndef USE_GRAPHIC_TEXT_GINE
601 auto* paragraphTxt = static_cast<txt::ParagraphTxt*>(paragraph_.get());
602 if (paragraphTxt != nullptr) {
603 bool didExceedMaxLines = paragraphTxt->DidExceedMaxLines() ||
604 (textStyle_.GetAdaptHeight() &&
605 GreatNotEqual(paragraph_->GetHeight(), GetLayoutParam().GetMaxSize().Height()));
606 #else
607 if (paragraph_ != nullptr) {
608 bool didExceedMaxLines = paragraph_->DidExceedMaxLines() ||
609 (textStyle_.GetAdaptHeight() &&
610 GreatNotEqual(paragraph_->GetHeight(), GetLayoutParam().GetMaxSize().Height()));
611 #endif
612 if (textStyle_.GetMaxLines() == 1) {
613 return didExceedMaxLines || GreatNotEqual(GetTextWidth(), paragraphMaxWidth);
614 }
615 return didExceedMaxLines;
616 }
617 return false;
618 }
619
620 bool RosenRenderText::ChangeDirectionIfNeeded(const std::string& data)
621 {
622 auto declaration = text_->GetDeclaration();
623 if (!declaration) {
624 return false;
625 }
626 auto& commonAttr = static_cast<CommonAttribute&>(declaration->GetAttribute(AttributeTag::COMMON_ATTR));
627 if (!commonAttr.IsValid() || commonAttr.direction != TextDirection::AUTO) {
628 return false;
629 }
630 auto showingTextForWString = StringUtils::ToWstring(data);
631 for (const auto& charOfShowingText : showingTextForWString) {
632 if (u_charDirection(charOfShowingText) == UCharDirection::U_LEFT_TO_RIGHT) {
633 defaultTextDirection_ = TextDirection::LTR;
634 return true;
635 } else if (u_charDirection(charOfShowingText) == UCharDirection::U_RIGHT_TO_LEFT) {
636 defaultTextDirection_ = TextDirection::RTL;
637 return true;
638 } else if (!IsCompatibleVersion() &&
639 u_charDirection(charOfShowingText) == UCharDirection::U_RIGHT_TO_LEFT_ARABIC) {
640 defaultTextDirection_ = TextDirection::RTL;
641 return true;
642 }
643 }
644 return false;
645 }
646
647 bool RosenRenderText::MaybeRelease()
648 {
649 auto context = GetContext().Upgrade();
650 if (context && context->GetRenderFactory() && context->GetRenderFactory()->GetRenderTextFactory()->Recycle(this)) {
651 ClearRenderObject();
652 return false;
653 }
654 return true;
655 }
656
657 void RosenRenderText::ClearRenderObject()
658 {
659 RenderText::ClearRenderObject();
660 paragraph_ = nullptr;
661 paragraphNewWidth_ = 0.0;
662 lastLayoutMaxWidth_ = 0.0;
663 lastLayoutMinWidth_ = 0.0;
664 lastLayoutMaxHeight_ = 0.0;
665 lastLayoutMinHeight_ = 0.0;
666 }
667
668 Offset RosenRenderText::GetHandleOffset(int32_t extend)
669 {
670 Rect result;
671 GetCaretRect(extend, result);
672 selectHeight_ = result.Bottom() - result.Top();
673 Offset handleLocalOffset = Offset((result.Left() + result.Right()) / 2.0, result.Bottom());
674 Offset handleOffset = handleLocalOffset + GetOffsetToPage();
675 return handleOffset;
676 }
677
678 } // namespace OHOS::Ace
679