• 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/render/adapter/pixelmap_image.h"
17 
18 #include "render_service_base/include/pipeline/rs_recording_canvas.h"
19 
20 #include "base/log/ace_trace.h"
21 #include "core/components/common/layout/constants.h"
22 #include "core/components_ng/image_provider/image_data.h"
23 #include "core/components_ng/pattern/image/image_dfx.h"
24 #include "core/components_ng/property/measure_utils.h"
25 #include "core/components_ng/render/adapter/image_painter_utils.h"
26 #include "core/components_ng/render/adapter/rosen/drawing_image.h"
27 #include "core/components_ng/render/canvas_image.h"
28 #include "core/components_ng/render/drawing_forward.h"
29 #include "core/pipeline/pipeline_base.h"
30 
31 namespace OHOS::Ace::NG {
32 namespace {
33 // The [GRAY_COLOR_MATRIX] is of dimension [4 x 5], which transforms a RGB source color (R, G, B, A) to the
34 // destination color (R', G', B', A').
35 //
36 // A classic color image to grayscale conversion formula is [Gray = R * 0.3 + G * 0.59 + B * 0.11].
37 // Hence we get the following conversion:
38 //
39 // | M11 M12 M13 M14 M15 |   | R |   | R' |
40 // | M21 M22 M23 M24 M25 |   | G |   | G' |
41 // | M31 M32 M33 M34 M35 | x | B | = | B' |
42 // | M41 M42 M43 M44 M45 |   | A |   | A' |
43 //                           | 1 |
44 const float GRAY_COLOR_MATRIX[20] = { 0.30f, 0.59f, 0.11f, 0, 0, // red
45     0.30f, 0.59f, 0.11f, 0, 0,                                   // green
46     0.30f, 0.59f, 0.11f, 0, 0,                                   // blue
47     0, 0, 0, 1.0f, 0 };                                          // alpha transparency
48 
49 constexpr int32_t BORDER_RADIUS_ARRAY_SIZE = 4;
50 constexpr int32_t DEGREE_NINETY = 90;
51 constexpr int32_t DEGREE_HUNDRED_EIGHTY = 180;
52 
PrintDrawingLatticeConfig(const Rosen::Drawing::Lattice & lattice,const RSRect & dstRect)53 void PrintDrawingLatticeConfig(const Rosen::Drawing::Lattice& lattice, const RSRect& dstRect)
54 {
55     std::string drawingConfigStr;
56     drawingConfigStr.append("dstRect = " + dstRect.ToString());
57     drawingConfigStr.append("fXCount = " + std::to_string(lattice.fXCount));
58     drawingConfigStr.append("fXDivs = [");
59     for (int32_t idx = 0; idx < lattice.fXCount; ++idx) {
60         drawingConfigStr.append(std::to_string(lattice.fXDivs[idx]) + " ");
61     }
62     drawingConfigStr.append("] ");
63     drawingConfigStr.append("fYCount = " + std::to_string(lattice.fYCount));
64     drawingConfigStr.append("fYDivs = [");
65     for (int32_t idx = 0; idx < lattice.fYCount; ++idx) {
66         drawingConfigStr.append(std::to_string(lattice.fYDivs[idx]) + " ");
67     }
68     drawingConfigStr.append("] ");
69     TAG_LOGD(AceLogTag::ACE_IMAGE, "Begin to draw image with lattice : %{public}s", drawingConfigStr.c_str());
70 }
71 
ConvertSlice(const ImagePaintConfig & config,RectF & result,float rawImageWidth,float rawImageHeight)72 bool ConvertSlice(const ImagePaintConfig& config, RectF& result, float rawImageWidth, float rawImageHeight)
73 {
74     const auto& slice = config.resizableSlice_;
75     CHECK_NULL_RETURN(slice.Valid(), false);
76     TAG_LOGD(AceLogTag::ACE_IMAGE, "Draw image with slice = %{public}s.", slice.ToString().c_str());
77     result.SetLeft(ConvertToPx(slice.left, ScaleProperty::CreateScaleProperty(), rawImageWidth).value_or(0.0f));
78     result.SetTop(ConvertToPx(slice.top, ScaleProperty::CreateScaleProperty(), rawImageHeight).value_or(0.0f));
79     auto rightSliceValue = ConvertToPx(slice.right, ScaleProperty::CreateScaleProperty(), rawImageWidth).value_or(0.0f);
80     auto bottomSliceValue =
81         ConvertToPx(slice.bottom, ScaleProperty::CreateScaleProperty(), rawImageHeight).value_or(0.0f);
82     // illegal case if left position if larger than right, then rect has negative width
83     if (GreatNotEqual(rawImageWidth - rightSliceValue - result.GetX(), 0.0f)) {
84         result.SetWidth(rawImageWidth - rightSliceValue - result.GetX());
85     } else {
86         return false;
87     }
88     // same illegal case for height
89     if (GreatNotEqual(rawImageHeight - bottomSliceValue - result.GetY(), 0.0f)) {
90         result.SetHeight(rawImageHeight - bottomSliceValue - result.GetY());
91     } else {
92         return false;
93     }
94     return true;
95 }
96 
GetDynamicModeString(DynamicRangeMode dynamicMode)97 std::string GetDynamicModeString(DynamicRangeMode dynamicMode)
98 {
99     switch (dynamicMode) {
100         case DynamicRangeMode::HIGH:
101             return "HIGH";
102         case DynamicRangeMode::CONSTRAINT:
103             return "CONSTRAINT";
104         case DynamicRangeMode::STANDARD:
105             return "STANDARD";
106         default:
107             return "STANDARD";
108     }
109 }
110 
111 #ifndef USE_ROSEN_DRAWING
UpdateSKFilter(const ImagePaintConfig & config,SKPaint & paint)112 void UpdateSKFilter(const ImagePaintConfig& config, SKPaint& paint)
113 {
114     if (config.colorFilter_.colorFilterMatrix_) {
115         paint.setColorFilter(SkColorFilters::Matrix(config.colorFilter_.colorFilterMatrix_->data()));
116     } else if (ImageRenderMode::TEMPLATE == config.renderMode_) {
117         paint.setColorFilter(SkColorFilters::Matrix(GRAY_COLOR_MATRIX));
118     }
119 }
120 #else
UpdateRSFilter(const ImagePaintConfig & config,RSFilter & filter)121 void UpdateRSFilter(const ImagePaintConfig& config, RSFilter& filter)
122 {
123     if (config.colorFilter_.colorFilterMatrix_) {
124         RSColorMatrix colorMatrix;
125         colorMatrix.SetArray(config.colorFilter_.colorFilterMatrix_->data());
126         filter.SetColorFilter(RSRecordingColorFilter::CreateMatrixColorFilter(colorMatrix));
127     } else if (config.colorFilter_.colorFilterDrawing_) {
128         auto colorFilterSptrAddr = static_cast<std::shared_ptr<RSColorFilter>*>(
129             config.colorFilter_.colorFilterDrawing_->GetDrawingColorFilterSptrAddr());
130         if (colorFilterSptrAddr && (*colorFilterSptrAddr)) {
131             filter.SetColorFilter(*colorFilterSptrAddr);
132         }
133     } else if (ImageRenderMode::TEMPLATE == config.renderMode_) {
134         RSColorMatrix colorMatrix;
135         colorMatrix.SetArray(GRAY_COLOR_MATRIX);
136         filter.SetColorFilter(RSRecordingColorFilter::CreateMatrixColorFilter(colorMatrix));
137     }
138 }
139 #endif
140 
CalculateRotateDegree(ImageRotateOrientation orientation)141 int32_t CalculateRotateDegree(ImageRotateOrientation orientation)
142 {
143     switch (orientation) {
144         case ImageRotateOrientation::LEFT:
145             return -DEGREE_NINETY;
146         case ImageRotateOrientation::RIGHT:
147             return DEGREE_NINETY;
148         case ImageRotateOrientation::DOWN:
149             return DEGREE_HUNDRED_EIGHTY;
150         default:
151             return 0;
152     }
153 }
154 } // namespace
155 
Create(const RefPtr<PixelMap> & pixelMap)156 RefPtr<CanvasImage> CanvasImage::Create(const RefPtr<PixelMap>& pixelMap)
157 {
158     return AceType::MakeRefPtr<PixelMapImage>(pixelMap);
159 }
160 
Clone()161 RefPtr<CanvasImage> PixelMapImage::Clone()
162 {
163     return MakeRefPtr<PixelMapImage>(pixelMap_);
164 }
165 
GetWidth() const166 int32_t PixelMapImage::GetWidth() const
167 {
168     auto pixmap = GetPixelMap();
169     if (pixmap) {
170         return pixmap->GetWidth();
171     }
172     TAG_LOGW(AceLogTag::ACE_IMAGE, "pixelMap_ is nullptr, return width 0.");
173     return 0;
174 }
175 
GetHeight() const176 int32_t PixelMapImage::GetHeight() const
177 {
178     auto pixmap = GetPixelMap();
179     if (pixmap) {
180         return pixmap->GetHeight();
181     }
182     TAG_LOGW(AceLogTag::ACE_IMAGE, "rsCanvas is nullptr, return height 0.");
183     return 0;
184 }
185 
StretchImageWithLattice(RSCanvas & canvas,const RSRect & srcRect,const RSRect & dstRect,const BorderRadiusArray & radiusXY)186 bool PixelMapImage::StretchImageWithLattice(
187     RSCanvas& canvas, const RSRect& srcRect, const RSRect& dstRect, const BorderRadiusArray& radiusXY)
188 {
189     auto pixmap = GetPixelMap();
190     const auto& config = GetPaintConfig();
191     auto drawingLattice = config.resizableLattice_;
192     CHECK_NULL_RETURN(drawingLattice, false);
193 #ifdef ENABLE_ROSEN_BACKEND
194     auto latticeSptrAddr =
195         static_cast<std::shared_ptr<Rosen::Drawing::Lattice>*>(drawingLattice->GetDrawingLatticeSptrAddr());
196     CHECK_NULL_RETURN((latticeSptrAddr && (*latticeSptrAddr)), false);
197     RSBrush brush;
198     auto filterMode = RSFilterMode::NEAREST;
199     switch (config.imageInterpolation_) {
200         case ImageInterpolation::LOW:
201         case ImageInterpolation::MEDIUM:
202             filterMode = RSFilterMode::LINEAR;
203             break;
204         case ImageInterpolation::HIGH:
205         default:
206             break;
207     }
208 
209     auto filter = brush.GetFilter();
210     UpdateRSFilter(config, filter);
211     brush.SetFilter(filter);
212     auto& recordingCanvas = static_cast<Rosen::ExtendRecordingCanvas&>(canvas);
213     auto radii = ImagePainterUtils::ToRSRadius(radiusXY);
214     std::vector<RSPoint> radius;
215     for (size_t ii = 0; ii < BORDER_RADIUS_ARRAY_SIZE; ii++) {
216         RSPoint point(radii[ii].GetX(), radii[ii].GetY());
217         radius.emplace_back(point);
218     }
219     recordingCanvas.ClipAdaptiveRoundRect(radius);
220     recordingCanvas.Scale(config.scaleX_, config.scaleY_);
221 
222     RSPoint pointRadius[BORDER_RADIUS_ARRAY_SIZE] = {};
223     for (size_t i = 0; i < BORDER_RADIUS_ARRAY_SIZE; i++) {
224         pointRadius[i] = radius[i];
225     }
226     std::shared_ptr<RSImage> rsImage = DrawingImage::MakeRSImageFromPixmap(pixmap);
227     CHECK_NULL_RETURN(rsImage, false);
228     auto lattice = *(*latticeSptrAddr);
229     if (SystemProperties::GetDebugEnabled()) {
230         PrintDrawingLatticeConfig(lattice, dstRect);
231     }
232     recordingCanvas.AttachBrush(brush);
233     recordingCanvas.DrawImageLattice(rsImage.get(), lattice, dstRect, filterMode);
234     recordingCanvas.DetachBrush();
235     return true;
236 #endif
237     return false;
238 }
239 
StretchImageWithSlice(RSCanvas & canvas,const RSRect & srcRect,const RSRect & dstRect,const BorderRadiusArray & radiusXY)240 bool PixelMapImage::StretchImageWithSlice(
241     RSCanvas& canvas, const RSRect& srcRect, const RSRect& dstRect, const BorderRadiusArray& radiusXY)
242 {
243     auto pixmap = GetPixelMap();
244     const auto& config = GetPaintConfig();
245     const auto& slice = GetPaintConfig().resizableSlice_;
246     CHECK_NULL_RETURN(slice.Valid(), false);
247     RectF centerRect;
248     CHECK_NULL_RETURN(ConvertSlice(config, centerRect, pixmap->GetWidth(), pixmap->GetHeight()), false);
249 #ifdef ENABLE_ROSEN_BACKEND
250     RSBrush brush;
251     auto filterMode = RSFilterMode::NEAREST;
252     switch (config.imageInterpolation_) {
253         case ImageInterpolation::LOW:
254         case ImageInterpolation::MEDIUM:
255             filterMode = RSFilterMode::LINEAR;
256             break;
257         case ImageInterpolation::HIGH:
258         default:
259             break;
260     }
261 
262     auto filter = brush.GetFilter();
263     UpdateRSFilter(config, filter);
264     brush.SetFilter(filter);
265     auto& recordingCanvas = static_cast<Rosen::ExtendRecordingCanvas&>(canvas);
266     auto radii = ImagePainterUtils::ToRSRadius(radiusXY);
267     std::vector<RSPoint> radius;
268     for (int ii = 0; ii < BORDER_RADIUS_ARRAY_SIZE; ii++) {
269         RSPoint point(radii[ii].GetX(), radii[ii].GetY());
270         radius.emplace_back(point);
271     }
272     recordingCanvas.ClipAdaptiveRoundRect(radius);
273     recordingCanvas.Scale(config.scaleX_, config.scaleY_);
274 
275     RSPoint pointRadius[BORDER_RADIUS_ARRAY_SIZE] = {};
276     for (int i = 0; i < BORDER_RADIUS_ARRAY_SIZE; i++) {
277         pointRadius[i] = radius[i];
278     }
279     RSRectI rsCenterRect(centerRect.GetX(), centerRect.GetY(), centerRect.GetX() + centerRect.Width(),
280         centerRect.GetY() + centerRect.Height());
281     std::shared_ptr<RSImage> rsImage = DrawingImage::MakeRSImageFromPixmap(pixmap);
282     CHECK_NULL_RETURN(rsImage, false);
283     recordingCanvas.AttachBrush(brush);
284     recordingCanvas.DrawImageNine(rsImage.get(), rsCenterRect, dstRect, filterMode, &brush);
285     recordingCanvas.DetachBrush();
286     return true;
287 #endif
288     return false;
289 }
290 
CheckIfNeedForStretching(RSCanvas & canvas,const RSRect & srcRect,const RSRect & dstRect,const BorderRadiusArray & radiusXY)291 bool PixelMapImage::CheckIfNeedForStretching(
292     RSCanvas& canvas, const RSRect& srcRect, const RSRect& dstRect, const BorderRadiusArray& radiusXY)
293 {
294     const auto& config = GetPaintConfig();
295 
296     if (config.frameCount_ == 1 && config.resizableLattice_ &&
297         StretchImageWithLattice(canvas, srcRect, dstRect, radiusXY)) {
298         return true;
299     }
300     if (config.frameCount_ == 1 && config.resizableSlice_.Valid() &&
301         StretchImageWithSlice(canvas, srcRect, dstRect, radiusXY)) {
302         return true;
303     }
304     return false;
305 }
306 
NotifyDrawCompletion(const std::string & srcInfo,const RefPtr<PixelMap> & pixmap)307 void PixelMapImage::NotifyDrawCompletion(const std::string& srcInfo, const RefPtr<PixelMap>& pixmap)
308 {
309     FireDrawCompleteCallback(RenderedImageInfo{
310         .renderSuccess = true,
311         .width = pixmap->GetWidth(),
312         .height = pixmap->GetHeight(),
313         .rowStride = pixmap->GetRowStride(),
314         .rowBytes = pixmap->GetRowBytes(),
315         .byteCount = pixmap->GetByteCount(),
316         .isHdr = pixmap->IsHdr(),
317         .alphaType = pixmap->GetAlphaType(),
318         .pixelFormat = pixmap->GetPixelFormat(),
319         .allocatorType = pixmap->GetAllocatorType(),
320         .pixelMapId = pixmap->GetId(),
321         .srcInfo = srcInfo
322     });
323 }
324 
DrawToRSCanvas(RSCanvas & canvas,const RSRect & srcRect,const RSRect & dstRect,const BorderRadiusArray & radiusXY)325 void PixelMapImage::DrawToRSCanvas(
326     RSCanvas& canvas, const RSRect& srcRect, const RSRect& dstRect, const BorderRadiusArray& radiusXY)
327 {
328     auto pixmap = GetPixelMap();
329     auto dfxConfig = GetImageDfxConfig();
330     if (!pixmap || !pixmap->GetPixelMapSharedPtr()) {
331         TAG_LOGE(AceLogTag::ACE_IMAGE, "pixmap null, %{private}s-%{public}s", dfxConfig.imageSrc_.c_str(),
332             dfxConfig.ToStringWithoutSrc().c_str());
333         return;
334     }
335 #ifdef ENABLE_ROSEN_BACKEND
336     if (CheckIfNeedForStretching(canvas, srcRect, dstRect, radiusXY)) {
337         return;
338     }
339     const auto& config = GetPaintConfig();
340     ACE_SCOPED_TRACE("DrawToRSCanvas %s-[%d x %d]-[%s]", dfxConfig.ToStringWithSrc().c_str(), pixmap->GetWidth(),
341         pixmap->GetHeight(), dfxConfig.borderRadiusValue_.c_str());
342     RSBrush brush;
343     RSSamplingOptions options;
344     ImagePainterUtils::AddFilter(brush, options, config);
345     auto radii = ImagePainterUtils::ToRSRadius(radiusXY);
346     auto& recordingCanvas = static_cast<Rosen::ExtendRecordingCanvas&>(canvas);
347     std::vector<RSPoint> radius;
348     for (int ii = 0; ii < BORDER_RADIUS_ARRAY_SIZE; ii++) {
349         RSPoint point(radii[ii].GetX(), radii[ii].GetY());
350         radius.emplace_back(point);
351     }
352     recordingCanvas.ClipAdaptiveRoundRect(radius);
353     recordingCanvas.Scale(config.scaleX_, config.scaleY_);
354 
355     RSPoint pointRadius[BORDER_RADIUS_ARRAY_SIZE] = {};
356     for (int i = 0; i < BORDER_RADIUS_ARRAY_SIZE; i++) {
357         pointRadius[i] = radius[i];
358     }
359     Rosen::Drawing::AdaptiveImageInfo rsImageInfo = { static_cast<int32_t>(config.imageFit_),
360         static_cast<int32_t>(config.imageRepeat_), { pointRadius[0], pointRadius[1], pointRadius[2], pointRadius[3] },
361         1.0, 0, 0, 0, static_cast<int32_t>(config.dynamicMode) };
362     rsImageInfo.fitMatrix = ToDrawingMatrix(config.imageMatrix_);
363     rsImageInfo.rotateDegree = CalculateRotateDegree(config.orientation_);
364     recordingCanvas.AttachBrush(brush);
365     if (SystemProperties::GetDebugPixelMapSaveEnabled()) {
366         TAG_LOGI(AceLogTag::ACE_IMAGE, "pixmap, %{public}s-[%{public}d * %{public}d]-[%{public}s][%{public}s]",
367             dfxConfig.ToStringWithSrc().c_str(), pixmap->GetWidth(), pixmap->GetHeight(),
368             dfxConfig.borderRadiusValue_.c_str(), GetDynamicModeString(config.dynamicMode).c_str());
369         pixmap->SavePixelMapToFile(dfxConfig.ToStringWithoutSrc() + "_ToRS_");
370     }
371     NotifyDrawCompletion(dfxConfig.ToStringWithSrc(), pixmap);
372     recordingCanvas.DrawPixelMapWithParm(pixmap->GetPixelMapSharedPtr(), rsImageInfo, options);
373     recordingCanvas.DetachBrush();
374 #endif
375 }
376 
DrawRect(RSCanvas & canvas,const RSRect & dstRect)377 void PixelMapImage::DrawRect(RSCanvas& canvas, const RSRect& dstRect)
378 {
379 #ifndef USE_ROSEN_DRAWING
380 #ifdef ENABLE_ROSEN_BACKEND
381     auto rsCanvas = canvas.GetImpl<RSSkCanvas>();
382     CHECK_NULL_VOID(rsCanvas);
383     auto skCanvas = rsCanvas->ExportSkCanvas();
384     CHECK_NULL_VOID(skCanvas);
385     auto recordingCanvas = static_cast<OHOS::Rosen::RSRecordingCanvas*>(skCanvas);
386     CHECK_NULL_VOID(recordingCanvas);
387     SkPaint paint;
388     SkSamplingOptions option { SkFilterMode::kLinear, SkMipmapMode::kLinear };
389     SkRect dst { dstRect.GetLeft(), dstRect.GetTop(), dstRect.GetRight(), dstRect.GetBottom() };
390 
391     CHECK_NULL_VOID(pixelMap_);
392     auto pixelMap = pixelMap_->GetPixelMapSharedPtr();
393     recordingCanvas->DrawPixelMapRect(pixelMap, dst, option, &paint);
394 #endif
395 #else
396 #ifdef ENABLE_ROSEN_BACKEND
397     auto& recordingCanvas = static_cast<Rosen::ExtendRecordingCanvas&>(canvas);
398     RSBrush brush;
399     RSSamplingOptions options { RSFilterMode::LINEAR, RSMipmapMode::LINEAR };
400     RSRect dst = RSRect(dstRect.GetLeft(), dstRect.GetTop(), dstRect.GetRight(), dstRect.GetBottom());
401 
402     auto pixelMap = pixelMap_->GetPixelMapSharedPtr();
403     CHECK_NULL_VOID(pixelMap);
404     RSRect src = RSRect(0, 0, pixelMap->GetWidth(), pixelMap->GetHeight());
405     recordingCanvas.AttachBrush(brush);
406     recordingCanvas.DrawPixelMapRect(pixelMap, src, dst, options);
407     recordingCanvas.DetachBrush();
408 #endif
409 #endif
410 }
411 
DrawRect(RSCanvas & canvas,const RSRect & srcRect,const RSRect & dstRect)412 void PixelMapImage::DrawRect(RSCanvas& canvas, const RSRect& srcRect, const RSRect& dstRect)
413 {
414     auto pixelMapPtr = GetPixelMap();
415 #ifndef USE_ROSEN_DRAWING
416     auto rsCanvas = canvas.GetImpl<RSSkCanvas>();
417     CHECK_NULL_VOID(rsCanvas);
418     auto skCanvas = rsCanvas->ExportSkCanvas();
419     CHECK_NULL_VOID(skCanvas);
420 
421     auto recordingCanvas = static_cast<OHOS::Rosen::RSRecordingCanvas*>(skCanvas);
422     CHECK_NULL_VOID(recordingCanvas);
423     SkPaint paint;
424     SkSamplingOptions option;
425     SkRect dst { dstRect.GetLeft(), dstRect.GetTop(), dstRect.GetRight(), dstRect.GetBottom() };
426 
427     CHECK_NULL_VOID(pixelMapPtr);
428     auto pixelMap = pixelMapPtr->GetPixelMapSharedPtr();
429     recordingCanvas->DrawPixelMapRect(pixelMap, dst, option, &paint);
430 #else
431     auto& recordingCanvas = static_cast<Rosen::ExtendRecordingCanvas&>(canvas);
432     RSBrush brush;
433     RSSamplingOptions options;
434     RSRect dst = RSRect(dstRect.GetLeft(), dstRect.GetTop(), dstRect.GetRight(), dstRect.GetBottom());
435 
436     CHECK_NULL_VOID(pixelMapPtr);
437     auto pixelMap = pixelMapPtr->GetPixelMapSharedPtr();
438     CHECK_NULL_VOID(pixelMap);
439     RSRect src = RSRect(srcRect.GetLeft(), srcRect.GetTop(), srcRect.GetRight(), srcRect.GetBottom());
440     recordingCanvas.AttachBrush(brush);
441     recordingCanvas.DrawPixelMapRect(pixelMap, src, dst, options);
442     recordingCanvas.DetachBrush();
443 #endif
444 }
445 
Cache(const std::string & key)446 void PixelMapImage::Cache(const std::string& key)
447 {
448     auto pipeline = PipelineBase::GetCurrentContext();
449     CHECK_NULL_VOID(pipeline);
450     auto cache = pipeline->GetImageCache();
451     CHECK_NULL_VOID(cache);
452     cache->CacheImageData(key, MakeRefPtr<PixmapData>(GetPixelMap()));
453 }
454 
QueryFromCache(const std::string & key)455 RefPtr<CanvasImage> PixelMapImage::QueryFromCache(const std::string& key)
456 {
457     auto pipeline = PipelineBase::GetCurrentContext();
458     CHECK_NULL_RETURN(pipeline, nullptr);
459     auto cache = pipeline->GetImageCache();
460     CHECK_NULL_RETURN(cache, nullptr);
461     auto data = DynamicCast<PixmapData>(cache->GetCacheImageData(key));
462     CHECK_NULL_RETURN(data, nullptr);
463     return MakeRefPtr<PixelMapImage>(data->GetPixmap());
464 }
465 
ToDrawingMatrix(const Matrix4 & matrix4)466 RSMatrix PixelMapImage::ToDrawingMatrix(const Matrix4& matrix4)
467 {
468     // Mappings from DrawingMatrix-index to input-index.
469     static const int32_t K_DRAWING_MATRIX_INDEX_TO_MATRIX4_INDEX[] = {
470         0,
471         4,
472         12,
473         1,
474         5,
475         13,
476         3,
477         7,
478         15,
479     };
480 
481     RSMatrix matrix;
482     for (std::size_t i = 0; i < ArraySize(K_DRAWING_MATRIX_INDEX_TO_MATRIX4_INDEX); ++i) {
483         int32_t matrixIndex = K_DRAWING_MATRIX_INDEX_TO_MATRIX4_INDEX[i];
484         if (matrixIndex < matrix4.Count()) {
485             matrix.Set(static_cast<RSMatrix::Index>(i), matrix4[matrixIndex]);
486         } else {
487             matrix.Set(static_cast<RSMatrix::Index>(i), 0.0);
488         }
489     }
490     return matrix;
491 }
492 } // namespace OHOS::Ace::NG
493