• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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