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 #include "image_painter_utils.h"
16
17 namespace {
18 // The [GRAY_COLOR_MATRIX] is of dimension [4 x 5], which transforms a RGB source color (R, G, B, A) to the
19 // destination color (R', G', B', A').
20 //
21 // A classic color image to grayscale conversion formula is [Gray = R * 0.3 + G * 0.59 + B * 0.11].
22 // Hence we get the following conversion:
23 //
24 // | M11 M12 M13 M14 M15 | | R | | R' |
25 // | M21 M22 M23 M24 M25 | | G | | G' |
26 // | M31 M32 M33 M34 M35 | x | B | = | B' |
27 // | M41 M42 M43 M44 M45 | | A | | A' |
28 // | 1 |
29 const float GRAY_COLOR_MATRIX[20] = { 0.30f, 0.59f, 0.11f, 0, 0, // red
30 0.30f, 0.59f, 0.11f, 0, 0, // green
31 0.30f, 0.59f, 0.11f, 0, 0, // blue
32 0, 0, 0, 1.0f, 0 }; // alpha transparency
33 } // namespace
34
35 namespace OHOS::Ace::NG {
36 #ifndef USE_ROSEN_DRAWING
ToSkRadius(const BorderRadiusArray & radiusXY)37 std::unique_ptr<SkVector[]> ImagePainterUtils::ToSkRadius(const BorderRadiusArray& radiusXY)
38 {
39 auto radii = std::make_unique<SkVector[]>(RADIUS_POINTS_SIZE);
40 if (radiusXY.size() == RADIUS_POINTS_SIZE) {
41 radii[SkRRect::kUpperLeft_Corner].set(
42 SkFloatToScalar(std::max(radiusXY[SkRRect::kUpperLeft_Corner].GetX(), 0.0f)),
43 SkFloatToScalar(std::max(radiusXY[SkRRect::kUpperLeft_Corner].GetY(), 0.0f)));
44 radii[SkRRect::kUpperRight_Corner].set(
45 SkFloatToScalar(std::max(radiusXY[SkRRect::kUpperRight_Corner].GetX(), 0.0f)),
46 SkFloatToScalar(std::max(radiusXY[SkRRect::kUpperRight_Corner].GetY(), 0.0f)));
47 radii[SkRRect::kLowerLeft_Corner].set(
48 SkFloatToScalar(std::max(radiusXY[SkRRect::kLowerRight_Corner].GetX(), 0.0f)),
49 SkFloatToScalar(std::max(radiusXY[SkRRect::kLowerRight_Corner].GetY(), 0.0f)));
50 radii[SkRRect::kLowerRight_Corner].set(
51 SkFloatToScalar(std::max(radiusXY[SkRRect::kLowerLeft_Corner].GetX(), 0.0f)),
52 SkFloatToScalar(std::max(radiusXY[SkRRect::kLowerLeft_Corner].GetY(), 0.0f)));
53 }
54 return radii;
55 }
56 #else
57 std::unique_ptr<RSPoint[]> ImagePainterUtils::ToRSRadius(const BorderRadiusArray& radiusXY)
58 {
59 auto radii = std::make_unique<RSPoint[]>(RADIUS_POINTS_SIZE);
60 if (radiusXY.size() == RADIUS_POINTS_SIZE) {
61 radii[RSRoundRect::TOP_LEFT_POS] =
62 RSPoint(static_cast<RSScalar>(std::max(radiusXY[RSRoundRect::TOP_LEFT_POS].GetX(), 0.0f)),
63 static_cast<RSScalar>(std::max(radiusXY[RSRoundRect::TOP_LEFT_POS].GetY(), 0.0f)));
64 radii[RSRoundRect::TOP_RIGHT_POS] =
65 RSPoint(static_cast<RSScalar>(std::max(radiusXY[RSRoundRect::TOP_RIGHT_POS].GetX(), 0.0f)),
66 static_cast<RSScalar>(std::max(radiusXY[RSRoundRect::TOP_RIGHT_POS].GetY(), 0.0f)));
67 radii[RSRoundRect::BOTTOM_LEFT_POS] =
68 RSPoint(static_cast<RSScalar>(std::max(radiusXY[RSRoundRect::BOTTOM_RIGHT_POS].GetX(), 0.0f)),
69 static_cast<RSScalar>(std::max(radiusXY[RSRoundRect::BOTTOM_RIGHT_POS].GetY(), 0.0f)));
70 radii[RSRoundRect::BOTTOM_RIGHT_POS] =
71 RSPoint(static_cast<RSScalar>(std::max(radiusXY[RSRoundRect::BOTTOM_LEFT_POS].GetX(), 0.0f)),
72 static_cast<RSScalar>(std::max(radiusXY[RSRoundRect::BOTTOM_LEFT_POS].GetY(), 0.0f)));
73 }
74 return radii;
75 }
76 #endif
77
78 #ifndef USE_ROSEN_DRAWING
79
AddFilter(SkPaint & paint,SkSamplingOptions & options,const ImagePaintConfig & config)80 void ImagePainterUtils::AddFilter(SkPaint& paint, SkSamplingOptions& options, const ImagePaintConfig& config)
81 {
82 switch (config.imageInterpolation_) {
83 case ImageInterpolation::LOW: {
84 options = SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone);
85 break;
86 }
87 case ImageInterpolation::MEDIUM: {
88 options = SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear);
89 break;
90 }
91 case ImageInterpolation::HIGH: {
92 options = SkSamplingOptions(SkCubicResampler::Mitchell());
93 break;
94 }
95 default:
96 options = SkSamplingOptions();
97 break;
98 }
99
100 if (config.colorFilter_.colorFilterMatrix_) {
101 paint.setColorFilter(SkColorFilters::Matrix(config.colorFilter_.colorFilterMatrix_->data()));
102 } else if (ImageRenderMode::TEMPLATE == config.renderMode_) {
103 paint.setColorFilter(SkColorFilters::Matrix(GRAY_COLOR_MATRIX));
104 }
105 }
106 #else
AddFilter(RSBrush & brush,RSSamplingOptions & options,const ImagePaintConfig & config)107 void ImagePainterUtils::AddFilter(RSBrush& brush, RSSamplingOptions& options, const ImagePaintConfig& config)
108 {
109 switch (config.imageInterpolation_) {
110 case ImageInterpolation::LOW: {
111 options = RSSamplingOptions(RSFilterMode::LINEAR, RSMipmapMode::NONE);
112 break;
113 }
114 case ImageInterpolation::MEDIUM: {
115 options = RSSamplingOptions(RSFilterMode::LINEAR, RSMipmapMode::LINEAR);
116 break;
117 }
118 case ImageInterpolation::HIGH: {
119 options = RSSamplingOptions(RSCubicResampler::Mitchell());
120 break;
121 }
122 default:
123 options = RSSamplingOptions();
124 break;
125 }
126
127 auto filter = brush.GetFilter();
128 if (config.colorFilter_.colorFilterMatrix_) {
129 RSColorMatrix colorMatrix;
130 colorMatrix.SetArray(config.colorFilter_.colorFilterMatrix_->data());
131 filter.SetColorFilter(RSRecordingColorFilter::CreateMatrixColorFilter(colorMatrix));
132 } else if (config.colorFilter_.colorFilterDrawing_) {
133 auto colorFilterSptrAddr = static_cast<std::shared_ptr<RSColorFilter>*>(
134 config.colorFilter_.colorFilterDrawing_->GetDrawingColorFilterSptrAddr());
135 if (colorFilterSptrAddr && (*colorFilterSptrAddr)) {
136 filter.SetColorFilter(*colorFilterSptrAddr);
137 }
138 } else if (ImageRenderMode::TEMPLATE == config.renderMode_) {
139 RSColorMatrix colorMatrix;
140 colorMatrix.SetArray(GRAY_COLOR_MATRIX);
141 filter.SetColorFilter(RSRecordingColorFilter::CreateMatrixColorFilter(colorMatrix));
142 }
143 brush.SetFilter(filter);
144 }
145 #endif
146
ClipRRect(RSCanvas & canvas,const RSRect & dstRect,const BorderRadiusArray & radiusXY)147 void ImagePainterUtils::ClipRRect(RSCanvas& canvas, const RSRect& dstRect, const BorderRadiusArray& radiusXY)
148 {
149 std::vector<RSPoint> radius(ImagePainterUtils::RADIUS_POINTS_SIZE);
150 // Adapt to the graphical interface and adjust the position of the last two parameters
151 radius[0] = RSPoint(radiusXY[0].GetX(), radiusXY[0].GetY());
152 radius[1] = RSPoint(radiusXY[1].GetX(), radiusXY[1].GetY());
153 radius[2] = RSPoint(radiusXY[3].GetX(), radiusXY[3].GetY());
154 radius[3] = RSPoint(radiusXY[2].GetX(), radiusXY[2].GetY());
155 RSRoundRect rRect(dstRect, radius);
156 canvas.ClipRoundRect(rRect, RSClipOp::INTERSECT, true);
157 }
158 } // namespace OHOS::Ace::NG
159