• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.. All rights reserved.
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 "recording/recording_canvas.h"
17 
18 #include "recording/cmd_list_helper.h"
19 #include "recording/draw_cmd.h"
20 #include "recording/draw_cmd_list.h"
21 #include "draw/color.h"
22 #include "effect/color_filter.h"
23 #include "effect/color_space.h"
24 #include "effect/filter.h"
25 #include "effect/image_filter.h"
26 #include "effect/mask_filter.h"
27 #include "effect/path_effect.h"
28 #include "effect/shader_effect.h"
29 #include "utils/log.h"
30 #include "sandbox_utils.h"
31 
32 namespace OHOS {
33 namespace Rosen {
34 namespace Drawing {
RecordingCanvas(int32_t width,int32_t height,bool addDrawOpImmediate)35 RecordingCanvas::RecordingCanvas(int32_t width, int32_t height, bool addDrawOpImmediate)
36     : NoDrawCanvas(width, height), addDrawOpImmediate_(addDrawOpImmediate)
37 {
38     DrawCmdList::UnmarshalMode mode =
39         addDrawOpImmediate ? DrawCmdList::UnmarshalMode::IMMEDIATE : DrawCmdList::UnmarshalMode::DEFERRED;
40     cmdList_ = std::make_shared<DrawCmdList>(width, height, mode);
41 }
42 
GetDrawCmdList() const43 std::shared_ptr<DrawCmdList> RecordingCanvas::GetDrawCmdList() const
44 {
45     return cmdList_;
46 }
47 
Clear() const48 void RecordingCanvas::Clear() const
49 {
50     if (cmdList_ == nullptr) {
51         return;
52     }
53     cmdList_->ClearOp();
54 }
55 
Reset(int32_t width,int32_t height,bool addDrawOpImmediate)56 void RecordingCanvas::Reset(int32_t width, int32_t height, bool addDrawOpImmediate)
57 {
58     DrawCmdList::UnmarshalMode mode =
59         addDrawOpImmediate ? DrawCmdList::UnmarshalMode::IMMEDIATE : DrawCmdList::UnmarshalMode::DEFERRED;
60     cmdList_ = std::make_shared<DrawCmdList>(width, height, mode);
61     addDrawOpImmediate_ = addDrawOpImmediate;
62     isCustomTextType_ = false;
63     isCustomTypeface_ = false;
64     customTextBrush_ = std::nullopt;
65     customTextPen_ = std::nullopt;
66     saveOpStateStack_ = std::stack<SaveOpState>();
67     gpuContext_ = nullptr;
68     opCount = 0;
69     RemoveAll();
70     DetachBrush();
71     DetachPen();
72     NoDrawCanvas::Reset(width, height);
73 }
74 
DrawPoint(const Point & point)75 void RecordingCanvas::DrawPoint(const Point& point)
76 {
77     if (!addDrawOpImmediate_) {
78         AddDrawOpDeferred<DrawPointOpItem>(point);
79         return;
80     }
81     AddDrawOpImmediate<DrawPointOpItem::ConstructorHandle>(point);
82 }
83 
DrawPoints(PointMode mode,size_t count,const Point pts[])84 void RecordingCanvas::DrawPoints(PointMode mode, size_t count, const Point pts[])
85 {
86     std::vector<Point> points(pts, pts + count);
87     if (!addDrawOpImmediate_) {
88         AddDrawOpDeferred<DrawPointsOpItem>(mode, points);
89         return;
90     }
91     auto pointsData = CmdListHelper::AddVectorToCmdList<Point>(*cmdList_, points);
92     AddDrawOpImmediate<DrawPointsOpItem::ConstructorHandle>(mode, pointsData);
93 }
94 
DrawLine(const Point & startPt,const Point & endPt)95 void RecordingCanvas::DrawLine(const Point& startPt, const Point& endPt)
96 {
97     if (!addDrawOpImmediate_) {
98         AddDrawOpDeferred<DrawLineOpItem>(startPt, endPt);
99         return;
100     }
101     AddDrawOpImmediate<DrawLineOpItem::ConstructorHandle>(startPt, endPt);
102 }
103 
DrawRect(const Rect & rect)104 void RecordingCanvas::DrawRect(const Rect& rect)
105 {
106     if (!addDrawOpImmediate_) {
107         AddDrawOpDeferred<DrawRectOpItem>(rect);
108         return;
109     }
110     AddDrawOpImmediate<DrawRectOpItem::ConstructorHandle>(rect);
111 }
112 
DrawRoundRect(const RoundRect & roundRect)113 void RecordingCanvas::DrawRoundRect(const RoundRect& roundRect)
114 {
115     if (!addDrawOpImmediate_) {
116         AddDrawOpDeferred<DrawRoundRectOpItem>(roundRect);
117         return;
118     }
119     AddDrawOpImmediate<DrawRoundRectOpItem::ConstructorHandle>(roundRect);
120 }
121 
DrawNestedRoundRect(const RoundRect & outer,const RoundRect & inner)122 void RecordingCanvas::DrawNestedRoundRect(const RoundRect& outer, const RoundRect& inner)
123 {
124     if (!addDrawOpImmediate_) {
125         AddDrawOpDeferred<DrawNestedRoundRectOpItem>(outer, inner);
126         return;
127     }
128     AddDrawOpImmediate<DrawNestedRoundRectOpItem::ConstructorHandle>(outer, inner);
129 }
130 
DrawArc(const Rect & oval,scalar startAngle,scalar sweepAngle)131 void RecordingCanvas::DrawArc(const Rect& oval, scalar startAngle, scalar sweepAngle)
132 {
133     if (!addDrawOpImmediate_) {
134         AddDrawOpDeferred<DrawArcOpItem>(oval, startAngle, sweepAngle);
135         return;
136     }
137     AddDrawOpImmediate<DrawArcOpItem::ConstructorHandle>(oval, startAngle, sweepAngle);
138 }
139 
DrawPie(const Rect & oval,scalar startAngle,scalar sweepAngle)140 void RecordingCanvas::DrawPie(const Rect& oval, scalar startAngle, scalar sweepAngle)
141 {
142     if (!addDrawOpImmediate_) {
143         AddDrawOpDeferred<DrawPieOpItem>(oval, startAngle, sweepAngle);
144         return;
145     }
146     AddDrawOpImmediate<DrawPieOpItem::ConstructorHandle>(oval, startAngle, sweepAngle);
147 }
148 
DrawOval(const Rect & oval)149 void RecordingCanvas::DrawOval(const Rect& oval)
150 {
151     if (!addDrawOpImmediate_) {
152         AddDrawOpDeferred<DrawOvalOpItem>(oval);
153         return;
154     }
155     AddDrawOpImmediate<DrawOvalOpItem::ConstructorHandle>(oval);
156 }
157 
DrawCircle(const Point & centerPt,scalar radius)158 void RecordingCanvas::DrawCircle(const Point& centerPt, scalar radius)
159 {
160     if (!addDrawOpImmediate_) {
161         AddDrawOpDeferred<DrawCircleOpItem>(centerPt, radius);
162         return;
163     }
164     AddDrawOpImmediate<DrawCircleOpItem::ConstructorHandle>(centerPt, radius);
165 }
166 
DrawPath(const Path & path)167 void RecordingCanvas::DrawPath(const Path& path)
168 {
169     if (!addDrawOpImmediate_) {
170         AddDrawOpDeferred<DrawPathOpItem>(path);
171         return;
172     }
173     auto pathHandle = CmdListHelper::AddPathToCmdList(*cmdList_, path);
174     AddDrawOpImmediate<DrawPathOpItem::ConstructorHandle>(pathHandle);
175 }
176 
DrawBackground(const Brush & brush)177 void RecordingCanvas::DrawBackground(const Brush& brush)
178 {
179     if (!addDrawOpImmediate_) {
180         cmdList_->AddDrawOp(std::make_shared<DrawBackgroundOpItem>(brush));
181         return;
182     }
183     BrushHandle brushHandle;
184     DrawOpItem::BrushToBrushHandle(brush, *cmdList_, brushHandle);
185     cmdList_->AddDrawOp<DrawBackgroundOpItem::ConstructorHandle>(brushHandle);
186 }
187 
DrawShadow(const Path & path,const Point3 & planeParams,const Point3 & devLightPos,scalar lightRadius,Color ambientColor,Color spotColor,ShadowFlags flag)188 void RecordingCanvas::DrawShadow(const Path& path, const Point3& planeParams, const Point3& devLightPos,
189     scalar lightRadius, Color ambientColor, Color spotColor, ShadowFlags flag)
190 {
191     if (!addDrawOpImmediate_) {
192         cmdList_->AddDrawOp(std::make_shared<DrawShadowOpItem>(
193             path, planeParams, devLightPos, lightRadius, ambientColor, spotColor, flag));
194         return;
195     }
196     auto pathHandle = CmdListHelper::AddPathToCmdList(*cmdList_, path);
197     cmdList_->AddDrawOp<DrawShadowOpItem::ConstructorHandle>(
198         pathHandle, planeParams, devLightPos, lightRadius, ambientColor, spotColor, flag);
199 }
200 
DrawShadowStyle(const Path & path,const Point3 & planeParams,const Point3 & devLightPos,scalar lightRadius,Color ambientColor,Color spotColor,ShadowFlags flag,bool isLimitElevation)201 void RecordingCanvas::DrawShadowStyle(const Path& path, const Point3& planeParams, const Point3& devLightPos,
202     scalar lightRadius, Color ambientColor, Color spotColor, ShadowFlags flag, bool isLimitElevation)
203 {
204     if (!addDrawOpImmediate_) {
205         cmdList_->AddDrawOp(std::make_shared<DrawShadowStyleOpItem>(
206             path, planeParams, devLightPos, lightRadius, ambientColor, spotColor, flag, isLimitElevation));
207         return;
208     }
209     auto pathHandle = CmdListHelper::AddPathToCmdList(*cmdList_, path);
210     cmdList_->AddDrawOp<DrawShadowStyleOpItem::ConstructorHandle>(
211         pathHandle, planeParams, devLightPos, lightRadius, ambientColor, spotColor, flag, isLimitElevation);
212 }
213 
DrawRegion(const Region & region)214 void RecordingCanvas::DrawRegion(const Region& region)
215 {
216     if (region.IsEmpty()) {
217         return;
218     }
219     if (!addDrawOpImmediate_) {
220         AddDrawOpDeferred<DrawRegionOpItem>(region);
221         return;
222     }
223     auto regionHandle = CmdListHelper::AddRegionToCmdList(*cmdList_, region);
224     AddDrawOpImmediate<DrawRegionOpItem::ConstructorHandle>(regionHandle);
225 }
226 
DrawPatch(const Point cubics[12],const ColorQuad colors[4],const Point texCoords[4],BlendMode mode)227 void RecordingCanvas::DrawPatch(const Point cubics[12], const ColorQuad colors[4],
228     const Point texCoords[4], BlendMode mode)
229 {
230     LOGD("RecordingCanvas::DrawPatch not support yet");
231 }
232 
DrawVertices(const Vertices & vertices,BlendMode mode)233 void RecordingCanvas::DrawVertices(const Vertices& vertices, BlendMode mode)
234 {
235     if (!addDrawOpImmediate_) {
236         AddDrawOpDeferred<DrawVerticesOpItem>(vertices, mode);
237         return;
238     }
239     auto opDataHandle = CmdListHelper::AddVerticesToCmdList(*cmdList_, vertices);
240     AddDrawOpImmediate<DrawVerticesOpItem::ConstructorHandle>(opDataHandle, mode);
241 }
242 
DrawImageNine(const Image * image,const RectI & center,const Rect & dst,FilterMode filterMode,const Brush * brush)243 void RecordingCanvas::DrawImageNine(const Image* image, const RectI& center, const Rect& dst,
244     FilterMode filterMode, const Brush* brush)
245 {
246     if (image == nullptr) {
247         LOGE("RecordingCanvas::DrawImageNine, image is nullptr!");
248         return;
249     }
250     if (!addDrawOpImmediate_) {
251         cmdList_->AddDrawOp(std::make_shared<DrawImageNineOpItem>(image, center, dst, filterMode, brush));
252         return;
253     }
254 
255     auto imageHandle = CmdListHelper::AddImageToCmdList(*cmdList_, *image);
256     BrushHandle brushHandle;
257     bool hasBrush = false;
258     if (brush != nullptr) {
259         hasBrush = true;
260         DrawOpItem::BrushToBrushHandle(*brush, *cmdList_, brushHandle);
261     }
262 
263     cmdList_->AddDrawOp<DrawImageNineOpItem::ConstructorHandle>(
264         imageHandle, center, dst, filterMode, brushHandle, hasBrush);
265 }
266 
DrawImageLattice(const Image * image,const Lattice & lattice,const Rect & dst,FilterMode filterMode)267 void RecordingCanvas::DrawImageLattice(const Image* image, const Lattice& lattice, const Rect& dst,
268     FilterMode filterMode)
269 {
270     if (image == nullptr) {
271         LOGE("RecordingCanvas::DrawImageLattice failed, image is nullptr");
272         return;
273     }
274     if (!addDrawOpImmediate_) {
275         AddDrawOpDeferred<DrawImageLatticeOpItem>(image, lattice, dst, filterMode);
276         return;
277     }
278 
279     auto imageHandle = CmdListHelper::AddImageToCmdList(*cmdList_, *image);
280     auto latticeHandle = CmdListHelper::AddLatticeToCmdList(*cmdList_, lattice);
281     AddDrawOpImmediate<DrawImageLatticeOpItem::ConstructorHandle>(imageHandle, latticeHandle, dst, filterMode);
282 }
283 
DrawColor(ColorQuad color,BlendMode mode)284 void RecordingCanvas::DrawColor(ColorQuad color, BlendMode mode)
285 {
286     if (!addDrawOpImmediate_) {
287         cmdList_->AddDrawOp(std::make_shared<DrawColorOpItem>(color, mode));
288         return;
289     }
290     cmdList_->AddDrawOp<DrawColorOpItem::ConstructorHandle>(color, mode);
291 }
292 
DrawAtlas(const Image * atlas,const RSXform xform[],const Rect tex[],const ColorQuad colors[],int count,BlendMode mode,const SamplingOptions & sampling,const Rect * cullRect)293 void RecordingCanvas::DrawAtlas(const Image* atlas, const RSXform xform[], const Rect tex[], const ColorQuad colors[],
294     int count, BlendMode mode, const SamplingOptions& sampling, const Rect* cullRect)
295 {
296     if (!atlas) {
297         return;
298     }
299     std::vector<RSXform> xformVec(xform, xform + count);
300     std::vector<Rect> texVec(tex, tex + count);
301     std::vector<ColorQuad> colorVec;
302     if (colors) {
303         colorVec.assign(colors, colors + count);
304     }
305     Rect rect;
306     bool hasCullRect = false;
307     if (cullRect) {
308         rect = *cullRect;
309         hasCullRect = true;
310     }
311     if (!addDrawOpImmediate_) {
312         AddDrawOpDeferred<DrawAtlasOpItem>(atlas, xformVec, texVec, colorVec, mode, sampling, hasCullRect, rect);
313         return;
314     }
315     auto imageHandle = CmdListHelper::AddImageToCmdList(*cmdList_, *atlas);
316     auto xformData = CmdListHelper::AddVectorToCmdList<RSXform>(*cmdList_, xformVec);
317     auto texData = CmdListHelper::AddVectorToCmdList<Rect>(*cmdList_, texVec);
318     auto colorData = CmdListHelper::AddVectorToCmdList<ColorQuad>(*cmdList_, colorVec);
319     AddDrawOpImmediate<DrawAtlasOpItem::ConstructorHandle>(imageHandle, xformData, texData, colorData, mode,
320         sampling, hasCullRect, rect);
321 }
322 
DrawBitmap(const Bitmap & bitmap,const scalar px,const scalar py)323 void RecordingCanvas::DrawBitmap(const Bitmap& bitmap, const scalar px, const scalar py)
324 {
325     auto image = bitmap.MakeImage();
326     if (image) {
327         DrawImage(*image, px, py, SamplingOptions());
328     }
329 }
330 
DrawImage(const Image & image,const scalar px,const scalar py,const SamplingOptions & sampling)331 void RecordingCanvas::DrawImage(const Image& image, const scalar px, const scalar py, const SamplingOptions& sampling)
332 {
333     if (!addDrawOpImmediate_) {
334         AddDrawOpDeferred<DrawImageOpItem>(image, px, py, sampling);
335         return;
336     }
337     opCount++;
338     auto imageHandle = CmdListHelper::AddImageToCmdList(*cmdList_, image);
339     AddDrawOpImmediate<DrawImageOpItem::ConstructorHandle>(imageHandle, px, py, sampling);
340 }
341 
DrawImageRect(const Image & image,const Rect & src,const Rect & dst,const SamplingOptions & sampling,SrcRectConstraint constraint)342 void RecordingCanvas::DrawImageRect(
343     const Image& image, const Rect& src, const Rect& dst, const SamplingOptions& sampling, SrcRectConstraint constraint)
344 {
345     if (!addDrawOpImmediate_) {
346         AddDrawOpDeferred<DrawImageRectOpItem>(image, src, dst, sampling, constraint);
347         return;
348     }
349     opCount++;
350     auto imageHandle = CmdListHelper::AddImageToCmdList(*cmdList_, image);
351     AddDrawOpImmediate<DrawImageRectOpItem::ConstructorHandle>(imageHandle, src, dst, sampling, constraint);
352 }
353 
DrawImageRect(const Image & image,const Rect & dst,const SamplingOptions & sampling)354 void RecordingCanvas::DrawImageRect(const Image& image, const Rect& dst, const SamplingOptions& sampling)
355 {
356     if (!addDrawOpImmediate_) {
357         Rect src(0, 0, image.GetWidth(), image.GetHeight());
358         AddDrawOpDeferred<DrawImageRectOpItem>(image, src, dst, sampling, SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
359         return;
360     }
361     opCount++;
362     auto imageHandle = CmdListHelper::AddImageToCmdList(*cmdList_, image);
363     Rect src(0, 0, image.GetWidth(), image.GetHeight());
364     AddDrawOpImmediate<DrawImageRectOpItem::ConstructorHandle>(
365         imageHandle, src, dst, sampling, SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
366 }
367 
DrawRecordCmd(const std::shared_ptr<RecordCmd> recordCmd,const Matrix * matrix,const Brush * brush)368 void RecordingCanvas::DrawRecordCmd(const std::shared_ptr<RecordCmd> recordCmd,
369     const Matrix* matrix, const Brush* brush)
370 {
371     if (recordCmd == nullptr) {
372         LOGE("RecordingCanvas::DrawRecordCmd, recordCmd is nullptr!");
373         return;
374     }
375 
376     if (!addDrawOpImmediate_) {
377         cmdList_->AddDrawOp(std::make_shared<DrawRecordCmdOpItem>(recordCmd, matrix, brush));
378         return;
379     }
380 
381     BrushHandle brushHandle;
382     bool hasBrush = false;
383     if (brush != nullptr) {
384         hasBrush = true;
385         DrawOpItem::BrushToBrushHandle(*brush, *cmdList_, brushHandle);
386     }
387 
388     Matrix layerMatrix;
389     Matrix::Buffer layerMatrixBuffer;
390     if (matrix != nullptr) {
391         layerMatrix = *matrix;
392     }
393     layerMatrix.GetAll(layerMatrixBuffer);
394     auto recordCmdHandle = CmdListHelper::AddRecordCmdToCmdList(*cmdList_, recordCmd);
395     cmdList_->AddDrawOp<DrawRecordCmdOpItem::ConstructorHandle>(recordCmdHandle,
396         layerMatrixBuffer, hasBrush, brushHandle);
397 }
398 
DrawPicture(const Picture & picture)399 void RecordingCanvas::DrawPicture(const Picture& picture)
400 {
401     if (!addDrawOpImmediate_) {
402         cmdList_->AddDrawOp(std::make_shared<DrawPictureOpItem>(picture));
403         return;
404     }
405     auto pictureHandle = CmdListHelper::AddPictureToCmdList(*cmdList_, picture);
406     cmdList_->AddDrawOp<DrawPictureOpItem::ConstructorHandle>(pictureHandle);
407 }
408 
DrawTextBlob(const TextBlob * blob,const scalar x,const scalar y)409 void RecordingCanvas::DrawTextBlob(const TextBlob* blob, const scalar x, const scalar y)
410 {
411     static uint64_t shiftedPid = static_cast<uint64_t>(GetRealPid()) << 32; // 32 for 64-bit unsignd number shift
412     if (!blob) {
413         return;
414     }
415 #ifdef ROSEN_OHOS
416     if (IsCustomTextType()) {
417         LOGD("RecordingCanvas::DrawTextBlob replace drawOpItem with cached one");
418         GenerateCachedOpForTextblob(blob, x, y);
419         return;
420     }
421 #endif
422     if (!addDrawOpImmediate_) {
423         AddDrawOpDeferred<DrawTextBlobOpItem>(blob, x, y);
424         return;
425     }
426     TextBlob::Context ctx {nullptr, false};
427     auto textBlobHandle = CmdListHelper::AddTextBlobToCmdList(*cmdList_, blob, &ctx);
428     uint64_t globalUniqueId = 0;
429     if (ctx.GetTypeface() != nullptr) {
430         uint32_t typefaceId = ctx.GetTypeface()->GetUniqueID();
431         globalUniqueId = (shiftedPid | typefaceId);
432     }
433     AddDrawOpImmediate<DrawTextBlobOpItem::ConstructorHandle>(textBlobHandle,
434         globalUniqueId, blob->GetTextContrast(), x, y);
435 }
436 
DrawSymbol(const DrawingHMSymbolData & symbol,Point locate)437 void RecordingCanvas::DrawSymbol(const DrawingHMSymbolData& symbol, Point locate)
438 {
439     if (!addDrawOpImmediate_) {
440         AddDrawOpDeferred<DrawSymbolOpItem>(symbol, locate);
441         return;
442     }
443     auto symbolHandle = CmdListHelper::AddSymbolToCmdList(*cmdList_, symbol);
444     AddDrawOpImmediate<DrawSymbolOpItem::ConstructorHandle>(symbolHandle, locate);
445 }
446 
ClipRect(const Rect & rect,ClipOp op,bool doAntiAlias)447 void RecordingCanvas::ClipRect(const Rect& rect, ClipOp op, bool doAntiAlias)
448 {
449     CheckForLazySave();
450     Canvas::ClipRect(rect, op, doAntiAlias);
451     if (!addDrawOpImmediate_) {
452         cmdList_->AddDrawOp(std::make_shared<ClipRectOpItem>(rect, op, doAntiAlias));
453         return;
454     }
455     cmdList_->AddDrawOp<ClipRectOpItem::ConstructorHandle>(rect, op, doAntiAlias);
456 }
457 
ClipIRect(const RectI & rect,ClipOp op)458 void RecordingCanvas::ClipIRect(const RectI& rect, ClipOp op)
459 {
460     CheckForLazySave();
461     Canvas::ClipIRect(rect, op);
462     if (!addDrawOpImmediate_) {
463         cmdList_->AddDrawOp(std::make_shared<ClipIRectOpItem>(rect, op));
464         return;
465     }
466     cmdList_->AddDrawOp<ClipIRectOpItem::ConstructorHandle>(rect, op);
467 }
468 
ClipRoundRect(const RoundRect & roundRect,ClipOp op,bool doAntiAlias)469 void RecordingCanvas::ClipRoundRect(const RoundRect& roundRect, ClipOp op, bool doAntiAlias)
470 {
471     CheckForLazySave();
472     Canvas::ClipRoundRect(roundRect, op, doAntiAlias);
473     if (!addDrawOpImmediate_) {
474         cmdList_->AddDrawOp(std::make_shared<ClipRoundRectOpItem>(roundRect, op, doAntiAlias));
475         return;
476     }
477     cmdList_->AddDrawOp<ClipRoundRectOpItem::ConstructorHandle>(roundRect, op, doAntiAlias);
478 }
479 
ClipRoundRect(const Rect & rect,std::vector<Point> & pts,bool doAntiAlias)480 void RecordingCanvas::ClipRoundRect(const Rect& rect, std::vector<Point>& pts, bool doAntiAlias)
481 {
482     CheckForLazySave();
483     RoundRect roundRect = RoundRect(rect, pts);
484     Canvas::ClipRoundRect(roundRect, ClipOp::INTERSECT, doAntiAlias);
485     if (!addDrawOpImmediate_) {
486         cmdList_->AddDrawOp(std::make_shared<ClipRoundRectOpItem>(roundRect, ClipOp::INTERSECT, doAntiAlias));
487         return;
488     }
489     cmdList_->AddDrawOp<ClipRoundRectOpItem::ConstructorHandle>(roundRect, ClipOp::INTERSECT, doAntiAlias);
490 }
491 
ClipPath(const Path & path,ClipOp op,bool doAntiAlias)492 void RecordingCanvas::ClipPath(const Path& path, ClipOp op, bool doAntiAlias)
493 {
494     CheckForLazySave();
495     Canvas::ClipPath(path, op, doAntiAlias);
496     if (!addDrawOpImmediate_) {
497         cmdList_->AddDrawOp(std::make_shared<ClipPathOpItem>(path, op, doAntiAlias));
498         return;
499     }
500     auto pathHandle = CmdListHelper::AddPathToCmdList(*cmdList_, path);
501     cmdList_->AddDrawOp<ClipPathOpItem::ConstructorHandle>(pathHandle, op, doAntiAlias);
502 }
503 
ClipRegion(const Region & region,ClipOp op)504 void RecordingCanvas::ClipRegion(const Region& region, ClipOp op)
505 {
506     CheckForLazySave();
507     Canvas::ClipRegion(region, op);
508     if (!addDrawOpImmediate_) {
509         cmdList_->AddDrawOp(std::make_shared<ClipRegionOpItem>(region, op));
510         return;
511     }
512     auto regionHandle = CmdListHelper::AddRegionToCmdList(*cmdList_, region);
513     cmdList_->AddDrawOp<ClipRegionOpItem::ConstructorHandle>(regionHandle, op);
514 }
515 
SetMatrix(const Matrix & matrix)516 void RecordingCanvas::SetMatrix(const Matrix& matrix)
517 {
518     CheckForLazySave();
519     Canvas::SetMatrix(matrix);
520     if (!addDrawOpImmediate_) {
521         cmdList_->AddDrawOp(std::make_shared<SetMatrixOpItem>(matrix));
522         return;
523     }
524     Matrix::Buffer matrixBuffer;
525     matrix.GetAll(matrixBuffer);
526     cmdList_->AddDrawOp<SetMatrixOpItem::ConstructorHandle>(matrixBuffer);
527 }
528 
ResetMatrix()529 void RecordingCanvas::ResetMatrix()
530 {
531     CheckForLazySave();
532     Canvas::ResetMatrix();
533     if (!addDrawOpImmediate_) {
534         cmdList_->AddDrawOp(std::make_shared<ResetMatrixOpItem>());
535         return;
536     }
537     cmdList_->AddDrawOp<ResetMatrixOpItem::ConstructorHandle>();
538 }
539 
ConcatMatrix(const Matrix & matrix)540 void RecordingCanvas::ConcatMatrix(const Matrix& matrix)
541 {
542     if (!matrix.IsIdentity()) {
543         CheckForLazySave();
544         Canvas::ConcatMatrix(matrix);
545         if (!addDrawOpImmediate_) {
546             cmdList_->AddDrawOp(std::make_shared<ConcatMatrixOpItem>(matrix));
547             return;
548         }
549         Matrix::Buffer matrixBuffer;
550         matrix.GetAll(matrixBuffer);
551         cmdList_->AddDrawOp<ConcatMatrixOpItem::ConstructorHandle>(matrixBuffer);
552     }
553 }
554 
Translate(scalar dx,scalar dy)555 void RecordingCanvas::Translate(scalar dx, scalar dy)
556 {
557     if (dx || dy) {
558         CheckForLazySave();
559         Canvas::Translate(dx, dy);
560         if (!addDrawOpImmediate_) {
561             cmdList_->AddDrawOp(std::make_shared<TranslateOpItem>(dx, dy));
562             return;
563         }
564         cmdList_->AddDrawOp<TranslateOpItem::ConstructorHandle>(dx, dy);
565     }
566 }
567 
Scale(scalar sx,scalar sy)568 void RecordingCanvas::Scale(scalar sx, scalar sy)
569 {
570     if (sx != 1 || sy != 1) {
571         CheckForLazySave();
572         Canvas::Scale(sx, sy);
573         if (!addDrawOpImmediate_) {
574             cmdList_->AddDrawOp(std::make_shared<ScaleOpItem>(sx, sy));
575             return;
576         }
577         cmdList_->AddDrawOp<ScaleOpItem::ConstructorHandle>(sx, sy);
578     }
579 }
580 
Rotate(scalar deg,scalar sx,scalar sy)581 void RecordingCanvas::Rotate(scalar deg, scalar sx, scalar sy)
582 {
583     if (deg) {
584         CheckForLazySave();
585         Canvas::Rotate(deg, sx, sy);
586         if (!addDrawOpImmediate_) {
587             cmdList_->AddDrawOp(std::make_shared<RotateOpItem>(deg, sx, sy));
588             return;
589         }
590         cmdList_->AddDrawOp<RotateOpItem::ConstructorHandle>(deg, sx, sy);
591     }
592 }
593 
Shear(scalar sx,scalar sy)594 void RecordingCanvas::Shear(scalar sx, scalar sy)
595 {
596     if (sx || sy) {
597         CheckForLazySave();
598         Canvas::Shear(sx, sy);
599         if (!addDrawOpImmediate_) {
600             cmdList_->AddDrawOp(std::make_shared<ShearOpItem>(sx, sy));
601             return;
602         }
603         cmdList_->AddDrawOp<ShearOpItem::ConstructorHandle>(sx, sy);
604     }
605 }
606 
Flush()607 void RecordingCanvas::Flush()
608 {
609     if (!addDrawOpImmediate_) {
610         cmdList_->AddDrawOp(std::make_shared<FlushOpItem>());
611         return;
612     }
613     cmdList_->AddDrawOp<FlushOpItem::ConstructorHandle>();
614 }
615 
Clear(ColorQuad color)616 void RecordingCanvas::Clear(ColorQuad color)
617 {
618     if (!addDrawOpImmediate_) {
619         cmdList_->AddDrawOp(std::make_shared<ClearOpItem>(color));
620         return;
621     }
622     cmdList_->AddDrawOp<ClearOpItem::ConstructorHandle>(color);
623 }
624 
Save()625 uint32_t RecordingCanvas::Save()
626 {
627     uint32_t ret = static_cast<uint32_t>(saveOpStateStack_.size());
628     saveOpStateStack_.push(LazySaveOp);
629     return ret + 1; // The minimum value for non-recording types is 1
630 }
631 
SaveLayer(const SaveLayerOps & saveLayerOps)632 void RecordingCanvas::SaveLayer(const SaveLayerOps& saveLayerOps)
633 {
634     Canvas::SaveLayer(saveLayerOps);
635     saveOpStateStack_.push(RealSaveOp);
636     if (!addDrawOpImmediate_) {
637         cmdList_->AddDrawOp(std::make_shared<SaveLayerOpItem>(saveLayerOps));
638         return;
639     }
640 
641     Rect rect;
642     bool hasBrush = false;
643     BrushHandle brushHandle;
644 
645     if (saveLayerOps.GetBounds() != nullptr) {
646         rect = *saveLayerOps.GetBounds();
647     }
648     const Brush* brush = saveLayerOps.GetBrush();
649     if (brush != nullptr) {
650         hasBrush = true;
651         DrawOpItem::BrushToBrushHandle(*brush, *cmdList_, brushHandle);
652     }
653 
654     cmdList_->AddDrawOp<SaveLayerOpItem::ConstructorHandle>(rect, hasBrush, brushHandle,
655         saveLayerOps.GetSaveLayerFlags());
656 }
657 
Restore()658 void RecordingCanvas::Restore()
659 {
660     if (saveOpStateStack_.empty()) {
661         return;
662     }
663 
664     SaveOpState state = saveOpStateStack_.top();
665     saveOpStateStack_.pop();
666     if (state == RealSaveOp) {
667         Canvas::Restore();
668         if (!addDrawOpImmediate_) {
669             cmdList_->AddDrawOp(std::make_shared<RestoreOpItem>());
670             return;
671         }
672         cmdList_->AddDrawOp<RestoreOpItem::ConstructorHandle>();
673     }
674 }
675 
GetSaveCount() const676 uint32_t RecordingCanvas::GetSaveCount() const
677 {
678     return static_cast<uint32_t>(saveOpStateStack_.size()) + 1; // The minimum value for non-recording types is 1
679 }
680 
Discard()681 void RecordingCanvas::Discard()
682 {
683     if (!addDrawOpImmediate_) {
684         cmdList_->AddDrawOp(std::make_shared<DiscardOpItem>());
685         return;
686     }
687     cmdList_->AddDrawOp<DiscardOpItem::ConstructorHandle>();
688 }
689 
ClipAdaptiveRoundRect(const std::vector<Point> & radius)690 void RecordingCanvas::ClipAdaptiveRoundRect(const std::vector<Point>& radius)
691 {
692     if (!addDrawOpImmediate_) {
693         cmdList_->AddDrawOp(std::make_shared<ClipAdaptiveRoundRectOpItem>(radius));
694         return;
695     }
696     auto radiusData = CmdListHelper::AddVectorToCmdList<Point>(*cmdList_, radius);
697     cmdList_->AddDrawOp<ClipAdaptiveRoundRectOpItem::ConstructorHandle>(radiusData);
698 }
699 
SetIsCustomTextType(bool isCustomTextType)700 void RecordingCanvas::SetIsCustomTextType(bool isCustomTextType)
701 {
702     isCustomTextType_ = isCustomTextType;
703 }
704 
IsCustomTextType() const705 bool RecordingCanvas::IsCustomTextType() const
706 {
707     return isCustomTextType_;
708 }
709 
SetIsCustomTypeface(bool isCustomTypeface)710 void RecordingCanvas::SetIsCustomTypeface(bool isCustomTypeface)
711 {
712     isCustomTypeface_ = isCustomTypeface;
713 }
714 
IsCustomTypeface() const715 bool RecordingCanvas::IsCustomTypeface() const
716 {
717     return isCustomTypeface_;
718 }
719 
SetIsRecordCmd(bool isRecordCmd)720 void RecordingCanvas::SetIsRecordCmd(bool isRecordCmd)
721 {
722     isRecordCmd_ = isRecordCmd;
723 }
724 
CheckForLazySave()725 void RecordingCanvas::CheckForLazySave()
726 {
727     if (!saveOpStateStack_.empty() && saveOpStateStack_.top() == LazySaveOp) {
728         Canvas::Save();
729         if (!addDrawOpImmediate_) {
730             cmdList_->AddDrawOp(std::make_shared<SaveOpItem>());
731         } else {
732             cmdList_->AddDrawOp<SaveOpItem::ConstructorHandle>();
733         }
734         saveOpStateStack_.top() = RealSaveOp;
735     }
736 }
737 
ResetHybridRenderSize(float width,float height)738 void RecordingCanvas::ResetHybridRenderSize(float width, float height)
739 {
740     if (cmdList_ == nullptr) {
741         return;
742     }
743     if (!addDrawOpImmediate_) {
744         cmdList_->AddDrawOp(std::make_shared<HybridRenderPixelMapSizeOpItem>(width, height));
745         return;
746     }
747     cmdList_->AddDrawOp<HybridRenderPixelMapSizeOpItem::ConstructorHandle>(width, height);
748 }
749 
750 template<typename T, typename... Args>
AddDrawOpImmediate(Args &&...args)751 void RecordingCanvas::AddDrawOpImmediate(Args&&... args)
752 {
753     if (opCount > 40000) { //image opitems upper limit
754         return;
755     }
756     bool brushValid = paintBrush_.IsValid();
757     bool penValid = paintPen_.IsValid();
758     if (!brushValid && !penValid) {
759         PaintHandle paintHandle;
760         paintHandle.isAntiAlias = true;
761         paintHandle.style = Paint::PaintStyle::PAINT_FILL;
762         cmdList_->AddDrawOp<T>(std::forward<Args>(args)..., paintHandle);
763         return;
764     }
765     if (brushValid && penValid && Paint::CanCombinePaint(paintBrush_, paintPen_)) {
766         PaintHandle paintHandle;
767         paintPen_.SetStyle(Paint::PaintStyle::PAINT_FILL_STROKE);
768         DrawOpItem::GenerateHandleFromPaint(*cmdList_, paintPen_, paintHandle);
769         cmdList_->AddDrawOp<T>(std::forward<Args>(args)..., paintHandle);
770         paintPen_.SetStyle(Paint::PaintStyle::PAINT_STROKE);
771         return;
772     }
773     if (brushValid) {
774         PaintHandle paintHandle;
775         DrawOpItem::GenerateHandleFromPaint(*cmdList_, paintBrush_, paintHandle);
776         cmdList_->AddDrawOp<T>(std::forward<Args>(args)..., paintHandle);
777     }
778     if (penValid) {
779         PaintHandle paintHandle;
780         DrawOpItem::GenerateHandleFromPaint(*cmdList_, paintPen_, paintHandle);
781         cmdList_->AddDrawOp<T>(std::forward<Args>(args)..., paintHandle);
782     }
783 }
784 
785 template<typename T, typename... Args>
AddDrawOpDeferred(Args &&...args)786 void RecordingCanvas::AddDrawOpDeferred(Args&&... args)
787 {
788     bool brushValid = paintBrush_.IsValid();
789     bool penValid = paintPen_.IsValid();
790     if (!brushValid && !penValid) {
791         cmdList_->AddDrawOp(std::make_shared<T>(std::forward<Args>(args)..., defaultPaint_));
792         return;
793     }
794     if (brushValid && penValid && Paint::CanCombinePaint(paintBrush_, paintPen_)) {
795         paintPen_.SetStyle(Paint::PaintStyle::PAINT_FILL_STROKE);
796         cmdList_->AddDrawOp(std::make_shared<T>(std::forward<Args>(args)..., paintPen_));
797         paintPen_.SetStyle(Paint::PaintStyle::PAINT_STROKE);
798         return;
799     }
800     if (brushValid) {
801         cmdList_->AddDrawOp(std::make_shared<T>(std::forward<Args>(args)..., paintBrush_));
802     }
803     if (penValid) {
804         cmdList_->AddDrawOp(std::make_shared<T>(std::forward<Args>(args)..., paintPen_));
805     }
806 }
807 
GenerateCachedOpForTextblob(const TextBlob * blob,const scalar x,const scalar y)808 void RecordingCanvas::GenerateCachedOpForTextblob(const TextBlob* blob, const scalar x, const scalar y)
809 {
810     bool brushValid = paintBrush_.IsValid();
811     bool penValid = paintPen_.IsValid();
812     if (!brushValid && !penValid) {
813         GenerateCachedOpForTextblob(blob, x, y, defaultPaint_);
814         return;
815     }
816     if (brushValid && penValid && Paint::CanCombinePaint(paintBrush_, paintPen_)) {
817         paintPen_.SetStyle(Paint::PaintStyle::PAINT_FILL_STROKE);
818         GenerateCachedOpForTextblob(blob, x, y, paintPen_);
819         paintPen_.SetStyle(Paint::PaintStyle::PAINT_STROKE);
820         return;
821     }
822     if (brushValid) {
823         GenerateCachedOpForTextblob(blob, x, y, paintBrush_);
824     }
825     if (penValid) {
826         GenerateCachedOpForTextblob(blob, x, y, paintPen_);
827     }
828 }
829 
GenerateCachedOpForTextblob(const TextBlob * blob,const scalar x,const scalar y,Paint & paint)830 void RecordingCanvas::GenerateCachedOpForTextblob(const TextBlob* blob, const scalar x, const scalar y, Paint& paint)
831 {
832     if (!addDrawOpImmediate_) {
833         std::shared_ptr<DrawTextBlobOpItem> op = std::make_shared<DrawTextBlobOpItem>(blob, x, y, paint);
834         cmdList_->AddDrawOp(op->GenerateCachedOpItem(nullptr));
835     } else {
836         DrawTextBlobOpItem::ConstructorHandle::GenerateCachedOpItem(*cmdList_, blob, x, y, paint);
837     }
838 }
839 } // namespace Drawing
840 } // namespace Rosen
841 } // namespace OHOS
842