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/text_drag/text_drag_overlay_modifier.h"
17
18 #include <variant>
19
20 #include "base/geometry/rect.h"
21 #include "base/utils/utils.h"
22 #include "core/components_ng/pattern/image/image_pattern.h"
23 #include "core/components_ng/pattern/text_drag/text_drag_pattern.h"
24 #include "core/components_ng/render/adapter/pixelmap_image.h"
25 #include "core/components_ng/render/drawing_prop_convertor.h"
26 #include "core/components/text/text_theme.h"
27
28 namespace OHOS::Ace::NG {
29 constexpr float DEFAULT_LIGHT_HEIGHT = 600.0f;
30 constexpr uint32_t DEFAULT_AMBIENT_COLOR = 0X0A000000;
31 constexpr float DEFAULT_SHADOW_COLOR = 0x33000000;
32 constexpr float DEFAULT_LIGHT_RADIUS = 800.0f;
33 constexpr float DEFAULT_ELEVATION = 120.0f;
34
TextDragOverlayModifier(const WeakPtr<OHOS::Ace::NG::Pattern> & pattern)35 TextDragOverlayModifier::TextDragOverlayModifier(const WeakPtr<OHOS::Ace::NG::Pattern>& pattern) : pattern_(pattern)
36 {
37 backgroundOffset_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(TEXT_DRAG_OFFSET.ConvertToPx());
38 selectedBackgroundOpacity_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0);
39 shadowOpacity_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0);
40 AttachProperty(backgroundOffset_);
41 AttachProperty(selectedBackgroundOpacity_);
42 AttachProperty(shadowOpacity_);
43 }
44
PaintShadow(const RSPath & path,const Shadow & shadow,RSCanvas & canvas)45 void TextDragOverlayModifier::PaintShadow(const RSPath& path, const Shadow& shadow, RSCanvas& canvas)
46 {
47 if (type_ == DragAnimType::DEFAULT) {
48 return;
49 }
50 RSRecordingPath rsPath;
51 rsPath.AddPath(path);
52 rsPath.Offset(shadow.GetOffset().GetX(), shadow.GetOffset().GetY());
53 Color color = shadow.GetColor();
54 color = color.BlendOpacity(shadowOpacity_->Get());
55 RSColor spotColor = ToRSColor(color);
56 RSPoint3 planeParams = { 0.0, 0.0, shadow.GetElevation() };
57 auto bounds = rsPath.GetBounds();
58 RSPoint3 lightPos = { bounds.GetLeft() + bounds.GetWidth() / 2.0, bounds.GetTop() + bounds.GetHeight() / 2.0,
59 DEFAULT_LIGHT_HEIGHT };
60 RSColor ambientColor = ToRSColor(Color(DEFAULT_AMBIENT_COLOR));
61 canvas.DrawShadowStyle(rsPath, planeParams, lightPos, DEFAULT_LIGHT_RADIUS, ambientColor, spotColor,
62 RSShadowFlags::TRANSPARENT_OCCLUDER, true);
63 canvas.Restore();
64 }
65
PaintBackground(const RSPath & path,RSCanvas & canvas,RefPtr<TextDragPattern> textDragPattern)66 void TextDragOverlayModifier::PaintBackground(const RSPath& path, RSCanvas& canvas,
67 RefPtr<TextDragPattern> textDragPattern)
68 {
69 auto shadow = Shadow(DEFAULT_ELEVATION, {0.0, 0.0}, Color(DEFAULT_SHADOW_COLOR), ShadowStyle::OuterFloatingSM);
70 PaintShadow(path, shadow, canvas);
71 auto pattern = DynamicCast<TextDragPattern>(pattern_.Upgrade());
72 CHECK_NULL_VOID(pattern);
73 Color color = pattern->GetDragBackgroundColor();
74 RSBrush brush;
75 brush.SetColor(ToRSColor(color));
76 brush.SetAntiAlias(true);
77 canvas.AttachBrush(brush);
78 canvas.DrawPath(path);
79 canvas.DetachBrush();
80 if (type_ == DragAnimType::DEFAULT) {
81 return;
82 }
83 canvas.Save();
84 canvas.ClipPath(path, RSClipOp::INTERSECT, true);
85 std::shared_ptr<RSPath> selPath = textDragPattern->GetSelBackgroundPath();
86 RSBrush selBrush;
87 Color selColor = Color::WHITE;
88 if (type_ == DragAnimType::FLOATING) {
89 selColor = selColor.BlendOpacity(selectedBackgroundOpacity_->Get());
90 }
91 selBrush.SetColor(ToRSColor(selColor));
92 selBrush.SetAntiAlias(true);
93 canvas.AttachBrush(selBrush);
94 canvas.DrawPath(*selPath);
95 canvas.DetachBrush();
96 canvas.Restore();
97 }
98
onDraw(DrawingContext & context)99 void TextDragOverlayModifier::onDraw(DrawingContext& context)
100 {
101 auto pattern = DynamicCast<TextDragPattern>(pattern_.Upgrade());
102 CHECK_NULL_VOID(pattern);
103 auto& canvas = context.canvas;
104 std::shared_ptr<RSPath> path;
105 if (!isAnimating_) {
106 path = pattern->GetBackgroundPath();
107 } else {
108 path = pattern->GenerateBackgroundPath(backgroundOffset_->Get(), 1 - selectedBackgroundOpacity_->Get());
109 }
110 PaintBackground(*path, canvas, pattern);
111 canvas.ClipPath(*pattern->GetClipPath(), RSClipOp::INTERSECT, true);
112 auto paragraph = pattern->GetParagraph().Upgrade();
113 if (paragraph) {
114 paragraph->Paint(canvas, pattern->GetTextRect().GetX(), pattern->GetTextRect().GetY());
115 }
116
117 size_t index = 0;
118 auto contentOffset = pattern->GetContentOffset();
119 auto imageChildren = pattern->GetImageChildren();
120 auto rectsForPlaceholders = pattern->GetRectsForPlaceholders();
121 for (const auto& child : imageChildren) {
122 auto rect = rectsForPlaceholders.at(index);
123 auto offset = OffsetF(rect.Left(), rect.Top()) - contentOffset;
124 auto imageChild = DynamicCast<ImagePattern>(child->GetPattern());
125 if (imageChild) {
126 RectF imageRect(offset.GetX(), offset.GetY(), rect.Width(), rect.Height());
127 auto canvasImage = imageChild->GetCanvasImage();
128 CHECK_NULL_VOID(canvasImage);
129 auto pixelMapImage = DynamicCast<PixelMapImage>(canvasImage);
130 CHECK_NULL_VOID(pixelMapImage);
131 pixelMapImage->DrawRect(canvas, ToRSRect(imageRect));
132 }
133 ++index;
134 }
135 }
136
SetBackgroundOffset(float offset)137 void TextDragOverlayModifier::SetBackgroundOffset(float offset)
138 {
139 backgroundOffset_->Set(offset);
140 }
141
SetSelectedBackgroundOpacity(float offset)142 void TextDragOverlayModifier::SetSelectedBackgroundOpacity(float offset)
143 {
144 selectedBackgroundOpacity_->Set(offset);
145 }
146 } // namespace OHOS::Ace::NG
147