1 /*
2  * Copyright (c) 2021-2022 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 "render/rs_image.h"
17 #include <type_traits>
18 
19 #include "common/rs_common_tools.h"
20 #include "common/rs_rect.h"
21 #include "draw/canvas.h"
22 #include "pipeline/rs_recording_canvas.h"
23 #include "pipeline/sk_resource_manager.h"
24 #include "platform/common/rs_log.h"
25 #include "platform/common/rs_system_properties.h"
26 #include "property/rs_properties_painter.h"
27 #include "render/rs_image_cache.h"
28 #include "render/rs_pixel_map_util.h"
29 #include "rs_trace.h"
30 #include "sandbox_utils.h"
31 #include "rs_profiler.h"
32 
33 #ifdef USE_VIDEO_PROCESSING_ENGINE
34 #include "render/rs_colorspace_convert.h"
35 #endif
36 
37 namespace OHOS {
38 namespace Rosen {
39 namespace {
40 constexpr int32_t CORNER_SIZE = 4;
41 constexpr float CENTER_ALIGNED_FACTOR = 2.f;
42 constexpr int32_t DEGREE_NINETY = 90;
43 }
44 
~RSImage()45 RSImage::~RSImage()
46 {}
47 
ReMapPixelMap(std::shared_ptr<Media::PixelMap> & pixelMap)48 inline void ReMapPixelMap(std::shared_ptr<Media::PixelMap>& pixelMap)
49 {
50 #ifdef ROSEN_OHOS
51     if (pixelMap && pixelMap->IsUnMap()) {
52         pixelMap->ReMap();
53     }
54 #endif
55 }
56 
IsEqual(const RSImage & other) const57 bool RSImage::IsEqual(const RSImage& other) const
58 {
59     bool radiusEq = true;
60     for (auto i = 0; i < CORNER_SIZE; i++) {
61         radiusEq &= (radius_[i] == other.radius_[i]);
62     }
63     return (image_ == other.image_) && (pixelMap_ == other.pixelMap_) &&
64            (imageFit_ == other.imageFit_) && (imageRepeat_ == other.imageRepeat_) &&
65            (scale_ == other.scale_) && radiusEq && (compressData_ == other.compressData_);
66 }
67 
HDRConvert(const Drawing::SamplingOptions & sampling,Drawing::Canvas & canvas)68 bool RSImage::HDRConvert(const Drawing::SamplingOptions& sampling, Drawing::Canvas& canvas)
69 {
70 #ifdef USE_VIDEO_PROCESSING_ENGINE
71     // HDR disable
72     if (!RSSystemProperties::GetHDRImageEnable()) {
73         return false;
74     }
75 
76     if (pixelMap_ == nullptr || image_ == nullptr) {
77         RS_LOGE("bhdr pixelMap_ || image_ is nullptr");
78         return false;
79     }
80     if (!pixelMap_->IsHdr()) {
81         RS_LOGD("bhdr pixelMap_ is not hdr");
82         return false;
83     }
84 
85     if (canvas.GetDrawingType() != Drawing::DrawingType::PAINT_FILTER) {
86         RS_LOGE("bhdr GetDrawingType() != Drawing::DrawingType::PAINT_FILTER");
87         return false;
88     }
89 
90     SurfaceBuffer* surfaceBuffer = reinterpret_cast<SurfaceBuffer*>(pixelMap_->GetFd());
91 
92     if (surfaceBuffer == nullptr) {
93         RS_LOGE("bhdr ColorSpaceConvertor surfaceBuffer is nullptr");
94         return false;
95     }
96 
97     Drawing::Matrix matrix;  //Identity Matrix
98     auto sx = dstRect_.GetWidth() / srcRect_.GetWidth();
99     auto sy = dstRect_.GetHeight() / srcRect_.GetHeight();
100     auto tx = dstRect_.GetLeft() - srcRect_.GetLeft() * sx;
101     auto ty = dstRect_.GetTop() - srcRect_.GetTop() * sy;
102     matrix.SetScaleTranslate(sx, sy, tx, ty);
103 
104     auto imageShader = Drawing::ShaderEffect::CreateImageShader(
105         *image_, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, sampling, matrix);
106 
107     sptr<SurfaceBuffer> sfBuffer(surfaceBuffer);
108     RSPaintFilterCanvas& rscanvas = static_cast<RSPaintFilterCanvas&>(canvas);
109     auto targetColorSpace = GRAPHIC_COLOR_GAMUT_SRGB;
110     if (LIKELY(!rscanvas.IsCapture())) {
111         RSColorSpaceConvert::Instance().ColorSpaceConvertor(imageShader, sfBuffer, paint_,
112             targetColorSpace, rscanvas.GetScreenId(), dynamicRangeMode_);
113     } else {
114         RSColorSpaceConvert::Instance().ColorSpaceConvertor(imageShader, sfBuffer, paint_,
115             targetColorSpace, rscanvas.GetScreenId(), DynamicRangeMode::STANDARD);
116     }
117     canvas.AttachPaint(paint_);
118     return true;
119 #else
120     return false;
121 #endif
122 }
123 
CanvasDrawImage(Drawing::Canvas & canvas,const Drawing::Rect & rect,const Drawing::SamplingOptions & samplingOptions,bool isBackground)124 void RSImage::CanvasDrawImage(Drawing::Canvas& canvas, const Drawing::Rect& rect,
125     const Drawing::SamplingOptions& samplingOptions, bool isBackground)
126 {
127     if (canvas.GetRecordingState() && RSSystemProperties::GetDumpUICaptureEnabled() && pixelMap_) {
128         CommonTools::SavePixelmapToFile(pixelMap_, "/data/rsImage_");
129     }
130     if (!isDrawn_ || rect != lastRect_) {
131         UpdateNodeIdToPicture(nodeId_);
132         Drawing::AutoCanvasRestore acr(canvas, HasRadius());
133         if (!canvas.GetOffscreen()) {
134             frameRect_.SetAll(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight());
135         }
136         if (!isBackground) {
137             ApplyImageFit();
138             ApplyCanvasClip(canvas);
139         }
140         if (rotateDegree_ != 0) {
141             canvas.Save();
142             canvas.Rotate(rotateDegree_);
143             auto axis = CalculateByDegree(rect);
144             canvas.Translate(axis.first, axis.second);
145             DrawImageRepeatRect(samplingOptions, canvas);
146             canvas.Restore();
147         } else {
148             DrawImageRepeatRect(samplingOptions, canvas);
149         }
150     } else {
151         Drawing::AutoCanvasRestore acr(canvas, HasRadius());
152         if (pixelMap_ != nullptr && pixelMap_->IsAstc()) {
153             canvas.Save();
154             RSPixelMapUtil::TransformDataSetForAstc(pixelMap_, src_, dst_, canvas);
155         }
156         ReMapPixelMap(pixelMap_);
157         if (image_) {
158             if (!isBackground) {
159                 ApplyCanvasClip(canvas);
160             }
161             if (innerRect_.has_value()) {
162                 canvas.DrawImageNine(image_.get(), innerRect_.value(), dst_, Drawing::FilterMode::LINEAR);
163             } else if (HDRConvert(samplingOptions, canvas)) {
164                 canvas.DrawRect(dst_);
165             } else {
166                 DrawImageWithRotateDegree(canvas, rect, samplingOptions);
167             }
168         }
169         if (pixelMap_ != nullptr && pixelMap_->IsAstc()) {
170             canvas.Restore();
171         }
172     }
173     lastRect_ = rect;
174 }
175 
DrawImageWithRotateDegree(Drawing::Canvas & canvas,const Drawing::Rect & rect,const Drawing::SamplingOptions & samplingOptions)176 void RSImage::DrawImageWithRotateDegree(
177     Drawing::Canvas& canvas, const Drawing::Rect& rect, const Drawing::SamplingOptions& samplingOptions)
178 {
179     Drawing::AutoCanvasRestore acr(canvas, true);
180     if (rotateDegree_ != 0) {
181         canvas.Rotate(rotateDegree_);
182         auto axis = CalculateByDegree(rect);
183         canvas.Translate(axis.first, axis.second);
184     }
185     canvas.DrawImageRect(*image_, src_, dst_, samplingOptions, Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
186 }
187 
188 struct ImageParameter {
189     float ratio;
190     float srcW;
191     float srcH;
192     float frameW;
193     float frameH;
194     float dstW;
195     float dstH;
196 };
197 
ApplyImageFitSwitch(ImageParameter & imageParameter,ImageFit imageFit_,RectF tempRectF)198 RectF ApplyImageFitSwitch(ImageParameter &imageParameter, ImageFit imageFit_, RectF tempRectF)
199 {
200     switch (imageFit_) {
201         case ImageFit::TOP_LEFT:
202             tempRectF.SetAll(0.f, 0.f, imageParameter.srcW, imageParameter.srcH);
203             return tempRectF;
204         case ImageFit::TOP:
205             tempRectF.SetAll((imageParameter.dstW - imageParameter.srcW) / CENTER_ALIGNED_FACTOR, 0.f,
206                 imageParameter.srcW, imageParameter.srcH);
207             return tempRectF;
208         case ImageFit::TOP_RIGHT:
209             tempRectF.SetAll(imageParameter.dstW - imageParameter.srcW, 0.f, imageParameter.srcW, imageParameter.srcH);
210             return tempRectF;
211         case ImageFit::LEFT:
212             tempRectF.SetAll(0.f, (imageParameter.dstH - imageParameter.srcH) / CENTER_ALIGNED_FACTOR,
213                 imageParameter.srcW, imageParameter.srcH);
214             return tempRectF;
215         case ImageFit::CENTER:
216             tempRectF.SetAll((imageParameter.dstW - imageParameter.srcW) / CENTER_ALIGNED_FACTOR,
217                 (imageParameter.dstH - imageParameter.srcH) / CENTER_ALIGNED_FACTOR,
218                 imageParameter.srcW, imageParameter.srcH);
219             return tempRectF;
220         case ImageFit::RIGHT:
221             tempRectF.SetAll(imageParameter.dstW - imageParameter.srcW,
222                 (imageParameter.dstH - imageParameter.srcH) / CENTER_ALIGNED_FACTOR,
223                 imageParameter.srcW, imageParameter.srcH);
224             return tempRectF;
225         case ImageFit::BOTTOM_LEFT:
226             tempRectF.SetAll(0.f, imageParameter.dstH - imageParameter.srcH, imageParameter.srcW, imageParameter.srcH);
227             return tempRectF;
228         case ImageFit::BOTTOM:
229             tempRectF.SetAll((imageParameter.dstW - imageParameter.srcW) / CENTER_ALIGNED_FACTOR,
230                 imageParameter.dstH - imageParameter.srcH, imageParameter.srcW, imageParameter.srcH);
231             return tempRectF;
232         case ImageFit::BOTTOM_RIGHT:
233             tempRectF.SetAll(imageParameter.dstW - imageParameter.srcW, imageParameter.dstH - imageParameter.srcH,
234                 imageParameter.srcW, imageParameter.srcH);
235             return tempRectF;
236         case ImageFit::FILL:
237             break;
238         case ImageFit::NONE:
239             imageParameter.dstW = imageParameter.srcW;
240             imageParameter.dstH = imageParameter.srcH;
241             break;
242         case ImageFit::COVER:
243             imageParameter.dstW = std::max(imageParameter.frameW, imageParameter.frameH * imageParameter.ratio);
244             imageParameter.dstH = std::max(imageParameter.frameH, imageParameter.frameW / imageParameter.ratio);
245             break;
246         case ImageFit::FIT_WIDTH:
247             imageParameter.dstH = imageParameter.frameW / imageParameter.ratio;
248             break;
249         case ImageFit::FIT_HEIGHT:
250             imageParameter.dstW = imageParameter.frameH * imageParameter.ratio;
251             break;
252         case ImageFit::SCALE_DOWN:
253             if (imageParameter.srcW < imageParameter.frameW && imageParameter.srcH < imageParameter.frameH) {
254                 imageParameter.dstW = imageParameter.srcW;
255                 imageParameter.dstH = imageParameter.srcH;
256             } else {
257                 imageParameter.dstW = std::min(imageParameter.frameW, imageParameter.frameH * imageParameter.ratio);
258                 imageParameter.dstH = std::min(imageParameter.frameH, imageParameter.frameW / imageParameter.ratio);
259             }
260             break;
261         case ImageFit::COVER_TOP_LEFT:
262             imageParameter.dstW = std::max(imageParameter.frameW, imageParameter.frameH * imageParameter.ratio);
263             imageParameter.dstH = std::max(imageParameter.frameH, imageParameter.frameW / imageParameter.ratio);
264             tempRectF.SetAll(0, 0, std::ceil(imageParameter.dstW), std::ceil(imageParameter.dstH));
265             return tempRectF;
266         case ImageFit::CONTAIN:
267         default:
268             imageParameter.dstW = std::min(imageParameter.frameW, imageParameter.frameH * imageParameter.ratio);
269             imageParameter.dstH = std::min(imageParameter.frameH, imageParameter.frameW / imageParameter.ratio);
270             break;
271     }
272     constexpr float horizontalAlignmentFactor = 2.f;
273     constexpr float verticalAlignmentFactor = 2.f;
274     tempRectF.SetAll(std::floor((imageParameter.frameW - imageParameter.dstW) / horizontalAlignmentFactor),
275                      std::floor((imageParameter.frameH - imageParameter.dstH) / verticalAlignmentFactor),
276                      std::ceil(imageParameter.dstW),
277                      std::ceil(imageParameter.dstH));
278     return tempRectF;
279 }
280 
ApplyImageFit()281 void RSImage::ApplyImageFit()
282 {
283     if (scale_ == 0) {
284         RS_LOGE("RSImage::ApplyImageFit failed, scale_ is zero ");
285         return;
286     }
287     const float srcW = srcRect_.width_ / scale_;
288     const float srcH = srcRect_.height_ / scale_;
289     float frameW = frameRect_.width_;
290     float frameH = frameRect_.height_;
291     if (rotateDegree_ == DEGREE_NINETY || rotateDegree_ == -DEGREE_NINETY) {
292         std::swap(frameW, frameH);
293     }
294     float dstW = frameW;
295     float dstH = frameH;
296     if (srcH == 0) {
297         RS_LOGE("RSImage::ApplyImageFit failed, srcH is zero ");
298         return;
299     }
300     float ratio = srcW / srcH;
301     if (ratio == 0) {
302         RS_LOGE("RSImage::ApplyImageFit failed, ratio is zero ");
303         return;
304     }
305     ImageParameter imageParameter;
306     imageParameter.ratio = ratio;
307     imageParameter.srcW = srcW;
308     imageParameter.srcH = srcH;
309     imageParameter.frameW = frameW;
310     imageParameter.frameH = frameH;
311     imageParameter.dstW = dstW;
312     imageParameter.dstH = dstH;
313     RectF tempRectF = dstRect_;
314     dstRect_ = ApplyImageFitSwitch(imageParameter, imageFit_, tempRectF);
315 }
316 
SetImageRotateDegree(int32_t degree)317 void RSImage::SetImageRotateDegree(int32_t degree)
318 {
319     rotateDegree_ = degree;
320 }
321 
CalculateByDegree(const Drawing::Rect & rect)322 std::pair<float, float> RSImage::CalculateByDegree(const Drawing::Rect& rect)
323 {
324     if (rotateDegree_ == DEGREE_NINETY) {
325         return { 0, -rect.GetWidth() };
326     } else if (rotateDegree_ == -DEGREE_NINETY) {
327         return { -rect.GetHeight(), 0 };
328     } else {
329         return { -rect.GetWidth(), -rect.GetHeight() };
330     }
331 }
332 
GetImageFit()333 ImageFit RSImage::GetImageFit()
334 {
335     return imageFit_;
336 }
337 
GetAdaptiveImageInfoWithCustomizedFrameRect(const Drawing::Rect & frameRect) const338 Drawing::AdaptiveImageInfo RSImage::GetAdaptiveImageInfoWithCustomizedFrameRect(const Drawing::Rect& frameRect) const
339 {
340     Drawing::AdaptiveImageInfo imageInfo = {
341         .fitNum = static_cast<int32_t>(imageFit_),
342         .repeatNum = static_cast<int32_t>(imageRepeat_),
343         .radius = { radius_[0], radius_[1], radius_[2], radius_[3] },
344         .scale = scale_,
345         .uniqueId = 0,
346         .width = 0,
347         .height = 0,
348         .dynamicRangeMode = dynamicRangeMode_,
349         .rotateDegree = rotateDegree_,
350         .frameRect = frameRect,
351     };
352     return imageInfo;
353 }
354 
GetDstRect()355 RectF RSImage::GetDstRect()
356 {
357     return dstRect_;
358 }
359 
SetFrameRect(RectF frameRect)360 void RSImage::SetFrameRect(RectF frameRect)
361 {
362     frameRect_ = frameRect;
363 }
364 
HasRadius() const365 bool RSImage::HasRadius() const
366 {
367     return hasRadius_;
368 }
369 
ApplyCanvasClip(Drawing::Canvas & canvas)370 void RSImage::ApplyCanvasClip(Drawing::Canvas& canvas)
371 {
372     if (!HasRadius()) {
373         return;
374     }
375     auto dstRect = dstRect_;
376     if (rotateDegree_ == DEGREE_NINETY || rotateDegree_ == -DEGREE_NINETY) {
377         dstRect = RectF(dstRect_.GetTop(), dstRect_.GetLeft(), dstRect_.GetHeight(), dstRect_.GetWidth());
378     }
379     auto rect = (imageRepeat_ == ImageRepeat::NO_REPEAT) ? dstRect.IntersectRect(frameRect_) : frameRect_;
380     Drawing::RoundRect rrect(RSPropertiesPainter::Rect2DrawingRect(rect), radius_);
381     canvas.ClipRoundRect(rrect, Drawing::ClipOp::INTERSECT, true);
382 }
383 
384 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
PixelFormatToCompressedType(Media::PixelFormat pixelFormat)385 static Drawing::CompressedType PixelFormatToCompressedType(Media::PixelFormat pixelFormat)
386 {
387     switch (pixelFormat) {
388         case Media::PixelFormat::ASTC_4x4: return Drawing::CompressedType::ASTC_RGBA8_4x4;
389         case Media::PixelFormat::ASTC_6x6: return Drawing::CompressedType::ASTC_RGBA8_6x6;
390         case Media::PixelFormat::ASTC_8x8: return Drawing::CompressedType::ASTC_RGBA8_8x8;
391         case Media::PixelFormat::UNKNOWN:
392         default: return Drawing::CompressedType::NoneType;
393     }
394 }
395 
ColorSpaceToDrawingColorSpace(ColorManager::ColorSpaceName colorSpaceName)396 static std::shared_ptr<Drawing::ColorSpace> ColorSpaceToDrawingColorSpace(ColorManager::ColorSpaceName
397  colorSpaceName)
398 {
399     switch (colorSpaceName) {
400         case ColorManager::ColorSpaceName::DISPLAY_P3:
401             return Drawing::ColorSpace::CreateRGB(
402                 Drawing::CMSTransferFuncType::SRGB, Drawing::CMSMatrixType::DCIP3);
403         case ColorManager::ColorSpaceName::LINEAR_SRGB:
404             return Drawing::ColorSpace::CreateSRGBLinear();
405         case ColorManager::ColorSpaceName::SRGB:
406             return Drawing::ColorSpace::CreateSRGB();
407         default:
408             return Drawing::ColorSpace::CreateSRGB();
409     }
410 }
411 #endif
412 
UploadGpu(Drawing::Canvas & canvas)413 void RSImage::UploadGpu(Drawing::Canvas& canvas)
414 {
415 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
416     if (compressData_) {
417         auto cache = RSImageCache::Instance().GetRenderDrawingImageCacheByPixelMapId(uniqueId_, gettid());
418         std::lock_guard<std::mutex> lock(mutex_);
419         if (cache) {
420             image_ = cache;
421         } else {
422             if (canvas.GetGPUContext() == nullptr) {
423                 return;
424             }
425             RS_TRACE_NAME("make compress img");
426             Media::ImageInfo imageInfo;
427             pixelMap_->GetImageInfo(imageInfo);
428             Media::Size realSize;
429             pixelMap_->GetAstcRealSize(realSize);
430             auto image = std::make_shared<Drawing::Image>();
431             std::shared_ptr<Drawing::ColorSpace> colorSpace =
432                 ColorSpaceToDrawingColorSpace(pixelMap_->InnerGetGrColorSpace().GetColorSpaceName());
433             bool result = image->BuildFromCompressed(*canvas.GetGPUContext(), compressData_,
434                 static_cast<int>(realSize.width), static_cast<int>(realSize.height),
435                 PixelFormatToCompressedType(imageInfo.pixelFormat), colorSpace);
436             if (result) {
437                 image_ = image;
438                 SKResourceManager::Instance().HoldResource(image);
439                 RSImageCache::Instance().CacheRenderDrawingImageByPixelMapId(uniqueId_, image, gettid());
440             } else {
441                 RS_LOGE("make astc image %{public}d (%{public}d, %{public}d) failed",
442                     (int)uniqueId_, (int)srcRect_.width_, (int)srcRect_.height_);
443             }
444             compressData_ = nullptr;
445         }
446         return;
447     }
448     if (isYUVImage_) {
449         ProcessYUVImage(canvas.GetGPUContext());
450     }
451 #endif
452 }
453 
DrawImageRepeatRect(const Drawing::SamplingOptions & samplingOptions,Drawing::Canvas & canvas)454 void RSImage::DrawImageRepeatRect(const Drawing::SamplingOptions& samplingOptions, Drawing::Canvas& canvas)
455 {
456     ReMapPixelMap(pixelMap_);
457     int minX = 0;
458     int minY = 0;
459     int maxX = 0;
460     int maxY = 0;
461     CalcRepeatBounds(minX, maxX, minY, maxY);
462     // draw repeat rect
463     ConvertPixelMapToDrawingImage();
464     UploadGpu(canvas);
465     bool hdrImageDraw = HDRConvert(samplingOptions, canvas);
466     src_ = RSPropertiesPainter::Rect2DrawingRect(srcRect_);
467     bool isAstc = pixelMap_ != nullptr && pixelMap_->IsAstc();
468     for (int i = minX; i <= maxX; ++i) {
469         auto left = dstRect_.left_ + i * dstRect_.width_;
470         auto right = left + dstRect_.width_;
471         for (int j = minY; j <= maxY; ++j) {
472             auto top = dstRect_.top_ + j * dstRect_.height_;
473             dst_ = Drawing::Rect(left, top, right, top + dstRect_.height_);
474             if (isAstc) {
475                 canvas.Save();
476                 RSPixelMapUtil::TransformDataSetForAstc(pixelMap_, src_, dst_, canvas);
477             }
478             if (image_) {
479                 DrawImageOnCanvas(samplingOptions, canvas, hdrImageDraw);
480             }
481             if (isAstc) {
482                 canvas.Restore();
483             }
484         }
485     }
486     if (imageRepeat_ == ImageRepeat::NO_REPEAT) {
487         isDrawn_ = true;
488     }
489 }
490 
CalcRepeatBounds(int & minX,int & maxX,int & minY,int & maxY)491 void RSImage::CalcRepeatBounds(int& minX, int& maxX, int& minY, int& maxY)
492 {
493     float left = frameRect_.left_;
494     float right = frameRect_.GetRight();
495     float top = frameRect_.top_;
496     float bottom = frameRect_.GetBottom();
497     // calculate REPEAT_XY
498     float eps = 0.01; // set epsilon
499     auto repeat_x = ImageRepeat::REPEAT_X;
500     auto repeat_y = ImageRepeat::REPEAT_Y;
501     if (rotateDegree_ == DEGREE_NINETY || rotateDegree_ == -DEGREE_NINETY) {
502         std::swap(right, bottom);
503         std::swap(repeat_x, repeat_y);
504     }
505     if (repeat_x == imageRepeat_ || ImageRepeat::REPEAT == imageRepeat_) {
506         while (dstRect_.left_ + minX * dstRect_.width_ > left + eps) {
507             --minX;
508         }
509         while (dstRect_.left_ + maxX * dstRect_.width_ < right - eps) {
510             ++maxX;
511         }
512     }
513     if (repeat_y == imageRepeat_ || ImageRepeat::REPEAT == imageRepeat_) {
514         while (dstRect_.top_ + minY * dstRect_.height_ > top + eps) {
515             --minY;
516         }
517         while (dstRect_.top_ + maxY * dstRect_.height_ < bottom - eps) {
518             ++maxY;
519         }
520     }
521 }
522 
DrawImageOnCanvas(const Drawing::SamplingOptions & samplingOptions,Drawing::Canvas & canvas,const bool hdrImageDraw)523 void RSImage::DrawImageOnCanvas(
524     const Drawing::SamplingOptions& samplingOptions, Drawing::Canvas& canvas, const bool hdrImageDraw)
525 {
526     if (canvas.GetTotalMatrix().HasPerspective()) {
527         // In case of perspective transformation, make dstRect 1px outset to anti-alias
528         dst_.MakeOutset(1, 1);
529     }
530     if (innerRect_.has_value()) {
531         canvas.DrawImageNine(image_.get(), innerRect_.value(), dst_, Drawing::FilterMode::LINEAR);
532     } else if (hdrImageDraw) {
533         canvas.DrawRect(dst_);
534     } else {
535         canvas.DrawImageRect(
536             *image_, src_, dst_, samplingOptions, Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
537     }
538 }
539 
SetCompressData(const std::shared_ptr<Drawing::Data> data,const uint32_t id,const int width,const int height)540 void RSImage::SetCompressData(
541     const std::shared_ptr<Drawing::Data> data, const uint32_t id, const int width, const int height)
542 {
543 #ifdef RS_ENABLE_GL
544     if (RSSystemProperties::GetGpuApiType() != GpuApiType::OPENGL) {
545         return;
546     }
547     compressData_ = data;
548     if (compressData_) {
549         srcRect_.SetAll(0.0, 0.0, width, height);
550         GenUniqueId(image_ ? image_->GetUniqueID() : id);
551         image_ = nullptr;
552     }
553 #endif
554 }
555 
556 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined (RS_ENABLE_VK))
SetCompressData(const std::shared_ptr<Drawing::Data> compressData)557 void RSImage::SetCompressData(const std::shared_ptr<Drawing::Data> compressData)
558 {
559     isDrawn_ = false;
560     compressData_ = compressData;
561     canPurgeShareMemFlag_ = CanPurgeFlag::DISABLED;
562 }
563 #endif
564 
SetImageFit(int fitNum)565 void RSImage::SetImageFit(int fitNum)
566 {
567     imageFit_ = static_cast<ImageFit>(fitNum);
568 }
569 
SetImageRepeat(int repeatNum)570 void RSImage::SetImageRepeat(int repeatNum)
571 {
572     imageRepeat_ = static_cast<ImageRepeat>(repeatNum);
573 }
574 
SetRadius(const std::vector<Drawing::Point> & radius)575 void RSImage::SetRadius(const std::vector<Drawing::Point>& radius)
576 {
577     hasRadius_ = false;
578     for (auto i = 0; i < CORNER_SIZE; i++) {
579         radius_[i] = radius[i];
580         hasRadius_ = hasRadius_ || !radius_[i].IsZero();
581     }
582 }
583 
SetScale(double scale)584 void RSImage::SetScale(double scale)
585 {
586     if (scale > 0.0) {
587         scale_ = scale;
588     }
589 }
590 
SetNodeId(NodeId nodeId)591 void RSImage::SetNodeId(NodeId nodeId)
592 {
593     nodeId_ = nodeId;
594 }
595 
SetPaint(Drawing::Paint paint)596 void RSImage::SetPaint(Drawing::Paint paint)
597 {
598     paint_ = paint;
599 }
600 
SetDynamicRangeMode(uint32_t dynamicRangeMode)601 void RSImage::SetDynamicRangeMode(uint32_t dynamicRangeMode)
602 {
603     dynamicRangeMode_ = dynamicRangeMode;
604 }
605 
606 #ifdef ROSEN_OHOS
UnmarshallingIdAndSize(Parcel & parcel,uint64_t & uniqueId,int & width,int & height)607 static bool UnmarshallingIdAndSize(Parcel& parcel, uint64_t& uniqueId, int& width, int& height)
608 {
609     if (!RSMarshallingHelper::Unmarshalling(parcel, uniqueId)) {
610         RS_LOGE("RSImage::Unmarshalling uniqueId fail");
611         return false;
612     }
613     RS_PROFILER_PATCH_NODE_ID(parcel, uniqueId);
614     if (!RSMarshallingHelper::Unmarshalling(parcel, width)) {
615         RS_LOGE("RSImage::Unmarshalling width fail");
616         return false;
617     }
618     if (!RSMarshallingHelper::Unmarshalling(parcel, height)) {
619         RS_LOGE("RSImage::Unmarshalling height fail");
620         return false;
621     }
622     return true;
623 }
624 
UnmarshallingCompressData(Parcel & parcel,bool skipData,std::shared_ptr<Drawing::Data> & compressData)625 static bool UnmarshallingCompressData(Parcel& parcel, bool skipData, std::shared_ptr<Drawing::Data>& compressData)
626 {
627     if (skipData) {
628         if (!RSMarshallingHelper::SkipData(parcel)) {
629             RS_LOGE("RSImage::Unmarshalling SkipData fail");
630             return false;
631         }
632     } else {
633         if (!RSMarshallingHelper::UnmarshallingWithCopy(parcel, compressData)) {
634             RS_LOGE("RSImage::Unmarshalling UnmarshallingWithCopy Data fail");
635             return false;
636         }
637     }
638     return true;
639 }
640 
Marshalling(Parcel & parcel) const641 bool RSImage::Marshalling(Parcel& parcel) const
642 {
643     int imageFit = static_cast<int>(imageFit_);
644     int imageRepeat = static_cast<int>(imageRepeat_);
645 
646     std::lock_guard<std::mutex> lock(mutex_);
647     auto image = image_;
648     auto compressData = compressData_;
649     if (image && image->IsTextureBacked()) {
650         image = nullptr;
651         ROSEN_LOGE("RSImage::Marshalling skip texture image");
652     }
653     RS_PROFILER_MARSHAL_DRAWINGIMAGE(image, compressData);
654     bool success = RSMarshallingHelper::Marshalling(parcel, uniqueId_) &&
655                    RSMarshallingHelper::Marshalling(parcel, static_cast<int>(srcRect_.width_)) &&
656                    RSMarshallingHelper::Marshalling(parcel, static_cast<int>(srcRect_.height_)) &&
657                    RSMarshallingHelper::Marshalling(parcel, nodeId_) &&
658                    parcel.WriteBool(pixelMap_ == nullptr) &&
659                    RSMarshallingHelper::Marshalling(parcel, image) &&
660                    RSMarshallingHelper::Marshalling(parcel, pixelMap_) &&
661                    RSMarshallingHelper::Marshalling(parcel, compressData) &&
662                    RSMarshallingHelper::Marshalling(parcel, imageFit) &&
663                    RSMarshallingHelper::Marshalling(parcel, imageRepeat) &&
664                    RSMarshallingHelper::Marshalling(parcel, radius_) &&
665                    RSMarshallingHelper::Marshalling(parcel, scale_) &&
666                    RSMarshallingHelper::Marshalling(parcel, rotateDegree_);
667     return success;
668 }
669 
Unmarshalling(Parcel & parcel)670 RSImage* RSImage::Unmarshalling(Parcel& parcel)
671 {
672     uint64_t uniqueId;
673     int width;
674     int height;
675     NodeId nodeId;
676     if (!UnmarshalIdSizeAndNodeId(parcel, uniqueId, width, height, nodeId)) {
677         return nullptr;
678     }
679     bool useSkImage;
680     std::shared_ptr<Drawing::Image> img;
681     std::shared_ptr<Media::PixelMap> pixelMap;
682     void* imagepixelAddr = nullptr;
683     if (!UnmarshallingDrawingImageAndPixelMap(parcel, uniqueId, useSkImage, img, pixelMap, imagepixelAddr)) {
684         return nullptr;
685     }
686     std::shared_ptr<Drawing::Data> compressData;
687     bool skipData = img != nullptr || !useSkImage;
688     if (!UnmarshallingCompressData(parcel, skipData, compressData)) {
689         return nullptr;
690     }
691     int fitNum;
692     int repeatNum;
693     std::vector<Drawing::Point> radius(CORNER_SIZE);
694     double scale;
695     int32_t degree = 0;
696     if (!UnmarshalImageProperties(parcel, fitNum, repeatNum, radius, scale, degree)) {
697         return nullptr;
698     }
699     RSImage* rsImage = new RSImage();
700     rsImage->SetImage(img);
701     rsImage->SetImagePixelAddr(imagepixelAddr);
702     rsImage->SetCompressData(compressData, uniqueId, width, height);
703     rsImage->SetPixelMap(pixelMap);
704     rsImage->SetImageFit(fitNum);
705     rsImage->SetImageRepeat(repeatNum);
706     rsImage->SetRadius(radius);
707     rsImage->SetScale(scale);
708     rsImage->SetNodeId(nodeId);
709     rsImage->SetImageRotateDegree(degree);
710     ProcessImageAfterCreation(rsImage, uniqueId, useSkImage, pixelMap);
711     return rsImage;
712 }
713 
UnmarshalIdSizeAndNodeId(Parcel & parcel,uint64_t & uniqueId,int & width,int & height,NodeId & nodeId)714 bool RSImage::UnmarshalIdSizeAndNodeId(Parcel& parcel, uint64_t& uniqueId, int& width, int& height, NodeId& nodeId)
715 {
716     if (!UnmarshallingIdAndSize(parcel, uniqueId, width, height)) {
717         RS_LOGE("RSImage::Unmarshalling UnmarshallingIdAndSize fail");
718         return false;
719     }
720     if (!RSMarshallingHelper::Unmarshalling(parcel, nodeId)) {
721         RS_LOGE("RSImage::Unmarshalling nodeId fail");
722         return false;
723     }
724     RS_PROFILER_PATCH_NODE_ID(parcel, nodeId);
725     return true;
726 }
727 
UnmarshalImageProperties(Parcel & parcel,int & fitNum,int & repeatNum,std::vector<Drawing::Point> & radius,double & scale,int32_t & degree)728 bool RSImage::UnmarshalImageProperties(
729     Parcel& parcel, int& fitNum, int& repeatNum, std::vector<Drawing::Point>& radius, double& scale, int32_t& degree)
730 {
731     if (!RSMarshallingHelper::Unmarshalling(parcel, fitNum)) {
732         RS_LOGE("RSImage::Unmarshalling fitNum fail");
733         return false;
734     }
735 
736     if (!RSMarshallingHelper::Unmarshalling(parcel, repeatNum)) {
737         RS_LOGE("RSImage::Unmarshalling repeatNum fail");
738         return false;
739     }
740 
741     if (!RSMarshallingHelper::Unmarshalling(parcel, radius)) {
742         RS_LOGE("RSImage::Unmarshalling radius fail");
743         return false;
744     }
745 
746     if (!RSMarshallingHelper::Unmarshalling(parcel, scale)) {
747         RS_LOGE("RSImage::Unmarshalling scale fail");
748         return false;
749     }
750 
751     if (!RSMarshallingHelper::Unmarshalling(parcel, degree)) {
752         RS_LOGE("RSImage::Unmarshalling rotateDegree fail");
753         return false;
754     }
755 
756     return true;
757 }
758 
ProcessImageAfterCreation(RSImage * rsImage,const uint64_t uniqueId,const bool useSkImage,const std::shared_ptr<Media::PixelMap> & pixelMap)759 void RSImage::ProcessImageAfterCreation(
760     RSImage* rsImage, const uint64_t uniqueId, const bool useSkImage, const std::shared_ptr<Media::PixelMap>& pixelMap)
761 {
762     rsImage->uniqueId_ = uniqueId;
763     rsImage->MarkRenderServiceImage();
764     RSImageBase::IncreaseCacheRefCount(uniqueId, useSkImage, pixelMap);
765 #if defined(ROSEN_OHOS) && defined(RS_ENABLE_GL) && defined(RS_ENABLE_PARALLEL_UPLOAD)
766     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
767 #if defined(RS_ENABLE_UNI_RENDER)
768         if (pixelMap != nullptr && pixelMap->GetAllocatorType() != Media::AllocatorType::DMA_ALLOC) {
769             rsImage->ConvertPixelMapToDrawingImage(true);
770         }
771 #endif
772     }
773 #endif
774 }
775 #endif
776 } // namespace Rosen
777 } // namespace OHOS
778