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 
UpdateParagraphAndImageSpanNodeList()32 void TextPaintMethod::UpdateParagraphAndImageSpanNodeList()
33 {
34     CHECK_NULL_VOID(textContentModifier_);
35     auto textPattern = DynamicCast<TextPattern>(pattern_.Upgrade());
36     CHECK_NULL_VOID(textPattern);
37     textContentModifier_->SetImageSpanNodeList(textPattern->GetImageSpanNodeList());
38 }
39 
UpdateContentModifier(PaintWrapper * paintWrapper)40 void TextPaintMethod::UpdateContentModifier(PaintWrapper* paintWrapper)
41 {
42     CHECK_NULL_VOID(paintWrapper);
43     CHECK_NULL_VOID(textContentModifier_);
44     auto pattern = DynamicCast<TextPattern>(pattern_.Upgrade());
45     CHECK_NULL_VOID(pattern);
46     auto pManager = pattern->GetParagraphManager();
47     CHECK_NULL_VOID(pManager);
48     UpdateParagraphAndImageSpanNodeList();
49     SizeF contentSize = paintWrapper->GetContentSize();
50     textContentModifier_->SetContentSize(contentSize);
51     auto offset = paintWrapper->GetContentOffset();
52     textContentModifier_->SetContentOffset(offset);
53     auto paintOffset = offset - OffsetF(0.0, std::min(baselineOffset_, 0.0f));
54     textContentModifier_->SetPrintOffset(paintOffset);
55     pattern->SetPrintInfo("ContentOffset:", paintOffset);
56     auto frameNode = pattern->GetHost();
57     CHECK_NULL_VOID(frameNode);
58     auto layoutProperty = frameNode->GetLayoutProperty<TextLayoutProperty>();
59     CHECK_NULL_VOID(layoutProperty);
60     auto renderContext = frameNode->GetRenderContext();
61     CHECK_NULL_VOID(renderContext);
62     auto textOverflow = layoutProperty->GetTextOverflow();
63     if (textOverflow.has_value() && textOverflow.value() == TextOverflow::MARQUEE) {
64         if (pManager->GetLongestLineWithIndent() > paintWrapper->GetContentSize().Width()) {
65             textContentModifier_->StartTextRace();
66         } else {
67             textContentModifier_->StopTextRace();
68         }
69     } else {
70         textContentModifier_->StopTextRace();
71     }
72 
73     // Privacy masking.
74     auto reasons = renderContext->GetObscured().value_or(std::vector<ObscuredReasons>());
75     bool ifPaintObscuration = std::any_of(reasons.begin(), reasons.end(),
76         [](const auto& reason) { return reason == ObscuredReasons::PLACEHOLDER; });
77     if (ifPaintObscuration) {
78         UpdateObscuredRects();
79     } else {
80         textContentModifier_->SetIfPaintObscuration(false);
81     }
82 
83     if (renderContext->GetClipEdge().has_value()) {
84         textContentModifier_->SetClip(renderContext->GetClipEdge().value());
85     }
86 }
87 
UpdateObscuredRects()88 void TextPaintMethod::UpdateObscuredRects()
89 {
90     auto pattern = DynamicCast<TextPattern>(pattern_.Upgrade());
91     CHECK_NULL_VOID(pattern);
92     auto pManager = pattern->GetParagraphManager();
93     CHECK_NULL_VOID(pManager);
94 
95     auto spanItemChildren = pattern->GetSpanItemChildren();
96     auto ifPaintObscuration = spanItemChildren.empty();
97     textContentModifier_->SetIfPaintObscuration(ifPaintObscuration);
98     CHECK_NULL_VOID(ifPaintObscuration);
99 
100     auto wideTextLength = pattern->GetDisplayWideTextLength();
101     std::vector<RectF> drawObscuredRects;
102     if (wideTextLength != 0 && ifPaintObscuration) {
103         drawObscuredRects = pManager->GetRects(0, wideTextLength);
104     }
105     textContentModifier_->SetDrawObscuredRects(drawObscuredRects);
106 }
107 
GetOverlayModifier(PaintWrapper * paintWrapper)108 RefPtr<Modifier> TextPaintMethod::GetOverlayModifier(PaintWrapper* paintWrapper)
109 {
110     return textOverlayModifier_;
111 }
112 
UpdateOverlayModifier(PaintWrapper * paintWrapper)113 void TextPaintMethod::UpdateOverlayModifier(PaintWrapper* paintWrapper)
114 {
115     CHECK_NULL_VOID(paintWrapper);
116     CHECK_NULL_VOID(textOverlayModifier_);
117 
118     auto textPattern = DynamicCast<TextPattern>(pattern_.Upgrade());
119     CHECK_NULL_VOID(textPattern);
120     auto pManager = textPattern->GetParagraphManager();
121     CHECK_NULL_VOID(pManager);
122 
123     auto offset = paintWrapper->GetContentOffset();
124     auto paintOffset = offset - OffsetF(0.0, std::min(baselineOffset_, 0.0f));
125     textOverlayModifier_->SetPrintOffset(paintOffset);
126     auto host = textPattern->GetHost();
127     CHECK_NULL_VOID(host);
128     auto context = host->GetRenderContext();
129     CHECK_NULL_VOID(context);
130     const auto& selection = textPattern->GetTextSelector();
131     auto contentRect = textPattern->GetTextContentRect();
132     std::vector<RectF> selectedRects;
133     if (selection.GetTextStart() != selection.GetTextEnd()) {
134         auto rects = pManager->GetParagraphsRects(selection.GetTextStart(), selection.GetTextEnd());
135         selectedRects = CalculateSelectedRect(rects, contentRect.Width());
136     }
137     textOverlayModifier_->SetContentRect(contentRect);
138     textOverlayModifier_->SetShowSelect(textPattern->GetShowSelect());
139     textOverlayModifier_->SetSelectedRects(selectedRects);
140     auto pipelineContext = host->GetContext();
141     CHECK_NULL_VOID(pipelineContext);
142     auto themeManager = pipelineContext->GetThemeManager();
143     CHECK_NULL_VOID(themeManager);
144     auto theme = themeManager->GetTheme<TextTheme>();
145     CHECK_NULL_VOID(theme);
146     auto layoutProperty = host->GetLayoutProperty<TextLayoutProperty>();
147     CHECK_NULL_VOID(layoutProperty);
148     auto cursorColor = layoutProperty->GetCursorColorValue(theme->GetCaretColor());
149     textOverlayModifier_->SetCursorColor(cursorColor.GetValue());
150     auto selectedColor = layoutProperty->GetSelectedBackgroundColorValue(theme->GetSelectedColor());
151     textOverlayModifier_->SetSelectedColor(selectedColor.GetValue());
152     if (context->GetClipEdge().has_value()) {
153         textOverlayModifier_->SetIsClip(context->GetClipEdge().value());
154     }
155 }
156 
CalculateSelectedRect(const std::vector<std::pair<std::vector<RectF>,TextDirection>> & selectedRects,float contentWidth)157 std::vector<RectF> TextPaintMethod::CalculateSelectedRect(
158     const std::vector<std::pair<std::vector<RectF>, TextDirection>>& selectedRects, float contentWidth)
159 {
160     std::vector<RectF> result;
161     for (const auto& info : selectedRects) {
162         auto rects = info.first;
163         TextBase::CalculateSelectedRect(rects, contentWidth, info.second);
164         result.insert(result.end(), rects.begin(), rects.end());
165     }
166     return result;
167 }
168 } // namespace OHOS::Ace::NG