• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "pipeline/rs_recording_canvas.h"
22 #include "pipeline/sk_resource_manager.h"
23 #include "platform/common/rs_log.h"
24 #include "platform/common/rs_system_properties.h"
25 #include "property/rs_properties_painter.h"
26 #include "render/rs_image_cache.h"
27 #include "render/rs_pixel_map_util.h"
28 #include "rs_trace.h"
29 #include "sandbox_utils.h"
30 #include "rs_profiler.h"
31 
32 #ifdef USE_VIDEO_PROCESSING_ENGINE
33 #include "render/rs_colorspace_convert.h"
34 #endif
35 
36 namespace OHOS {
37 namespace Rosen {
38 namespace {
39 constexpr int32_t CORNER_SIZE = 4;
40 constexpr float CENTER_ALIGNED_FACTOR = 2.f;
41 constexpr int32_t DEGREE_NINETY = 90;
42 }
43 
~RSImage()44 RSImage::~RSImage()
45 {}
46 
IsEqual(const RSImage & other) const47 bool RSImage::IsEqual(const RSImage& other) const
48 {
49     bool radiusEq = true;
50     for (auto i = 0; i < CORNER_SIZE; i++) {
51         radiusEq &= (radius_[i] == other.radius_[i]);
52     }
53     return (image_ == other.image_) && (pixelMap_ == other.pixelMap_) &&
54            (imageFit_ == other.imageFit_) && (imageRepeat_ == other.imageRepeat_) &&
55            (scale_ == other.scale_) && radiusEq && (compressData_ == other.compressData_);
56 }
57 
CanDrawRectWithImageShader(const Drawing::Canvas & canvas) const58 bool RSImage::CanDrawRectWithImageShader(const Drawing::Canvas& canvas) const
59 {
60     return canvas.GetTotalMatrix().HasPerspective() && imageRepeat_ == ImageRepeat::NO_REPEAT && image_ != nullptr;
61 }
62 
GenerateImageShaderForDrawRect(const Drawing::Canvas & canvas,const Drawing::SamplingOptions & sampling) const63 std::shared_ptr<Drawing::ShaderEffect> RSImage::GenerateImageShaderForDrawRect(
64     const Drawing::Canvas& canvas, const Drawing::SamplingOptions& sampling) const
65 {
66     if (!CanDrawRectWithImageShader(canvas)) {
67         return nullptr;
68     }
69 
70     if (Drawing::IsScalarAlmostEqual(0, src_.GetWidth()) || Drawing::IsScalarAlmostEqual(0, src_.GetHeight())) {
71         RS_LOGW("RSImage::GenerateImageShaderForDrawRect src_ width or height is equal 0");
72         return nullptr;
73     }
74 
75     Drawing::Matrix matrix;
76     auto sx = dstRect_.GetWidth() / src_.GetWidth();
77     auto sy = dstRect_.GetHeight() / src_.GetHeight();
78     auto tx = dstRect_.GetLeft() - src_.GetLeft() * sx;
79     auto ty = dstRect_.GetTop() - src_.GetTop() * sy;
80     matrix.SetScaleTranslate(sx, sy, tx, ty);
81 
82     return Drawing::ShaderEffect::CreateImageShader(
83         *image_, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, sampling, matrix);
84 }
85 
HDRConvert(const Drawing::SamplingOptions & sampling,Drawing::Canvas & canvas)86 bool RSImage::HDRConvert(const Drawing::SamplingOptions& sampling, Drawing::Canvas& canvas)
87 {
88 #ifdef USE_VIDEO_PROCESSING_ENGINE
89     if (pixelMap_ == nullptr || image_ == nullptr) {
90         RS_LOGE("bhdr pixelMap_ || image_ is nullptr");
91         return false;
92     }
93     RS_LOGD("RSImage::HDRConvert HDRDraw pixelMap_ IsHdr: %{public}d", pixelMap_->IsHdr());
94     if (!pixelMap_->IsHdr()) {
95         return false;
96     }
97 
98     if (canvas.GetDrawingType() != Drawing::DrawingType::PAINT_FILTER) {
99         RS_LOGE("bhdr GetDrawingType() != Drawing::DrawingType::PAINT_FILTER");
100         return false;
101     }
102 
103     SurfaceBuffer* surfaceBuffer = reinterpret_cast<SurfaceBuffer*>(pixelMap_->GetFd());
104 
105     if (surfaceBuffer == nullptr) {
106         RS_LOGE("bhdr ColorSpaceConvertor surfaceBuffer is nullptr");
107         return false;
108     }
109 
110     Drawing::Matrix matrix;  //Identity Matrix
111     auto sx = dstRect_.GetWidth() / srcRect_.GetWidth();
112     auto sy = dstRect_.GetHeight() / srcRect_.GetHeight();
113     auto tx = dstRect_.GetLeft() - srcRect_.GetLeft() * sx;
114     auto ty = dstRect_.GetTop() - srcRect_.GetTop() * sy;
115     matrix.SetScaleTranslate(sx, sy, tx, ty);
116 
117     auto imageShader = Drawing::ShaderEffect::CreateImageShader(
118         *image_, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, sampling, matrix);
119 
120     sptr<SurfaceBuffer> sfBuffer(surfaceBuffer);
121     RSPaintFilterCanvas& rscanvas = static_cast<RSPaintFilterCanvas&>(canvas);
122     auto targetColorSpace = GRAPHIC_COLOR_GAMUT_SRGB;
123     auto shotType = rscanvas.GetScreenshotType();
124     bool isSDRCapture = shotType == RSPaintFilterCanvas::ScreenshotType::SDR_SCREENSHOT ||
125         shotType == RSPaintFilterCanvas::ScreenshotType::SDR_WINDOWSHOT;
126     if (LIKELY(!rscanvas.IsOnMultipleScreen() && !isSDRCapture && rscanvas.GetHdrOn() &&
127         RSSystemProperties::GetHdrImageEnabled())) {
128         RSColorSpaceConvert::Instance().ColorSpaceConvertor(imageShader, sfBuffer, paint_, targetColorSpace,
129             rscanvas.GetScreenId(), dynamicRangeMode_, rscanvas.GetHDRProperties());
130     } else {
131         RSColorSpaceConvert::Instance().ColorSpaceConvertor(imageShader, sfBuffer, paint_, targetColorSpace,
132             rscanvas.GetScreenId(), DynamicRangeMode::STANDARD, rscanvas.GetHDRProperties());
133     }
134     canvas.AttachPaint(paint_);
135     // Avoid cross-thread destruction
136     paint_.SetShaderEffect(nullptr);
137     return true;
138 #else
139     return false;
140 #endif
141 }
142 
CanvasDrawImage(Drawing::Canvas & canvas,const Drawing::Rect & rect,const Drawing::SamplingOptions & samplingOptions,bool isBackground)143 void RSImage::CanvasDrawImage(Drawing::Canvas& canvas, const Drawing::Rect& rect,
144     const Drawing::SamplingOptions& samplingOptions, bool isBackground)
145 {
146 #ifdef ROSEN_OHOS
147     if (canvas.GetRecordingState() && RSSystemProperties::GetDumpUICaptureEnabled() && pixelMap_) {
148         CommonTools::SavePixelmapToFile(pixelMap_, "/data/rsImage_");
149     }
150 #endif
151     isFitMatrixValid_ = !isBackground && imageFit_ == ImageFit::MATRIX &&
152                                 fitMatrix_.has_value() && !fitMatrix_.value().IsIdentity();
153     isOrientationValid_ = orientationFit_ != OrientationFit::NONE;
154 #ifdef ROSEN_OHOS
155     auto pixelMapUseCountGuard = PixelMapUseCountGuard(pixelMap_, IsPurgeable());
156     DePurge();
157 #endif
158     if (!isDrawn_ || rect != lastRect_) {
159         UpdateNodeIdToPicture(nodeId_);
160         bool needCanvasRestore = HasRadius() || isFitMatrixValid_ || (rotateDegree_ != 0);
161         Drawing::AutoCanvasRestore acr(canvas, needCanvasRestore);
162         if (!canvas.GetOffscreen()) {
163             frameRect_.SetAll(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight());
164         }
165         if (!isBackground) {
166             ApplyImageFit();
167             ApplyCanvasClip(canvas);
168         }
169         if (isFitMatrixValid_) {
170             canvas.ConcatMatrix(fitMatrix_.value());
171         }
172         if (rotateDegree_ != 0) {
173             canvas.Rotate(rotateDegree_);
174             auto axis = CalculateByDegree(rect);
175             canvas.Translate(axis.first, axis.second);
176         }
177         DrawImageRepeatRect(samplingOptions, canvas);
178     } else {
179         bool needCanvasRestore = HasRadius() || (pixelMap_ != nullptr && pixelMap_->IsAstc()) ||
180                                  isFitMatrixValid_ ;
181         Drawing::AutoCanvasRestore acr(canvas, needCanvasRestore);
182         if (pixelMap_ != nullptr && pixelMap_->IsAstc()) {
183             RSPixelMapUtil::TransformDataSetForAstc(pixelMap_, src_, dst_, canvas, imageFit_);
184         }
185         if (isFitMatrixValid_) {
186             canvas.ConcatMatrix(fitMatrix_.value());
187         }
188 
189         if (image_) {
190             if (!isBackground) {
191                 ApplyCanvasClip(canvas);
192             }
193             if (innerRect_.has_value()) {
194                 canvas.DrawImageNine(image_.get(), innerRect_.value(), dst_, Drawing::FilterMode::LINEAR);
195             } else if (HDRConvert(samplingOptions, canvas)) {
196                 canvas.DrawRect(dst_);
197             } else {
198                 DrawImageRect(canvas, rect, samplingOptions);
199             }
200         }
201     }
202     lastRect_ = rect;
203 }
204 
ApplyImageOrientation(Drawing::Canvas & canvas)205 void RSImage::ApplyImageOrientation(Drawing::Canvas& canvas)
206 {
207     switch (orientationFit_) {
208         case OrientationFit::VERTICAL_FLIP:
209             canvas.Scale(1, -1);
210             canvas.Translate(0, -(dst_.GetBottom() + dst_.GetTop()));
211             return;
212         case OrientationFit::HORIZONTAL_FLIP:
213             canvas.Scale(-1, 1);
214             canvas.Translate(-(dst_.GetRight() + dst_.GetLeft()), 0);
215             return;
216         default:
217             return;
218     }
219 }
220 
DrawImageRect(Drawing::Canvas & canvas,const Drawing::Rect & rect,const Drawing::SamplingOptions & samplingOptions)221 void RSImage::DrawImageRect(
222     Drawing::Canvas& canvas, const Drawing::Rect& rect, const Drawing::SamplingOptions& samplingOptions)
223 {
224     bool needCanvasRestore = rotateDegree_ || isOrientationValid_;
225     Drawing::AutoCanvasRestore acr(canvas, needCanvasRestore);
226     if (rotateDegree_ != 0) {
227         canvas.Rotate(rotateDegree_);
228         auto axis = CalculateByDegree(rect);
229         canvas.Translate(axis.first, axis.second);
230     }
231 
232     if (isOrientationValid_) {
233         ApplyImageOrientation(canvas);
234     }
235     auto imageShader = GenerateImageShaderForDrawRect(canvas, samplingOptions);
236     if (imageShader != nullptr) {
237         DrawImageShaderRectOnCanvas(canvas, imageShader);
238         return;
239     }
240 
241     if (imageRepeat_ == ImageRepeat::NO_REPEAT && isFitMatrixValid_ &&
242         (fitMatrix_->Get(Drawing::Matrix::Index::SKEW_X) != 0 ||
243         fitMatrix_->Get(Drawing::Matrix::Index::SKEW_Y) != 0 ||
244         fitMatrix_->HasPerspective())) {
245         DrawImageWithFirMatrixRotateOnCanvas(samplingOptions, canvas);
246         return;
247     }
248     canvas.DrawImageRect(*image_, src_, dst_, samplingOptions, Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
249 }
250 
251 struct ImageParameter {
252     float ratio;
253     float srcW;
254     float srcH;
255     float frameW;
256     float frameH;
257     float dstW;
258     float dstH;
259 };
260 
ApplyImageFitSwitch(ImageParameter & imageParameter,ImageFit imageFit_,RectF tempRectF)261 RectF ApplyImageFitSwitch(ImageParameter &imageParameter, ImageFit imageFit_, RectF tempRectF)
262 {
263     switch (imageFit_) {
264         case ImageFit::MATRIX:
265             tempRectF.SetAll(0.f, 0.f, imageParameter.srcW, imageParameter.srcH);
266             return tempRectF;
267         case ImageFit::TOP_LEFT:
268             tempRectF.SetAll(0.f, 0.f, imageParameter.srcW, imageParameter.srcH);
269             return tempRectF;
270         case ImageFit::TOP:
271             tempRectF.SetAll((imageParameter.dstW - imageParameter.srcW) / CENTER_ALIGNED_FACTOR, 0.f,
272                 imageParameter.srcW, imageParameter.srcH);
273             return tempRectF;
274         case ImageFit::TOP_RIGHT:
275             tempRectF.SetAll(imageParameter.dstW - imageParameter.srcW, 0.f, imageParameter.srcW, imageParameter.srcH);
276             return tempRectF;
277         case ImageFit::LEFT:
278             tempRectF.SetAll(0.f, (imageParameter.dstH - imageParameter.srcH) / CENTER_ALIGNED_FACTOR,
279                 imageParameter.srcW, imageParameter.srcH);
280             return tempRectF;
281         case ImageFit::CENTER:
282             tempRectF.SetAll((imageParameter.dstW - imageParameter.srcW) / CENTER_ALIGNED_FACTOR,
283                 (imageParameter.dstH - imageParameter.srcH) / CENTER_ALIGNED_FACTOR,
284                 imageParameter.srcW, imageParameter.srcH);
285             return tempRectF;
286         case ImageFit::RIGHT:
287             tempRectF.SetAll(imageParameter.dstW - imageParameter.srcW,
288                 (imageParameter.dstH - imageParameter.srcH) / CENTER_ALIGNED_FACTOR,
289                 imageParameter.srcW, imageParameter.srcH);
290             return tempRectF;
291         case ImageFit::BOTTOM_LEFT:
292             tempRectF.SetAll(0.f, imageParameter.dstH - imageParameter.srcH, imageParameter.srcW, imageParameter.srcH);
293             return tempRectF;
294         case ImageFit::BOTTOM:
295             tempRectF.SetAll((imageParameter.dstW - imageParameter.srcW) / CENTER_ALIGNED_FACTOR,
296                 imageParameter.dstH - imageParameter.srcH, imageParameter.srcW, imageParameter.srcH);
297             return tempRectF;
298         case ImageFit::BOTTOM_RIGHT:
299             tempRectF.SetAll(imageParameter.dstW - imageParameter.srcW, imageParameter.dstH - imageParameter.srcH,
300                 imageParameter.srcW, imageParameter.srcH);
301             return tempRectF;
302         case ImageFit::FILL:
303             break;
304         case ImageFit::NONE:
305             imageParameter.dstW = imageParameter.srcW;
306             imageParameter.dstH = imageParameter.srcH;
307             break;
308         case ImageFit::COVER:
309             imageParameter.dstW = std::max(imageParameter.frameW, imageParameter.frameH * imageParameter.ratio);
310             imageParameter.dstH = std::max(imageParameter.frameH, imageParameter.frameW / imageParameter.ratio);
311             break;
312         case ImageFit::FIT_WIDTH:
313             imageParameter.dstH = imageParameter.frameW / imageParameter.ratio;
314             break;
315         case ImageFit::FIT_HEIGHT:
316             imageParameter.dstW = imageParameter.frameH * imageParameter.ratio;
317             break;
318         case ImageFit::SCALE_DOWN:
319             if (imageParameter.srcW < imageParameter.frameW && imageParameter.srcH < imageParameter.frameH) {
320                 imageParameter.dstW = imageParameter.srcW;
321                 imageParameter.dstH = imageParameter.srcH;
322             } else {
323                 imageParameter.dstW = std::min(imageParameter.frameW, imageParameter.frameH * imageParameter.ratio);
324                 imageParameter.dstH = std::min(imageParameter.frameH, imageParameter.frameW / imageParameter.ratio);
325             }
326             break;
327         case ImageFit::COVER_TOP_LEFT:
328             imageParameter.dstW = std::max(imageParameter.frameW, imageParameter.frameH * imageParameter.ratio);
329             imageParameter.dstH = std::max(imageParameter.frameH, imageParameter.frameW / imageParameter.ratio);
330             tempRectF.SetAll(0, 0, std::ceil(imageParameter.dstW), std::ceil(imageParameter.dstH));
331             return tempRectF;
332         case ImageFit::CONTAIN:
333         default:
334             imageParameter.dstW = std::min(imageParameter.frameW, imageParameter.frameH * imageParameter.ratio);
335             imageParameter.dstH = std::min(imageParameter.frameH, imageParameter.frameW / imageParameter.ratio);
336             break;
337     }
338     constexpr float horizontalAlignmentFactor = 2.f;
339     constexpr float verticalAlignmentFactor = 2.f;
340     tempRectF.SetAll(std::floor((imageParameter.frameW - imageParameter.dstW) / horizontalAlignmentFactor),
341                      std::floor((imageParameter.frameH - imageParameter.dstH) / verticalAlignmentFactor),
342                      std::ceil(imageParameter.dstW),
343                      std::ceil(imageParameter.dstH));
344     return tempRectF;
345 }
346 
ApplyImageFit()347 void RSImage::ApplyImageFit()
348 {
349     if (scale_ == 0) {
350         RS_LOGE("RSImage::ApplyImageFit failed, scale_ is zero ");
351         return;
352     }
353     const float srcW = srcRect_.width_ / scale_;
354     const float srcH = srcRect_.height_ / scale_;
355     float frameW = frameRect_.width_;
356     float frameH = frameRect_.height_;
357     if (rotateDegree_ == DEGREE_NINETY || rotateDegree_ == -DEGREE_NINETY) {
358         std::swap(frameW, frameH);
359     }
360     float dstW = frameW;
361     float dstH = frameH;
362     if (srcH == 0) {
363         RS_LOGE("RSImage::ApplyImageFit failed, srcH is zero ");
364         return;
365     }
366     float ratio = srcW / srcH;
367     if (ratio == 0) {
368         RS_LOGE("RSImage::ApplyImageFit failed, ratio is zero ");
369         return;
370     }
371     ImageParameter imageParameter;
372     imageParameter.ratio = ratio;
373     imageParameter.srcW = srcW;
374     imageParameter.srcH = srcH;
375     imageParameter.frameW = frameW;
376     imageParameter.frameH = frameH;
377     imageParameter.dstW = dstW;
378     imageParameter.dstH = dstH;
379     RectF tempRectF = dstRect_;
380     dstRect_ = ApplyImageFitSwitch(imageParameter, imageFit_, tempRectF);
381 }
382 
SetImageRotateDegree(int32_t degree)383 void RSImage::SetImageRotateDegree(int32_t degree)
384 {
385     rotateDegree_ = degree;
386 }
387 
CalculateByDegree(const Drawing::Rect & rect)388 std::pair<float, float> RSImage::CalculateByDegree(const Drawing::Rect& rect)
389 {
390     if (rotateDegree_ == DEGREE_NINETY) {
391         return { 0, -rect.GetWidth() };
392     } else if (rotateDegree_ == -DEGREE_NINETY) {
393         return { -rect.GetHeight(), 0 };
394     } else {
395         return { -rect.GetWidth(), -rect.GetHeight() };
396     }
397 }
398 
GetImageFit()399 ImageFit RSImage::GetImageFit()
400 {
401     return imageFit_;
402 }
403 
GetAdaptiveImageInfoWithCustomizedFrameRect(const Drawing::Rect & frameRect) const404 Drawing::AdaptiveImageInfo RSImage::GetAdaptiveImageInfoWithCustomizedFrameRect(const Drawing::Rect& frameRect) const
405 {
406     Drawing::AdaptiveImageInfo imageInfo = {
407         .fitNum = static_cast<int32_t>(imageFit_),
408         .repeatNum = static_cast<int32_t>(imageRepeat_),
409         .radius = { radius_[0], radius_[1], radius_[2], radius_[3] },
410         .scale = scale_,
411         .uniqueId = 0,
412         .width = 0,
413         .height = 0,
414         .dynamicRangeMode = dynamicRangeMode_,
415         .rotateDegree = rotateDegree_,
416         .frameRect = frameRect,
417         .fitMatrix = fitMatrix_.has_value() ? fitMatrix_.value() : Drawing::Matrix(),
418         .orientationNum = static_cast<int32_t>(orientationFit_)
419     };
420     return imageInfo;
421 }
422 
SetFitMatrix(const Drawing::Matrix & matrix)423 void RSImage::SetFitMatrix(const Drawing::Matrix& matrix)
424 {
425     fitMatrix_ = matrix;
426 }
427 
GetFitMatrix() const428 Drawing::Matrix RSImage::GetFitMatrix() const
429 {
430     return fitMatrix_.value();
431 }
432 
SetOrientationFit(int orientationFitNum)433 void RSImage::SetOrientationFit(int orientationFitNum)
434 {
435     orientationFit_ = static_cast<OrientationFit>(orientationFitNum);
436 }
437 
GetOrientationFit() const438 OrientationFit RSImage::GetOrientationFit() const
439 {
440     return orientationFit_;
441 }
442 
GetImage() const443 std::shared_ptr<Drawing::Image> RSImage::GetImage() const
444 {
445     return image_;
446 }
447 
GetDstRect()448 RectF RSImage::GetDstRect()
449 {
450     return dstRect_;
451 }
452 
SetFrameRect(RectF frameRect)453 void RSImage::SetFrameRect(RectF frameRect)
454 {
455     frameRect_ = frameRect;
456 }
457 
HasRadius() const458 bool RSImage::HasRadius() const
459 {
460     return hasRadius_;
461 }
462 
ApplyCanvasClip(Drawing::Canvas & canvas)463 void RSImage::ApplyCanvasClip(Drawing::Canvas& canvas)
464 {
465     if (!HasRadius()) {
466         return;
467     }
468     auto dstRect = dstRect_;
469     if (rotateDegree_ == DEGREE_NINETY || rotateDegree_ == -DEGREE_NINETY) {
470         dstRect = RectF(dstRect_.GetTop(), dstRect_.GetLeft(), dstRect_.GetHeight(), dstRect_.GetWidth());
471     }
472     auto rect = (imageRepeat_ == ImageRepeat::NO_REPEAT) ? dstRect.IntersectRect(frameRect_) : frameRect_;
473     Drawing::RoundRect rrect(RSPropertiesPainter::Rect2DrawingRect(rect), radius_);
474     canvas.ClipRoundRect(rrect, Drawing::ClipOp::INTERSECT, true);
475 }
476 
PixelSamplingDump() const477 std::string RSImage::PixelSamplingDump() const
478 {
479     if (pixelMap_ == nullptr) {
480         return " pixelMap_ is nullptr";
481     }
482     std::stringstream oss;
483     int32_t w = pixelMap_->GetWidth();
484     int32_t h = pixelMap_->GetHeight();
485     oss << "[ Width:" << w << " Height:" << h;
486     oss << " pixels:" << std::hex << std::uppercase;
487 #ifdef ROSEN_OHOS
488     Media::Position pos;
489     uint32_t pixel;
490 
491     int32_t widthStep = std::max((w / 2) - 1, 1);
492     int32_t heightStep = std::max((h / 2) - 1, 1);
493 
494     for (int32_t i = 1; i < w; i += widthStep) {
495         for (int32_t j = 1; j < h; j += heightStep) {
496             pos = {i, j};
497             pixelMap_->ReadPixel(pos, pixel);
498             oss << " ARGB-0x" << pixel;
499         }
500     }
501 #endif
502     oss << ']';
503 
504     return oss.str().c_str();
505 }
506 
DrawImageRepeatRect(const Drawing::SamplingOptions & samplingOptions,Drawing::Canvas & canvas)507 void RSImage::DrawImageRepeatRect(const Drawing::SamplingOptions& samplingOptions, Drawing::Canvas& canvas)
508 {
509     int minX = 0;
510     int minY = 0;
511     int maxX = 0;
512     int maxY = 0;
513     CalcRepeatBounds(minX, maxX, minY, maxY);
514     // draw repeat rect
515     ConvertPixelMapToDrawingImage();
516     UploadGpu(canvas);
517     bool hdrImageDraw = HDRConvert(samplingOptions, canvas);
518     src_ = RSPropertiesPainter::Rect2DrawingRect(srcRect_);
519     bool isAstc = pixelMap_ != nullptr && pixelMap_->IsAstc();
520     for (int i = minX; i <= maxX; ++i) {
521         auto left = dstRect_.left_ + i * dstRect_.width_;
522         auto right = left + dstRect_.width_;
523         for (int j = minY; j <= maxY; ++j) {
524             auto top = dstRect_.top_ + j * dstRect_.height_;
525             dst_ = Drawing::Rect(left, top, right, top + dstRect_.height_);
526 
527             bool needCanvasRestore = isAstc || isOrientationValid_;
528             Drawing::AutoCanvasRestore acr(canvas, needCanvasRestore);
529 
530             if (isAstc) {
531                 RSPixelMapUtil::TransformDataSetForAstc(pixelMap_, src_, dst_, canvas, imageFit_);
532             }
533 
534             if (isOrientationValid_) {
535                 ApplyImageOrientation(canvas);
536             }
537 
538             if (image_) {
539                 DrawImageOnCanvas(samplingOptions, canvas, hdrImageDraw);
540             }
541         }
542     }
543     if (imageRepeat_ == ImageRepeat::NO_REPEAT) {
544         isDrawn_ = true;
545     }
546 }
547 
CalcRepeatBounds(int & minX,int & maxX,int & minY,int & maxY)548 void RSImage::CalcRepeatBounds(int& minX, int& maxX, int& minY, int& maxY)
549 {
550     if (dstRect_.width_ == 0 || dstRect_.height_ == 0) {
551         return;
552     }
553     float left = frameRect_.left_;
554     float right = frameRect_.GetRight();
555     float top = frameRect_.top_;
556     float bottom = frameRect_.GetBottom();
557     // calculate REPEAT_XY
558     float eps = 0.01; // set epsilon
559     auto repeat_x = ImageRepeat::REPEAT_X;
560     auto repeat_y = ImageRepeat::REPEAT_Y;
561     if (rotateDegree_ == DEGREE_NINETY || rotateDegree_ == -DEGREE_NINETY) {
562         std::swap(right, bottom);
563         std::swap(repeat_x, repeat_y);
564     }
565     if (repeat_x == imageRepeat_ || ImageRepeat::REPEAT == imageRepeat_) {
566         while (dstRect_.left_ + minX * dstRect_.width_ > left + eps) {
567             --minX;
568         }
569         while (dstRect_.left_ + maxX * dstRect_.width_ < right - eps) {
570             ++maxX;
571         }
572     }
573     if (repeat_y == imageRepeat_ || ImageRepeat::REPEAT == imageRepeat_) {
574         while (dstRect_.top_ + minY * dstRect_.height_ > top + eps) {
575             --minY;
576         }
577         while (dstRect_.top_ + maxY * dstRect_.height_ < bottom - eps) {
578             ++maxY;
579         }
580     }
581 }
582 
DrawImageShaderRectOnCanvas(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::ShaderEffect> & imageShader) const583 void RSImage::DrawImageShaderRectOnCanvas(
584     Drawing::Canvas& canvas, const std::shared_ptr<Drawing::ShaderEffect>& imageShader) const
585 {
586     if (imageShader == nullptr) {
587         RS_LOGE("RSImage::DrawImageShaderRectOnCanvas image shader is nullptr");
588         return;
589     }
590     Drawing::Paint paint;
591 
592     if (imageRepeat_ == ImageRepeat::NO_REPEAT && isFitMatrixValid_ &&
593         (fitMatrix_->Get(Drawing::Matrix::Index::SKEW_X) != 0 ||
594         fitMatrix_->Get(Drawing::Matrix::Index::SKEW_Y) != 0 ||
595         fitMatrix_->HasPerspective())) {
596         Drawing::Filter filter;
597         Drawing::scalar sigma = 1;
598         filter.SetMaskFilter(Drawing::MaskFilter::CreateBlurMaskFilter(Drawing::BlurType::NORMAL, sigma, false));
599         paint.SetFilter(filter);
600     }
601 
602     paint.SetShaderEffect(imageShader);
603     paint.SetStyle(Drawing::Paint::PAINT_FILL_STROKE);
604     canvas.AttachPaint(paint);
605     canvas.DrawRect(dst_);
606     canvas.DetachPaint();
607 }
608 
DrawImageOnCanvas(const Drawing::SamplingOptions & samplingOptions,Drawing::Canvas & canvas,const bool hdrImageDraw)609 void RSImage::DrawImageOnCanvas(
610     const Drawing::SamplingOptions& samplingOptions, Drawing::Canvas& canvas, const bool hdrImageDraw)
611 {
612     if (canvas.GetTotalMatrix().HasPerspective()) {
613         // In case of perspective transformation, make dstRect 1px outset to anti-alias
614         dst_.MakeOutset(1, 1);
615     }
616     if (innerRect_.has_value()) {
617         canvas.DrawImageNine(image_.get(), innerRect_.value(), dst_, Drawing::FilterMode::LINEAR);
618     } else if (hdrImageDraw) {
619         canvas.DrawRect(dst_);
620     } else {
621         auto imageShader = GenerateImageShaderForDrawRect(canvas, samplingOptions);
622         if (imageShader != nullptr) {
623             DrawImageShaderRectOnCanvas(canvas, imageShader);
624             return;
625         }
626 
627         if (imageRepeat_ == ImageRepeat::NO_REPEAT && isFitMatrixValid_ &&
628             (fitMatrix_->Get(Drawing::Matrix::Index::SKEW_X) != 0 ||
629             fitMatrix_->Get(Drawing::Matrix::Index::SKEW_Y) != 0 ||
630             fitMatrix_->HasPerspective())) {
631             DrawImageWithFirMatrixRotateOnCanvas(samplingOptions, canvas);
632             return;
633         }
634 
635         canvas.DrawImageRect(
636             *image_, src_, dst_, samplingOptions, Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
637     }
638 }
639 
DrawImageWithFirMatrixRotateOnCanvas(const Drawing::SamplingOptions & samplingOptions,Drawing::Canvas & canvas) const640 void RSImage::DrawImageWithFirMatrixRotateOnCanvas(
641     const Drawing::SamplingOptions& samplingOptions, Drawing::Canvas& canvas) const
642 {
643     Drawing::Pen pen;
644     Drawing::Filter filter;
645     Drawing::scalar sigma = 1;
646     filter.SetMaskFilter(Drawing::MaskFilter::CreateBlurMaskFilter(Drawing::BlurType::NORMAL, sigma, false));
647     pen.SetFilter(filter);
648     canvas.AttachPen(pen);
649     canvas.DrawImageRect(
650         *image_, src_, dst_, samplingOptions, Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
651     canvas.DetachPen();
652 }
653 
SetCompressData(const std::shared_ptr<Drawing::Data> data,const uint32_t id,const int width,const int height)654 void RSImage::SetCompressData(
655     const std::shared_ptr<Drawing::Data> data, const uint32_t id, const int width, const int height)
656 {
657 #ifdef RS_ENABLE_GL
658     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
659         compressData_ = data;
660         if (compressData_) {
661             srcRect_.SetAll(0.0, 0.0, width, height);
662             GenUniqueId(image_ ? image_->GetUniqueID() : id);
663             image_ = nullptr;
664         }
665     }
666 #endif
667 }
668 
SetImageFit(int fitNum)669 void RSImage::SetImageFit(int fitNum)
670 {
671     imageFit_ = static_cast<ImageFit>(fitNum);
672 }
673 
SetImageRepeat(int repeatNum)674 void RSImage::SetImageRepeat(int repeatNum)
675 {
676     imageRepeat_ = static_cast<ImageRepeat>(repeatNum);
677 }
678 
SetRadius(const std::vector<Drawing::Point> & radius)679 void RSImage::SetRadius(const std::vector<Drawing::Point>& radius)
680 {
681     hasRadius_ = false;
682     for (auto i = 0; i < CORNER_SIZE; i++) {
683         radius_[i] = radius[i];
684         hasRadius_ = hasRadius_ || !radius_[i].IsZero();
685     }
686 }
687 
SetScale(double scale)688 void RSImage::SetScale(double scale)
689 {
690     if (scale > 0.0) {
691         scale_ = scale;
692     }
693 }
694 
SetNodeId(NodeId nodeId)695 void RSImage::SetNodeId(NodeId nodeId)
696 {
697     nodeId_ = nodeId;
698 }
699 
SetPaint(Drawing::Paint paint)700 void RSImage::SetPaint(Drawing::Paint paint)
701 {
702     paint_ = paint;
703 }
704 
SetDynamicRangeMode(uint32_t dynamicRangeMode)705 void RSImage::SetDynamicRangeMode(uint32_t dynamicRangeMode)
706 {
707     dynamicRangeMode_ = dynamicRangeMode;
708 }
709 
710 #ifdef ROSEN_OHOS
UnmarshallingIdAndSize(Parcel & parcel,uint64_t & uniqueId,int & width,int & height)711 static bool UnmarshallingIdAndSize(Parcel& parcel, uint64_t& uniqueId, int& width, int& height)
712 {
713     if (!RSMarshallingHelper::UnmarshallingPidPlusId(parcel, uniqueId)) {
714         RS_LOGE("RSImage::Unmarshalling uniqueId fail");
715         return false;
716     }
717     if (!RSMarshallingHelper::Unmarshalling(parcel, width)) {
718         RS_LOGE("RSImage::Unmarshalling width fail");
719         return false;
720     }
721     if (!RSMarshallingHelper::Unmarshalling(parcel, height)) {
722         RS_LOGE("RSImage::Unmarshalling height fail");
723         return false;
724     }
725     return true;
726 }
727 
UnmarshallingCompressData(Parcel & parcel,bool skipData,std::shared_ptr<Drawing::Data> & compressData)728 static bool UnmarshallingCompressData(Parcel& parcel, bool skipData, std::shared_ptr<Drawing::Data>& compressData)
729 {
730     if (skipData) {
731         if (!RSMarshallingHelper::SkipData(parcel)) {
732             RS_LOGE("RSImage::Unmarshalling SkipData fail");
733             return false;
734         }
735     } else {
736         if (!RSMarshallingHelper::UnmarshallingWithCopy(parcel, compressData)) {
737             RS_LOGE("RSImage::Unmarshalling UnmarshallingWithCopy Data fail");
738             return false;
739         }
740     }
741     return true;
742 }
743 
Marshalling(Parcel & parcel) const744 bool RSImage::Marshalling(Parcel& parcel) const
745 {
746     int imageFit = static_cast<int>(imageFit_);
747     int imageRepeat = static_cast<int>(imageRepeat_);
748     int orientationFit = static_cast<int>(orientationFit_);
749 
750     std::lock_guard<std::mutex> lock(mutex_);
751     auto image = image_;
752     auto compressData = compressData_;
753     if (image && image->IsTextureBacked()) {
754         image = nullptr;
755         ROSEN_LOGE("RSImage::Marshalling skip texture image");
756     }
757     RS_PROFILER_MARSHAL_DRAWINGIMAGE(image, compressData);
758     uint32_t versionId = pixelMap_ == nullptr ? 0 : pixelMap_->GetVersionId();
759     bool success = RSMarshallingHelper::Marshalling(parcel, uniqueId_) &&
760                    RSMarshallingHelper::Marshalling(parcel, static_cast<int>(srcRect_.width_)) &&
761                    RSMarshallingHelper::Marshalling(parcel, static_cast<int>(srcRect_.height_)) &&
762                    RSMarshallingHelper::Marshalling(parcel, nodeId_) &&
763                    parcel.WriteBool(pixelMap_ == nullptr) &&
764                    RSMarshallingHelper::Marshalling(parcel, versionId) &&
765                    RSMarshallingHelper::Marshalling(parcel, image) &&
766                    RSMarshallingHelper::Marshalling(parcel, pixelMap_) &&
767                    RSMarshallingHelper::Marshalling(parcel, compressData) &&
768                    RSMarshallingHelper::Marshalling(parcel, imageFit) &&
769                    RSMarshallingHelper::Marshalling(parcel, imageRepeat) &&
770                    RSMarshallingHelper::Marshalling(parcel, radius_) &&
771                    RSMarshallingHelper::Marshalling(parcel, scale_) &&
772                    RSMarshallingHelper::Marshalling(parcel, dynamicRangeMode_) &&
773                    RSMarshallingHelper::Marshalling(parcel, rotateDegree_) &&
774                    RSMarshallingHelper::Marshalling(parcel, orientationFit) &&
775                    parcel.WriteBool(fitMatrix_.has_value()) &&
776                    fitMatrix_.has_value() ? RSMarshallingHelper::Marshalling(parcel, fitMatrix_.value()) : true;
777     if (!success) {
778         ROSEN_LOGE("RSImage::Marshalling failed");
779     }
780     return success;
781 }
782 
Unmarshalling(Parcel & parcel)783 RSImage* RSImage::Unmarshalling(Parcel& parcel)
784 {
785     uint64_t uniqueId;
786     int width;
787     int height;
788     NodeId nodeId;
789     if (!UnmarshalIdSizeAndNodeId(parcel, uniqueId, width, height, nodeId)) {
790         return nullptr;
791     }
792     bool useSkImage;
793     std::shared_ptr<Drawing::Image> img;
794     std::shared_ptr<Media::PixelMap> pixelMap;
795     void* imagepixelAddr = nullptr;
796     if (!UnmarshallingDrawingImageAndPixelMap(parcel, uniqueId, useSkImage, img, pixelMap, imagepixelAddr)) {
797         return nullptr;
798     }
799     std::shared_ptr<Drawing::Data> compressData;
800     bool skipData = img != nullptr || !useSkImage;
801     if (!UnmarshallingCompressData(parcel, skipData, compressData)) {
802         return nullptr;
803     }
804     int fitNum;
805     int repeatNum;
806     std::vector<Drawing::Point> radius(CORNER_SIZE);
807     double scale;
808     bool hasFitMatrix;
809     Drawing::Matrix fitMatrix;
810     uint32_t dynamicRangeMode = 0;
811     int32_t degree = 0;
812     int orientationFit;
813     if (!UnmarshalImageProperties(parcel, fitNum, repeatNum, radius, scale,
814         hasFitMatrix, fitMatrix, dynamicRangeMode, degree, orientationFit)) {
815         return nullptr;
816     }
817     RSImage* rsImage = new RSImage();
818     rsImage->SetImage(img);
819     rsImage->SetImagePixelAddr(imagepixelAddr);
820     rsImage->SetCompressData(compressData, uniqueId, width, height);
821     rsImage->SetPixelMap(pixelMap);
822     rsImage->SetImageFit(fitNum);
823     rsImage->SetImageRepeat(repeatNum);
824     rsImage->SetRadius(radius);
825     rsImage->SetScale(scale);
826     rsImage->SetDynamicRangeMode(dynamicRangeMode);
827     rsImage->SetNodeId(nodeId);
828     rsImage->SetImageRotateDegree(degree);
829     if (hasFitMatrix && !fitMatrix.IsIdentity()) {
830         rsImage->SetFitMatrix(fitMatrix);
831     }
832     rsImage->SetOrientationFit(orientationFit);
833     ProcessImageAfterCreation(rsImage, uniqueId, useSkImage, pixelMap);
834     return rsImage;
835 }
836 
UnmarshalIdSizeAndNodeId(Parcel & parcel,uint64_t & uniqueId,int & width,int & height,NodeId & nodeId)837 bool RSImage::UnmarshalIdSizeAndNodeId(Parcel& parcel, uint64_t& uniqueId, int& width, int& height, NodeId& nodeId)
838 {
839     if (!UnmarshallingIdAndSize(parcel, uniqueId, width, height)) {
840         RS_LOGE("RSImage::Unmarshalling UnmarshallingIdAndSize fail");
841         return false;
842     }
843     if (!RSMarshallingHelper::UnmarshallingPidPlusId(parcel, nodeId)) {
844         RS_LOGE("RSImage::Unmarshalling nodeId fail");
845         return false;
846     }
847     return true;
848 }
849 
UnmarshalImageProperties(Parcel & parcel,int & fitNum,int & repeatNum,std::vector<Drawing::Point> & radius,double & scale,bool & hasFitMatrix,Drawing::Matrix & fitMatrix,uint32_t & dynamicRangeMode,int32_t & degree,int & orientationFitNum)850 bool RSImage::UnmarshalImageProperties(
851     Parcel& parcel, int& fitNum, int& repeatNum, std::vector<Drawing::Point>& radius, double& scale,
852     bool& hasFitMatrix, Drawing::Matrix& fitMatrix, uint32_t& dynamicRangeMode, int32_t& degree,
853     int& orientationFitNum)
854 {
855     if (!RSMarshallingHelper::Unmarshalling(parcel, fitNum)) {
856         RS_LOGE("RSImage::Unmarshalling fitNum fail");
857         return false;
858     }
859 
860     if (!RSMarshallingHelper::Unmarshalling(parcel, repeatNum)) {
861         RS_LOGE("RSImage::Unmarshalling repeatNum fail");
862         return false;
863     }
864 
865     if (!RSMarshallingHelper::Unmarshalling(parcel, radius)) {
866         RS_LOGE("RSImage::Unmarshalling radius fail");
867         return false;
868     }
869 
870     if (!RSMarshallingHelper::Unmarshalling(parcel, scale)) {
871         RS_LOGE("RSImage::Unmarshalling scale fail");
872         return false;
873     }
874 
875     if (!RSMarshallingHelper::Unmarshalling(parcel, dynamicRangeMode)) {
876         RS_LOGE("RSImage::Unmarshalling dynamicRangeMode fail");
877         return false;
878     }
879 
880     if (!RSMarshallingHelper::Unmarshalling(parcel, degree)) {
881         RS_LOGE("RSImage::Unmarshalling rotateDegree fail");
882         return false;
883     }
884 
885     if (!RSMarshallingHelper::Unmarshalling(parcel, orientationFitNum)) {
886         RS_LOGE("RSImage::Unmarshalling orientationFitNum fail");
887         return false;
888     }
889 
890     if (!RSMarshallingHelper::Unmarshalling(parcel, hasFitMatrix)) {
891         RS_LOGE("RSImage::Unmarshalling hasFitMatrix fail");
892         return false;
893     }
894 
895     if (hasFitMatrix) {
896         if (!RSMarshallingHelper::Unmarshalling(parcel, fitMatrix)) {
897             RS_LOGE("RSImage::Unmarshalling fitMatrix fail");
898             return false;
899         }
900     }
901 
902     return true;
903 }
904 
ProcessImageAfterCreation(RSImage * rsImage,const uint64_t uniqueId,const bool useSkImage,const std::shared_ptr<Media::PixelMap> & pixelMap)905 void RSImage::ProcessImageAfterCreation(
906     RSImage* rsImage, const uint64_t uniqueId, const bool useSkImage, const std::shared_ptr<Media::PixelMap>& pixelMap)
907 {
908     rsImage->uniqueId_ = uniqueId;
909     rsImage->MarkRenderServiceImage();
910     RSImageBase::IncreaseCacheRefCount(uniqueId, useSkImage, pixelMap);
911 }
912 #endif
913 } // namespace Rosen
914 } // namespace OHOS
915