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_content_modifier.h"
17 #include "core/components_ng/pattern/rich_editor/rich_editor_pattern.h"
18 #include "core/components_ng/render/drawing.h"
19 #include "base/log/ace_trace.h"
20 
21 namespace OHOS::Ace::NG {
RichEditorContentModifier(const std::optional<TextStyle> & textStyle,const ParagraphManager * pManager,const WeakPtr<OHOS::Ace::NG::Pattern> & pattern)22 RichEditorContentModifier::RichEditorContentModifier(const std::optional<TextStyle>& textStyle,
23     const ParagraphManager* pManager, const WeakPtr<OHOS::Ace::NG::Pattern>& pattern)
24     : TextContentModifier(textStyle, pattern), pManager_(pManager), pattern_(pattern)
25 {
26     auto richEditorPattern = AceType::DynamicCast<RichEditorPattern>(pattern_.Upgrade());
27     CHECK_NULL_VOID(richEditorPattern);
28     richTextRectX_ = AceType::MakeRefPtr<PropertyFloat>(richEditorPattern->GetTextRect().GetX());
29     AttachProperty(richTextRectX_);
30     richTextRectY_ = AceType::MakeRefPtr<PropertyFloat>(richEditorPattern->GetTextRect().GetY());
31     AttachProperty(richTextRectY_);
32     clipOffset_ = AceType::MakeRefPtr<AnimatablePropertyOffsetF>(OffsetF());
33     AttachProperty(clipOffset_);
34     clipSize_ = AceType::MakeRefPtr<AnimatablePropertySizeF>(SizeF());
35     AttachProperty(clipSize_);
36 }
37 
onDraw(DrawingContext & drawingContext)38 void RichEditorContentModifier::onDraw(DrawingContext& drawingContext)
39 {
40     ACE_SCOPED_TRACE("RichEditorContentOnDraw");
41     CHECK_NULL_VOID(pManager_);
42     auto richEditorPattern = AceType::DynamicCast<RichEditorPattern>(pattern_.Upgrade());
43     CHECK_NULL_VOID(richEditorPattern);
44     auto& canvas = drawingContext.canvas;
45     canvas.Save();
46     auto contentRect = richEditorPattern->GetTextContentRect();
47     RSRect clipInnerRect = RSRect(contentRect.GetX(), contentRect.GetY(), contentRect.GetX() + contentRect.Width(),
48         contentRect.GetY() + contentRect.Height());
49     canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
50     auto&& paragraphs = pManager_->GetParagraphs();
51     auto offset = richEditorPattern->GetTextRect().GetOffset();
52     for (auto&& info : paragraphs) {
53         info.paragraph->Paint(drawingContext.canvas, offset.GetX(), offset.GetY());
54         offset.AddY(info.paragraph->GetHeight());
55     }
56     canvas.Restore();
57 
58     auto clipOffset = clipOffset_->Get();
59     auto size = clipSize_->Get();
60     auto clipRect = RSRect(
61         clipOffset.GetX(), clipOffset.GetY(), clipOffset.GetX() + size.Width(), clipOffset.GetY() + size.Height());
62     drawingContext.canvas.ClipRect(clipRect, RSClipOp::INTERSECT);
63     PaintCustomSpan(drawingContext);
64 }
65 
PaintCustomSpan(DrawingContext & drawingContext)66 void RichEditorContentModifier::PaintCustomSpan(DrawingContext& drawingContext)
67 {
68     CHECK_NULL_VOID(pManager_);
69     auto richEditorPattern = AceType::DynamicCast<RichEditorPattern>(pattern_.Upgrade());
70     CHECK_NULL_VOID(richEditorPattern);
71     auto offset = richEditorPattern->GetTextRect().GetOffset();
72     const auto& rectsForPlaceholders = richEditorPattern->GetRectsForPlaceholders();
73     auto customSpanPlaceholderInfo = richEditorPattern->GetCustomSpanPlaceholderInfo();
74     for (auto& customSpanPlaceholder : customSpanPlaceholderInfo) {
75         if (!customSpanPlaceholder.onDraw || pManager_->GetParagraphs().empty()) {
76             continue;
77         }
78         auto index = customSpanPlaceholder.customSpanIndex;
79         const auto& rect = rectsForPlaceholders.at(index);
80         auto lineMetrics = pManager_->GetLineMetricsByRectF(rect, customSpanPlaceholder.paragraphIndex);
81         CustomSpanOptions customSpanOptions;
82         customSpanOptions.x = static_cast<double>(rect.Left()) + offset.GetX();
83         customSpanOptions.lineTop = lineMetrics.y + offset.GetY();
84         customSpanOptions.lineBottom = customSpanOptions.lineTop + lineMetrics.height;
85         customSpanOptions.baseline = customSpanOptions.lineTop + lineMetrics.ascender;
86         customSpanPlaceholder.onDraw(drawingContext, customSpanOptions);
87     }
88 }
89 } // namespace OHOS::Ace::NG
90