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 "core/components_ng/pattern/rich_editor/rich_editor_paint_method.h"
17 
18 #include "core/components_ng/pattern/rich_editor/paragraph_manager.h"
19 #include "core/components_ng/pattern/rich_editor/rich_editor_overlay_modifier.h"
20 #include "core/components_ng/pattern/rich_editor/rich_editor_pattern.h"
21 #include "core/components_ng/pattern/text/text_content_modifier.h"
22 #include "core/components_ng/pattern/text/text_overlay_modifier.h"
23 
24 namespace OHOS::Ace::NG {
RichEditorPaintMethod(const WeakPtr<Pattern> & pattern,const ParagraphManager * pManager,float baselineOffset,const RefPtr<TextContentModifier> & contentMod,const RefPtr<TextOverlayModifier> & overlayMod)25 RichEditorPaintMethod::RichEditorPaintMethod(const WeakPtr<Pattern>& pattern, const ParagraphManager* pManager,
26     float baselineOffset, const RefPtr<TextContentModifier>& contentMod,
27     const RefPtr<TextOverlayModifier>& overlayMod)
28     : TextPaintMethod(pattern, baselineOffset, contentMod, overlayMod),
29       pManager_(pManager)
30 {}
31 
UpdateOverlayModifier(PaintWrapper * paintWrapper)32 void RichEditorPaintMethod::UpdateOverlayModifier(PaintWrapper* paintWrapper)
33 {
34     TextPaintMethod::UpdateOverlayModifier(paintWrapper);
35     auto richEditorPattern = DynamicCast<RichEditorPattern>(GetPattern().Upgrade());
36     CHECK_NULL_VOID(richEditorPattern);
37     auto overlayMod = DynamicCast<RichEditorOverlayModifier>(GetOverlayModifier(paintWrapper));
38     overlayMod->SetPrintOffset(richEditorPattern->GetTextRect().GetOffset());
39     overlayMod->SetTextHeight(richEditorPattern->GetTextRect().Height());
40     overlayMod->SetScrollOffset(richEditorPattern->GetScrollOffset());
41     SetPreviewTextDecoration(paintWrapper);
42     if (!richEditorPattern->HasFocus()) {
43         overlayMod->UpdateScrollBar(paintWrapper);
44         overlayMod->SetCaretVisible(false);
45         const auto& selection = richEditorPattern->GetTextSelector();
46         if (richEditorPattern->GetTextContentLength() > 0 && selection.GetTextStart() != selection.GetTextEnd()) {
47             overlayMod->SetSelectedRects(pManager_->GetRects(selection.GetTextStart(), selection.GetTextEnd()));
48         }
49         return;
50     }
51     auto caretVisible = richEditorPattern->GetCaretVisible();
52     overlayMod->SetShowSelect(richEditorPattern->GetShowSelect());
53     overlayMod->SetCaretVisible(caretVisible);
54     overlayMod->SetCaretColor(richEditorPattern->GetCaretColor().GetValue());
55     overlayMod->SetSelectedBackgroundColor(richEditorPattern->GetSelectedBackgroundColor().GetValue());
56     constexpr float CARET_WIDTH = 2.0f;
57     overlayMod->SetCaretWidth(static_cast<float>(Dimension(CARET_WIDTH, DimensionUnit::VP).ConvertToPx()));
58     SetCaretOffsetAndHeight(paintWrapper);
59     std::vector<RectF> selectedRects;
60     const auto& selection = richEditorPattern->GetTextSelector();
61     if (richEditorPattern->GetTextContentLength() > 0 && selection.GetTextStart() != selection.GetTextEnd()) {
62         selectedRects = pManager_->GetRects(selection.GetTextStart(), selection.GetTextEnd());
63     }
64     auto contentRect = richEditorPattern->GetTextContentRect();
65     overlayMod->SetContentRect(contentRect);
66     overlayMod->SetSelectedRects(selectedRects);
67     auto frameSize = paintWrapper->GetGeometryNode()->GetFrameSize();
68     overlayMod->SetFrameSize(frameSize);
69     overlayMod->UpdateScrollBar(paintWrapper);
70     overlayMod->SetIsClip(false);
71 }
72 
SetPreviewTextDecoration(PaintWrapper * paintWrapper)73 void RichEditorPaintMethod::SetPreviewTextDecoration(PaintWrapper* paintWrapper)
74 {
75     auto richEditorPattern = DynamicCast<RichEditorPattern>(GetPattern().Upgrade());
76     CHECK_NULL_VOID(richEditorPattern);
77     auto overlayMod = DynamicCast<RichEditorOverlayModifier>(GetOverlayModifier(paintWrapper));
78     CHECK_NULL_VOID(overlayMod);
79     overlayMod->SetPreviewTextDecorationColor(richEditorPattern->GetPreviewTextDecorationColor());
80     overlayMod->SetPreviewTextUnderlineWidth(richEditorPattern->GetPreviewTextUnderlineWidth());
81     overlayMod->SetShowPreviewTextDecoration(richEditorPattern->IsPreviewTextInputting());
82     overlayMod->SetPreviewTextStyle(richEditorPattern->GetPreviewTextStyle());
83 }
84 
SetCaretOffsetAndHeight(PaintWrapper * paintWrapper)85 void RichEditorPaintMethod::SetCaretOffsetAndHeight(PaintWrapper* paintWrapper)
86 {
87     auto richEditorPattern = DynamicCast<RichEditorPattern>(GetPattern().Upgrade());
88     CHECK_NULL_VOID(richEditorPattern);
89     auto overlayMod = DynamicCast<RichEditorOverlayModifier>(GetOverlayModifier(paintWrapper));
90     CHECK_NULL_VOID(overlayMod);
91     CHECK_NULL_VOID(!richEditorPattern->IsMoveCaretAnywhere()); // Avoid to reset caret offset
92     auto [caretOffset, caretHeight] = richEditorPattern->CalculateCaretOffsetAndHeight();
93     auto lastOffset = overlayMod->GetCaretOffset();
94     auto lastCaretY = lastOffset.GetY() + overlayMod->GetCaretHeight() - richEditorPattern->GetLastTextRect().GetY();
95     auto curCaretY = caretOffset.GetY() + caretHeight - richEditorPattern->GetTextRect().GetY();
96     overlayMod->SetCaretOffsetAndHeight(caretOffset, caretHeight);
97     if (richEditorPattern->IsTriggerAvoidOnCaretAvoidMode() || !NearEqual(lastCaretY, curCaretY) ||
98         !NearEqual(lastOffset.GetX(), caretOffset.GetX())) {
99         richEditorPattern->NotifyCaretChange();
100         richEditorPattern->ResetTriggerAvoidFlagOnCaretChange();
101     }
102     richEditorPattern->ChangeLastRichTextRect();
103 }
104 
UpdateContentModifier(PaintWrapper * paintWrapper)105 void RichEditorPaintMethod::UpdateContentModifier(PaintWrapper* paintWrapper)
106 {
107     auto contentMod = DynamicCast<RichEditorContentModifier>(GetContentModifier(paintWrapper));
108     CHECK_NULL_VOID(contentMod);
109     TextPaintMethod::UpdateContentModifier(paintWrapper);
110     auto richEditorPattern = DynamicCast<RichEditorPattern>(GetPattern().Upgrade());
111     CHECK_NULL_VOID(richEditorPattern);
112     auto richtTextOffset = richEditorPattern->GetTextRect().GetOffset();
113     contentMod->SetRichTextRectX(richtTextOffset.GetX());
114     contentMod->SetRichTextRectY(richtTextOffset.GetY());
115 
116     const auto& geometryNode = paintWrapper->GetGeometryNode();
117     auto frameSize = geometryNode->GetPaddingSize();
118     OffsetF paddingOffset = geometryNode->GetPaddingOffset() - geometryNode->GetFrameOffset();
119     contentMod->SetClipOffset(paddingOffset);
120     contentMod->SetClipSize(frameSize);
121 }
122 } // namespace OHOS::Ace::NG
123