1 /*
2 * Copyright (c) 2022-2024 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/image/image_paint_method.h"
17
18 #include "base/utils/utils.h"
19 #include "core/common/container.h"
20 #include "core/components_ng/pattern/image/image_dfx.h"
21 #include "core/components_ng/render/adapter/svg_canvas_image.h"
22
23 namespace {
24 constexpr unsigned int TOP_LEFT = 0;
25 constexpr unsigned int TOP_RIGHT = 1;
26 constexpr unsigned int BOTTOM_LEFT = 2;
27 constexpr unsigned int BOTTOM_RIGHT = 3;
28 constexpr float DEFAULT_HDR_BRIGHTNESS = 1.0f;
29 } // namespace
30
31 namespace OHOS::Ace::NG {
32 namespace {
NormalizeRadius(BorderRadiusArray & radius,const SizeF & size)33 void NormalizeRadius(BorderRadiusArray& radius, const SizeF& size)
34 {
35 auto maxRadius = std::min(size.Width(), size.Height()) / 2;
36 // radius shouldn't be larger than half of image size
37 for (auto&& corner : radius) {
38 if (corner.GetX() > maxRadius) {
39 corner.SetX(maxRadius);
40 }
41 if (corner.GetY() > maxRadius) {
42 corner.SetY(maxRadius);
43 }
44 }
45 }
46 } // namespace
47
UpdateBorderRadius(PaintWrapper * paintWrapper,ImageDfxConfig & imageDfxConfig)48 void ImagePaintMethod::UpdateBorderRadius(PaintWrapper* paintWrapper, ImageDfxConfig& imageDfxConfig)
49 {
50 auto renderCtx = paintWrapper->GetRenderContext();
51 CHECK_NULL_VOID(renderCtx);
52 auto borderRadius = renderCtx->GetBorderRadius();
53 if (!borderRadius.has_value()) {
54 return;
55 }
56 BorderRadiusArray radiusXY = BorderRadiusArray();
57
58 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
59 auto paintRectWidth = renderCtx->GetPaintRectWithoutTransform().Width();
60 radiusXY = { PointF(borderRadius->radiusTopLeft->ConvertToPxWithSize(paintRectWidth),
61 borderRadius->radiusTopLeft->ConvertToPxWithSize(paintRectWidth)),
62 PointF(borderRadius->radiusTopRight->ConvertToPxWithSize(paintRectWidth),
63 borderRadius->radiusTopRight->ConvertToPxWithSize(paintRectWidth)),
64 PointF(borderRadius->radiusBottomLeft->ConvertToPxWithSize(paintRectWidth),
65 borderRadius->radiusBottomLeft->ConvertToPxWithSize(paintRectWidth)),
66 PointF(borderRadius->radiusBottomRight->ConvertToPxWithSize(paintRectWidth),
67 borderRadius->radiusBottomRight->ConvertToPxWithSize(paintRectWidth)) };
68 } else {
69 radiusXY = { PointF(borderRadius->radiusTopLeft->ConvertToPx(), borderRadius->radiusTopLeft->ConvertToPx()),
70 PointF(borderRadius->radiusTopRight->ConvertToPx(), borderRadius->radiusTopRight->ConvertToPx()),
71 PointF(borderRadius->radiusBottomLeft->ConvertToPx(), borderRadius->radiusBottomLeft->ConvertToPx()),
72 PointF(borderRadius->radiusBottomRight->ConvertToPx(), borderRadius->radiusBottomRight->ConvertToPx()) };
73 }
74
75 // adjust image radius to match border (concentric round rects)
76 auto width = renderCtx->GetBorderWidth();
77 if (width) {
78 if (width->leftDimen) {
79 auto diff = width->leftDimen->ConvertToPx();
80 radiusXY[TOP_LEFT].SetX(radiusXY[TOP_LEFT].GetX() - diff);
81 radiusXY[BOTTOM_LEFT].SetX(radiusXY[BOTTOM_LEFT].GetX() - diff);
82 }
83 if (width->rightDimen) {
84 auto diff = width->rightDimen->ConvertToPx();
85 radiusXY[TOP_RIGHT].SetX(radiusXY[TOP_RIGHT].GetX() - diff);
86 radiusXY[BOTTOM_RIGHT].SetX(radiusXY[BOTTOM_RIGHT].GetX() - diff);
87 }
88 if (width->topDimen) {
89 auto diff = width->topDimen->ConvertToPx();
90 radiusXY[TOP_LEFT].SetY(radiusXY[TOP_LEFT].GetY() - diff);
91 radiusXY[TOP_RIGHT].SetY(radiusXY[TOP_RIGHT].GetY() - diff);
92 }
93 if (width->bottomDimen) {
94 auto diff = width->bottomDimen->ConvertToPx();
95 radiusXY[BOTTOM_LEFT].SetY(radiusXY[BOTTOM_LEFT].GetY() - diff);
96 radiusXY[BOTTOM_RIGHT].SetY(radiusXY[BOTTOM_RIGHT].GetY() - diff);
97 }
98 }
99
100 NormalizeRadius(radiusXY, paintWrapper->GetContentSize());
101 auto&& config = canvasImage_->GetPaintConfig();
102 config.borderRadiusXY_ = std::make_shared<BorderRadiusArray>(radiusXY);
103 }
104
UpdatePaintConfig(PaintWrapper * paintWrapper)105 void ImagePaintMethod::UpdatePaintConfig(PaintWrapper* paintWrapper)
106 {
107 auto&& config = canvasImage_->GetPaintConfig();
108 auto renderProps = DynamicCast<ImageRenderProperty>(paintWrapper->GetPaintProperty());
109 config.renderMode_ = renderProps->GetImageRenderMode().value_or(ImageRenderMode::ORIGINAL);
110 config.imageInterpolation_ = renderProps->GetImageInterpolation().value_or(interpolationDefault_);
111 config.imageRepeat_ = renderProps->GetImageRepeat().value_or(ImageRepeat::NO_REPEAT);
112 config.smoothEdge_ = renderProps->GetSmoothEdge().value_or(0.0f);
113 config.dynamicMode = renderProps->GetDynamicModeValue(DynamicRangeMode::STANDARD);
114 config.svgFillColor_ = renderProps->GetSvgFillColor();
115 config.resizableSlice_ = renderProps->GetImageResizableSliceValue({});
116 config.resizableLattice_ = renderProps->GetImageResizableLatticeValue(nullptr);
117
118 bool isRightToLeft = AceApplicationInfo::GetInstance().IsRightToLeft();
119 config.flipHorizontally_ = isRightToLeft && renderProps->GetMatchTextDirection().value_or(false);
120 config.colorFilter_.Reset();
121
122 auto colorFilterMatrix = renderProps->GetColorFilter();
123 if (colorFilterMatrix.has_value()) {
124 config.colorFilter_.colorFilterMatrix_ = std::make_shared<std::vector<float>>(colorFilterMatrix.value());
125 }
126 auto drawingColorFilter = renderProps->GetDrawingColorFilter();
127 if (drawingColorFilter.has_value()) {
128 config.colorFilter_.colorFilterDrawing_ = drawingColorFilter.value();
129 }
130 auto renderCtx = paintWrapper->GetRenderContext();
131 if (renderCtx) {
132 config.obscuredReasons_ = renderCtx->GetObscured().value_or(std::vector<ObscuredReasons>());
133 }
134
135 if (renderProps->HasHdrBrightness() && canvasImage_->IsHdrPixelMap() && renderCtx) {
136 renderCtx->SetImageHDRBrightness(renderProps->GetHdrBrightnessValue(DEFAULT_HDR_BRIGHTNESS));
137 renderCtx->SetImageHDRPresent(true);
138 config.dynamicMode = DynamicRangeMode::HIGH;
139 }
140
141 if (renderProps->GetNeedBorderRadiusValue(false)) {
142 UpdateBorderRadius(paintWrapper, canvasImage_->GetImageDfxConfig());
143 }
144 auto ImageFit = renderProps->GetImageFit().value_or(ImageFit::COVER);
145 if (ImageFit == ImageFit::MATRIX) {
146 const auto matrix4Len = Matrix4::DIMENSION * Matrix4::DIMENSION;
147 std::vector<float> matrix(matrix4Len);
148 const int32_t initPosition = 5;
149 for (int32_t i = 0; i < matrix4Len; i = i + initPosition) {
150 matrix[i] = 1.0f;
151 }
152 Matrix4 defaultValue = Matrix4(
153 matrix[0], matrix[4], matrix[8], matrix[12],
154 matrix[1], matrix[5], matrix[9], matrix[13],
155 matrix[2], matrix[6], matrix[10], matrix[14],
156 matrix[3], matrix[7], matrix[11], matrix[15]);
157 config.imageMatrix_ = renderProps->GetImageMatrix().value_or(defaultValue);
158 }
159 }
160
UpdatePaintMethod(const RefPtr<CanvasImage> & canvasImage,const ImagePaintMethodConfig & imagePainterMethodConfig)161 void ImagePaintMethod::UpdatePaintMethod(
162 const RefPtr<CanvasImage>& canvasImage, const ImagePaintMethodConfig& imagePainterMethodConfig)
163 {
164 selected_ = imagePainterMethodConfig.selected;
165 selected_ = imagePainterMethodConfig.selected;
166 sensitive_ = imagePainterMethodConfig.sensitive;
167 canvasImage_ = canvasImage;
168 interpolationDefault_ = imagePainterMethodConfig.interpolation;
169 imageOverlayModifier_ = imagePainterMethodConfig.imageOverlayModifier;
170 imageContentModifier_ = imagePainterMethodConfig.imageContentModifier;
171 }
172
GetOverlayModifier(PaintWrapper * paintWrapper)173 RefPtr<Modifier> ImagePaintMethod::GetOverlayModifier(PaintWrapper* paintWrapper)
174 {
175 return imageOverlayModifier_;
176 }
177
GetContentModifier(PaintWrapper * paintWrapper)178 RefPtr<Modifier> ImagePaintMethod::GetContentModifier(PaintWrapper* paintWrapper)
179 {
180 return imageContentModifier_;
181 }
182
UpdateOverlayModifier(PaintWrapper * paintWrapper)183 void ImagePaintMethod::UpdateOverlayModifier(PaintWrapper* paintWrapper)
184 {
185 CHECK_NULL_VOID(paintWrapper);
186 CHECK_NULL_VOID(imageOverlayModifier_);
187 auto size = paintWrapper->GetContentSize();
188 auto offset = paintWrapper->GetContentOffset();
189 imageOverlayModifier_->SetSize(size);
190 imageOverlayModifier_->SetOffset(offset);
191 imageOverlayModifier_->SetIsSelected(selected_);
192 }
193
UpdateContentModifier(PaintWrapper * paintWrapper)194 void ImagePaintMethod::UpdateContentModifier(PaintWrapper* paintWrapper)
195 {
196 CHECK_NULL_VOID(canvasImage_);
197 CHECK_NULL_VOID(paintWrapper);
198 CHECK_NULL_VOID(imageContentModifier_);
199 UpdatePaintConfig(paintWrapper);
200 auto size = paintWrapper->GetContentSize();
201 imageContentModifier_->SetSize(size);
202 imageContentModifier_->SetSensitive(sensitive_);
203 imageContentModifier_->SetCanvasImageWrapper(CanvasImageModifierWrapper(canvasImage_));;
204 }
205 } // namespace OHOS::Ace::NG
206