1 /*
2 * Copyright (c) 2022 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_ng/pattern/text/text_paint_method.h"
17
18 #include "core/components_ng/pattern/text/text_pattern.h"
19
20 namespace OHOS::Ace::NG {
TextPaintMethod(const WeakPtr<Pattern> & pattern,float baselineOffset,RefPtr<TextContentModifier> textContentModifier,RefPtr<TextOverlayModifier> textOverlayModifier)21 TextPaintMethod::TextPaintMethod(const WeakPtr<Pattern>& pattern, float baselineOffset,
22 RefPtr<TextContentModifier> textContentModifier, RefPtr<TextOverlayModifier> textOverlayModifier)
23 : pattern_(pattern), baselineOffset_(baselineOffset),
24 textContentModifier_(std::move(textContentModifier)), textOverlayModifier_(std::move(textOverlayModifier))
25 {}
26
GetContentModifier(PaintWrapper * paintWrapper)27 RefPtr<Modifier> TextPaintMethod::GetContentModifier(PaintWrapper* paintWrapper)
28 {
29 return textContentModifier_;
30 }
31
UpdateContentModifier(PaintWrapper * paintWrapper)32 void TextPaintMethod::UpdateContentModifier(PaintWrapper* paintWrapper)
33 {
34 CHECK_NULL_VOID(paintWrapper);
35 CHECK_NULL_VOID(textContentModifier_);
36
37 auto textPattern = DynamicCast<TextPattern>(pattern_.Upgrade());
38 CHECK_NULL_VOID(textPattern);
39 auto paragraph = textPattern->GetParagraph();
40 CHECK_NULL_VOID(paragraph);
41
42 textContentModifier_->SetParagraph(paragraph);
43
44 SizeF contentSize = paintWrapper->GetContentSize();
45 textContentModifier_->SetContentSize(contentSize);
46 auto offset = paintWrapper->GetContentOffset();
47 textContentModifier_->SetContentOffset(offset);
48 auto paintOffset = offset - OffsetF(0.0, std::min(baselineOffset_, 0.0f));
49 textContentModifier_->SetPrintOffset(paintOffset);
50
51 auto frameNode = textPattern->GetHost();
52 CHECK_NULL_VOID(frameNode);
53 auto layoutProperty = frameNode->GetLayoutProperty<TextLayoutProperty>();
54 CHECK_NULL_VOID(layoutProperty);
55 auto renderContext = frameNode->GetRenderContext();
56 CHECK_NULL_VOID(renderContext);
57 auto pattern = frameNode->GetPattern<TextPattern>();
58 CHECK_NULL_VOID(pattern);
59
60 auto textOverflow = layoutProperty->GetTextOverflow();
61 if (textOverflow.has_value() && textOverflow.value() == TextOverflow::MARQUEE) {
62 if (paragraph->GetTextWidth() > paintWrapper->GetContentSize().Width()) {
63 textContentModifier_->StartTextRace();
64 } else {
65 textContentModifier_->StopTextRace();
66 }
67 } else {
68 textContentModifier_->StopTextRace();
69 }
70
71 auto reasons = renderContext->GetObscured().value_or(std::vector<ObscuredReasons>());
72 textContentModifier_->SetObscured(reasons);
73 auto spanItemChildren = pattern->GetSpanItemChildren();
74 textContentModifier_->SetIfHaveSpanItemChildren(!spanItemChildren.empty());
75 auto wideTextLength = pattern->GetDisplayWideTextLength();
76 std::vector<RectF> drawObscuredRects;
77 if (wideTextLength != 0) {
78 paragraph->GetRectsForRange(0, wideTextLength, drawObscuredRects);
79 }
80 textContentModifier_->SetDrawObscuredRects(drawObscuredRects);
81 if (renderContext->GetClipEdge().has_value()) {
82 textContentModifier_->SetClip(renderContext->GetClipEdge().value());
83 }
84
85 PropertyChangeFlag flag = 0;
86 if (textContentModifier_->NeedMeasureUpdate(flag)) {
87 frameNode->MarkDirtyNode(flag);
88 }
89 }
90
GetOverlayModifier(PaintWrapper * paintWrapper)91 RefPtr<Modifier> TextPaintMethod::GetOverlayModifier(PaintWrapper* paintWrapper)
92 {
93 return textOverlayModifier_;
94 }
95
UpdateOverlayModifier(PaintWrapper * paintWrapper)96 void TextPaintMethod::UpdateOverlayModifier(PaintWrapper* paintWrapper)
97 {
98 CHECK_NULL_VOID(paintWrapper);
99 CHECK_NULL_VOID(textOverlayModifier_);
100
101 auto textPattern = DynamicCast<TextPattern>(pattern_.Upgrade());
102 CHECK_NULL_VOID(textPattern);
103 auto paragraph = textPattern->GetParagraph();
104 CHECK_NULL_VOID(paragraph);
105
106 auto offset = paintWrapper->GetContentOffset();
107 auto paintOffset = offset - OffsetF(0.0, std::min(baselineOffset_, 0.0f));
108 textOverlayModifier_->SetPrintOffset(paintOffset);
109 auto host = textPattern->GetHost();
110 CHECK_NULL_VOID(host);
111 auto context = host->GetRenderContext();
112 CHECK_NULL_VOID(context);
113 const auto& selection = textPattern->GetTextSelector();
114 auto contentRect = textPattern->GetTextContentRect();
115 std::vector<RectF> selectedRects;
116 if (selection.GetTextStart() != selection.GetTextEnd()) {
117 paragraph->GetRectsForRange(selection.GetTextStart(), selection.GetTextEnd(), selectedRects);
118 TextBase::CalculateSelectedRect(selectedRects, contentRect.Width());
119 }
120 textOverlayModifier_->SetContentRect(contentRect);
121 textOverlayModifier_->SetShowSelect(textPattern->GetShowSelect());
122 textOverlayModifier_->SetSelectedRects(selectedRects);
123 auto pipelineContext = PipelineContext::GetCurrentContext();
124 CHECK_NULL_VOID(pipelineContext);
125 auto themeManager = pipelineContext->GetThemeManager();
126 CHECK_NULL_VOID(themeManager);
127 auto theme = themeManager->GetTheme<TextTheme>();
128 auto selectedColor = theme->GetSelectedColor().GetValue();
129 textOverlayModifier_->SetSelectedColor(selectedColor);
130 if (context->GetClipEdge().has_value()) {
131 textOverlayModifier_->SetIsClip(context->GetClipEdge().value());
132 }
133 }
134 } // namespace OHOS::Ace::NG