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 (!addDrawOpImmediate_) {
247         cmdList_->AddDrawOp(std::make_shared<DrawImageNineOpItem>(image, center, dst, filterMode, brush));
248         return;
249     }
250 
251     auto imageHandle = CmdListHelper::AddImageToCmdList(*cmdList_, *image);
252     BrushHandle brushHandle;
253     bool hasBrush = false;
254     if (brush != nullptr) {
255         hasBrush = true;
256         DrawOpItem::BrushToBrushHandle(*brush, *cmdList_, brushHandle);
257     }
258 
259     cmdList_->AddDrawOp<DrawImageNineOpItem::ConstructorHandle>(
260         imageHandle, center, dst, filterMode, brushHandle, hasBrush);
261 }
262 
DrawImageLattice(const Image * image,const Lattice & lattice,const Rect & dst,FilterMode filterMode)263 void RecordingCanvas::DrawImageLattice(const Image* image, const Lattice& lattice, const Rect& dst,
264     FilterMode filterMode)
265 {
266     if (!addDrawOpImmediate_) {
267         AddDrawOpDeferred<DrawImageLatticeOpItem>(image, lattice, dst, filterMode);
268         return;
269     }
270 
271     auto imageHandle = CmdListHelper::AddImageToCmdList(*cmdList_, *image);
272     auto latticeHandle = CmdListHelper::AddLatticeToCmdList(*cmdList_, lattice);
273     AddDrawOpImmediate<DrawImageLatticeOpItem::ConstructorHandle>(imageHandle, latticeHandle, dst, filterMode);
274 }
275 
DrawColor(ColorQuad color,BlendMode mode)276 void RecordingCanvas::DrawColor(ColorQuad color, BlendMode mode)
277 {
278     if (!addDrawOpImmediate_) {
279         cmdList_->AddDrawOp(std::make_shared<DrawColorOpItem>(color, mode));
280         return;
281     }
282     cmdList_->AddDrawOp<DrawColorOpItem::ConstructorHandle>(color, mode);
283 }
284 
DrawAtlas(const Image * atlas,const RSXform xform[],const Rect tex[],const ColorQuad colors[],int count,BlendMode mode,const SamplingOptions & sampling,const Rect * cullRect)285 void RecordingCanvas::DrawAtlas(const Image* atlas, const RSXform xform[], const Rect tex[], const ColorQuad colors[],
286     int count, BlendMode mode, const SamplingOptions& sampling, const Rect* cullRect)
287 {
288     if (!atlas) {
289         return;
290     }
291     std::vector<RSXform> xformVec(xform, xform + count);
292     std::vector<Rect> texVec(tex, tex + count);
293     std::vector<ColorQuad> colorVec;
294     if (colors) {
295         colorVec.assign(colors, colors + count);
296     }
297     Rect rect;
298     bool hasCullRect = false;
299     if (cullRect) {
300         rect = *cullRect;
301         hasCullRect = true;
302     }
303     if (!addDrawOpImmediate_) {
304         AddDrawOpDeferred<DrawAtlasOpItem>(atlas, xformVec, texVec, colorVec, mode, sampling, hasCullRect, rect);
305         return;
306     }
307     auto imageHandle = CmdListHelper::AddImageToCmdList(*cmdList_, *atlas);
308     auto xformData = CmdListHelper::AddVectorToCmdList<RSXform>(*cmdList_, xformVec);
309     auto texData = CmdListHelper::AddVectorToCmdList<Rect>(*cmdList_, texVec);
310     auto colorData = CmdListHelper::AddVectorToCmdList<ColorQuad>(*cmdList_, colorVec);
311     AddDrawOpImmediate<DrawAtlasOpItem::ConstructorHandle>(imageHandle, xformData, texData, colorData, mode,
312         sampling, hasCullRect, rect);
313 }
314 
DrawBitmap(const Bitmap & bitmap,const scalar px,const scalar py)315 void RecordingCanvas::DrawBitmap(const Bitmap& bitmap, const scalar px, const scalar py)
316 {
317     auto image = bitmap.MakeImage();
318     if (image) {
319         DrawImage(*image, px, py, SamplingOptions());
320     }
321 }
322 
DrawImage(const Image & image,const scalar px,const scalar py,const SamplingOptions & sampling)323 void RecordingCanvas::DrawImage(const Image& image, const scalar px, const scalar py, const SamplingOptions& sampling)
324 {
325     if (!addDrawOpImmediate_) {
326         AddDrawOpDeferred<DrawImageOpItem>(image, px, py, sampling);
327         return;
328     }
329     opCount++;
330     auto imageHandle = CmdListHelper::AddImageToCmdList(*cmdList_, image);
331     AddDrawOpImmediate<DrawImageOpItem::ConstructorHandle>(imageHandle, px, py, sampling);
332 }
333 
DrawImageRect(const Image & image,const Rect & src,const Rect & dst,const SamplingOptions & sampling,SrcRectConstraint constraint)334 void RecordingCanvas::DrawImageRect(
335     const Image& image, const Rect& src, const Rect& dst, const SamplingOptions& sampling, SrcRectConstraint constraint)
336 {
337     if (!addDrawOpImmediate_) {
338         AddDrawOpDeferred<DrawImageRectOpItem>(image, src, dst, sampling, constraint);
339         return;
340     }
341     opCount++;
342     auto imageHandle = CmdListHelper::AddImageToCmdList(*cmdList_, image);
343     AddDrawOpImmediate<DrawImageRectOpItem::ConstructorHandle>(imageHandle, src, dst, sampling, constraint);
344 }
345 
DrawImageRect(const Image & image,const Rect & dst,const SamplingOptions & sampling)346 void RecordingCanvas::DrawImageRect(const Image& image, const Rect& dst, const SamplingOptions& sampling)
347 {
348     if (!addDrawOpImmediate_) {
349         Rect src(0, 0, image.GetWidth(), image.GetHeight());
350         AddDrawOpDeferred<DrawImageRectOpItem>(image, src, dst, sampling, SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
351         return;
352     }
353     opCount++;
354     auto imageHandle = CmdListHelper::AddImageToCmdList(*cmdList_, image);
355     Rect src(0, 0, image.GetWidth(), image.GetHeight());
356     AddDrawOpImmediate<DrawImageRectOpItem::ConstructorHandle>(
357         imageHandle, src, dst, sampling, SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
358 }
359 
DrawRecordCmd(const std::shared_ptr<RecordCmd> recordCmd,const Matrix * matrix,const Brush * brush)360 void RecordingCanvas::DrawRecordCmd(const std::shared_ptr<RecordCmd> recordCmd,
361     const Matrix* matrix, const Brush* brush)
362 {
363     if (recordCmd == nullptr) {
364         LOGE("RecordingCanvas::DrawRecordCmd, recordCmd is nullptr!");
365         return;
366     }
367     if (isRecordCmd_) {
368         LOGE("RecordingCanvas::DrawRecordCmd, operation is unsupported!");
369         return;
370     }
371     if (!addDrawOpImmediate_) {
372         cmdList_->AddDrawOp(std::make_shared<DrawRecordCmdOpItem>(recordCmd, matrix, brush));
373         return;
374     }
375 
376     BrushHandle brushHandle;
377     bool hasBrush = false;
378     if (brush != nullptr) {
379         hasBrush = true;
380         DrawOpItem::BrushToBrushHandle(*brush, *cmdList_, brushHandle);
381     }
382 
383     Matrix layerMatrix;
384     Matrix::Buffer layerMatrixBuffer;
385     if (matrix != nullptr) {
386         layerMatrix = *matrix;
387     }
388     layerMatrix.GetAll(layerMatrixBuffer);
389     auto recordCmdHandle = CmdListHelper::AddRecordCmdToCmdList(*cmdList_, recordCmd);
390     cmdList_->AddDrawOp<DrawRecordCmdOpItem::ConstructorHandle>(recordCmdHandle,
391         layerMatrixBuffer, hasBrush, brushHandle);
392 }
393 
DrawPicture(const Picture & picture)394 void RecordingCanvas::DrawPicture(const Picture& picture)
395 {
396     if (!addDrawOpImmediate_) {
397         cmdList_->AddDrawOp(std::make_shared<DrawPictureOpItem>(picture));
398         return;
399     }
400     auto pictureHandle = CmdListHelper::AddPictureToCmdList(*cmdList_, picture);
401     cmdList_->AddDrawOp<DrawPictureOpItem::ConstructorHandle>(pictureHandle);
402 }
403 
DrawTextBlob(const TextBlob * blob,const scalar x,const scalar y)404 void RecordingCanvas::DrawTextBlob(const TextBlob* blob, const scalar x, const scalar y)
405 {
406     static uint64_t shiftedPid = static_cast<uint64_t>(GetRealPid()) << 32; // 32 for 64-bit unsignd number shift
407     if (!blob) {
408         return;
409     }
410 #ifdef ROSEN_OHOS
411     if (IsCustomTextType()) {
412         LOGD("RecordingCanvas::DrawTextBlob replace drawOpItem with cached one");
413         GenerateCachedOpForTextblob(blob, x, y);
414         return;
415     }
416 #endif
417     if (!addDrawOpImmediate_) {
418         AddDrawOpDeferred<DrawTextBlobOpItem>(blob, x, y);
419         return;
420     }
421     TextBlob::Context ctx {nullptr, false};
422     auto textBlobHandle = CmdListHelper::AddTextBlobToCmdList(*cmdList_, blob, &ctx);
423     uint64_t globalUniqueId = 0;
424     if (ctx.GetTypeface() != nullptr) {
425         uint32_t typefaceId = ctx.GetTypeface()->GetUniqueID();
426         globalUniqueId = (shiftedPid | typefaceId);
427     }
428     AddDrawOpImmediate<DrawTextBlobOpItem::ConstructorHandle>(textBlobHandle, globalUniqueId, x, y);
429 }
430 
DrawSymbol(const DrawingHMSymbolData & symbol,Point locate)431 void RecordingCanvas::DrawSymbol(const DrawingHMSymbolData& symbol, Point locate)
432 {
433     if (!addDrawOpImmediate_) {
434         AddDrawOpDeferred<DrawSymbolOpItem>(symbol, locate);
435         return;
436     }
437     auto symbolHandle = CmdListHelper::AddSymbolToCmdList(*cmdList_, symbol);
438     AddDrawOpImmediate<DrawSymbolOpItem::ConstructorHandle>(symbolHandle, locate);
439 }
440 
ClipRect(const Rect & rect,ClipOp op,bool doAntiAlias)441 void RecordingCanvas::ClipRect(const Rect& rect, ClipOp op, bool doAntiAlias)
442 {
443     CheckForLazySave();
444     Canvas::ClipRect(rect, op, doAntiAlias);
445     if (!addDrawOpImmediate_) {
446         cmdList_->AddDrawOp(std::make_shared<ClipRectOpItem>(rect, op, doAntiAlias));
447         return;
448     }
449     cmdList_->AddDrawOp<ClipRectOpItem::ConstructorHandle>(rect, op, doAntiAlias);
450 }
451 
ClipIRect(const RectI & rect,ClipOp op)452 void RecordingCanvas::ClipIRect(const RectI& rect, ClipOp op)
453 {
454     CheckForLazySave();
455     Canvas::ClipIRect(rect, op);
456     if (!addDrawOpImmediate_) {
457         cmdList_->AddDrawOp(std::make_shared<ClipIRectOpItem>(rect, op));
458         return;
459     }
460     cmdList_->AddDrawOp<ClipIRectOpItem::ConstructorHandle>(rect, op);
461 }
462 
ClipRoundRect(const RoundRect & roundRect,ClipOp op,bool doAntiAlias)463 void RecordingCanvas::ClipRoundRect(const RoundRect& roundRect, ClipOp op, bool doAntiAlias)
464 {
465     CheckForLazySave();
466     Canvas::ClipRoundRect(roundRect, op, doAntiAlias);
467     if (!addDrawOpImmediate_) {
468         cmdList_->AddDrawOp(std::make_shared<ClipRoundRectOpItem>(roundRect, op, doAntiAlias));
469         return;
470     }
471     cmdList_->AddDrawOp<ClipRoundRectOpItem::ConstructorHandle>(roundRect, op, doAntiAlias);
472 }
473 
ClipRoundRect(const Rect & rect,std::vector<Point> & pts,bool doAntiAlias)474 void RecordingCanvas::ClipRoundRect(const Rect& rect, std::vector<Point>& pts, bool doAntiAlias)
475 {
476     CheckForLazySave();
477     RoundRect roundRect = RoundRect(rect, pts);
478     Canvas::ClipRoundRect(roundRect, ClipOp::INTERSECT, doAntiAlias);
479     if (!addDrawOpImmediate_) {
480         cmdList_->AddDrawOp(std::make_shared<ClipRoundRectOpItem>(roundRect, ClipOp::INTERSECT, doAntiAlias));
481         return;
482     }
483     cmdList_->AddDrawOp<ClipRoundRectOpItem::ConstructorHandle>(roundRect, ClipOp::INTERSECT, doAntiAlias);
484 }
485 
ClipPath(const Path & path,ClipOp op,bool doAntiAlias)486 void RecordingCanvas::ClipPath(const Path& path, ClipOp op, bool doAntiAlias)
487 {
488     CheckForLazySave();
489     Canvas::ClipPath(path, op, doAntiAlias);
490     if (!addDrawOpImmediate_) {
491         cmdList_->AddDrawOp(std::make_shared<ClipPathOpItem>(path, op, doAntiAlias));
492         return;
493     }
494     auto pathHandle = CmdListHelper::AddPathToCmdList(*cmdList_, path);
495     cmdList_->AddDrawOp<ClipPathOpItem::ConstructorHandle>(pathHandle, op, doAntiAlias);
496 }
497 
ClipRegion(const Region & region,ClipOp op)498 void RecordingCanvas::ClipRegion(const Region& region, ClipOp op)
499 {
500     CheckForLazySave();
501     Canvas::ClipRegion(region, op);
502     if (!addDrawOpImmediate_) {
503         cmdList_->AddDrawOp(std::make_shared<ClipRegionOpItem>(region, op));
504         return;
505     }
506     auto regionHandle = CmdListHelper::AddRegionToCmdList(*cmdList_, region);
507     cmdList_->AddDrawOp<ClipRegionOpItem::ConstructorHandle>(regionHandle, op);
508 }
509 
SetMatrix(const Matrix & matrix)510 void RecordingCanvas::SetMatrix(const Matrix& matrix)
511 {
512     CheckForLazySave();
513     Canvas::SetMatrix(matrix);
514     if (!addDrawOpImmediate_) {
515         cmdList_->AddDrawOp(std::make_shared<SetMatrixOpItem>(matrix));
516         return;
517     }
518     Matrix::Buffer matrixBuffer;
519     matrix.GetAll(matrixBuffer);
520     cmdList_->AddDrawOp<SetMatrixOpItem::ConstructorHandle>(matrixBuffer);
521 }
522 
ResetMatrix()523 void RecordingCanvas::ResetMatrix()
524 {
525     CheckForLazySave();
526     Canvas::ResetMatrix();
527     if (!addDrawOpImmediate_) {
528         cmdList_->AddDrawOp(std::make_shared<ResetMatrixOpItem>());
529         return;
530     }
531     cmdList_->AddDrawOp<ResetMatrixOpItem::ConstructorHandle>();
532 }
533 
ConcatMatrix(const Matrix & matrix)534 void RecordingCanvas::ConcatMatrix(const Matrix& matrix)
535 {
536     if (!matrix.IsIdentity()) {
537         CheckForLazySave();
538         Canvas::ConcatMatrix(matrix);
539         if (!addDrawOpImmediate_) {
540             cmdList_->AddDrawOp(std::make_shared<ConcatMatrixOpItem>(matrix));
541             return;
542         }
543         Matrix::Buffer matrixBuffer;
544         matrix.GetAll(matrixBuffer);
545         cmdList_->AddDrawOp<ConcatMatrixOpItem::ConstructorHandle>(matrixBuffer);
546     }
547 }
548 
Translate(scalar dx,scalar dy)549 void RecordingCanvas::Translate(scalar dx, scalar dy)
550 {
551     if (dx || dy) {
552         CheckForLazySave();
553         Canvas::Translate(dx, dy);
554         if (!addDrawOpImmediate_) {
555             cmdList_->AddDrawOp(std::make_shared<TranslateOpItem>(dx, dy));
556             return;
557         }
558         cmdList_->AddDrawOp<TranslateOpItem::ConstructorHandle>(dx, dy);
559     }
560 }
561 
Scale(scalar sx,scalar sy)562 void RecordingCanvas::Scale(scalar sx, scalar sy)
563 {
564     if (sx != 1 || sy != 1) {
565         CheckForLazySave();
566         Canvas::Scale(sx, sy);
567         if (!addDrawOpImmediate_) {
568             cmdList_->AddDrawOp(std::make_shared<ScaleOpItem>(sx, sy));
569             return;
570         }
571         cmdList_->AddDrawOp<ScaleOpItem::ConstructorHandle>(sx, sy);
572     }
573 }
574 
Rotate(scalar deg,scalar sx,scalar sy)575 void RecordingCanvas::Rotate(scalar deg, scalar sx, scalar sy)
576 {
577     if (deg) {
578         CheckForLazySave();
579         Canvas::Rotate(deg, sx, sy);
580         if (!addDrawOpImmediate_) {
581             cmdList_->AddDrawOp(std::make_shared<RotateOpItem>(deg, sx, sy));
582             return;
583         }
584         cmdList_->AddDrawOp<RotateOpItem::ConstructorHandle>(deg, sx, sy);
585     }
586 }
587 
Shear(scalar sx,scalar sy)588 void RecordingCanvas::Shear(scalar sx, scalar sy)
589 {
590     if (sx || sy) {
591         CheckForLazySave();
592         Canvas::Shear(sx, sy);
593         if (!addDrawOpImmediate_) {
594             cmdList_->AddDrawOp(std::make_shared<ShearOpItem>(sx, sy));
595             return;
596         }
597         cmdList_->AddDrawOp<ShearOpItem::ConstructorHandle>(sx, sy);
598     }
599 }
600 
Flush()601 void RecordingCanvas::Flush()
602 {
603     if (!addDrawOpImmediate_) {
604         cmdList_->AddDrawOp(std::make_shared<FlushOpItem>());
605         return;
606     }
607     cmdList_->AddDrawOp<FlushOpItem::ConstructorHandle>();
608 }
609 
Clear(ColorQuad color)610 void RecordingCanvas::Clear(ColorQuad color)
611 {
612     if (!addDrawOpImmediate_) {
613         cmdList_->AddDrawOp(std::make_shared<ClearOpItem>(color));
614         return;
615     }
616     cmdList_->AddDrawOp<ClearOpItem::ConstructorHandle>(color);
617 }
618 
Save()619 uint32_t RecordingCanvas::Save()
620 {
621     uint32_t ret = static_cast<uint32_t>(saveOpStateStack_.size());
622     saveOpStateStack_.push(LazySaveOp);
623     return ret + 1; // The minimum value for non-recording types is 1
624 }
625 
SaveLayer(const SaveLayerOps & saveLayerOps)626 void RecordingCanvas::SaveLayer(const SaveLayerOps& saveLayerOps)
627 {
628     Canvas::SaveLayer(saveLayerOps);
629     saveOpStateStack_.push(RealSaveOp);
630     if (!addDrawOpImmediate_) {
631         cmdList_->AddDrawOp(std::make_shared<SaveLayerOpItem>(saveLayerOps));
632         return;
633     }
634 
635     Rect rect;
636     bool hasBrush = false;
637     BrushHandle brushHandle;
638 
639     if (saveLayerOps.GetBounds() != nullptr) {
640         rect = *saveLayerOps.GetBounds();
641     }
642     const Brush* brush = saveLayerOps.GetBrush();
643     if (brush != nullptr) {
644         hasBrush = true;
645         DrawOpItem::BrushToBrushHandle(*brush, *cmdList_, brushHandle);
646     }
647 
648     cmdList_->AddDrawOp<SaveLayerOpItem::ConstructorHandle>(rect, hasBrush, brushHandle,
649         saveLayerOps.GetSaveLayerFlags());
650 }
651 
Restore()652 void RecordingCanvas::Restore()
653 {
654     if (saveOpStateStack_.empty()) {
655         return;
656     }
657 
658     SaveOpState state = saveOpStateStack_.top();
659     saveOpStateStack_.pop();
660     if (state == RealSaveOp) {
661         Canvas::Restore();
662         if (!addDrawOpImmediate_) {
663             cmdList_->AddDrawOp(std::make_shared<RestoreOpItem>());
664             return;
665         }
666         cmdList_->AddDrawOp<RestoreOpItem::ConstructorHandle>();
667     }
668 }
669 
GetSaveCount() const670 uint32_t RecordingCanvas::GetSaveCount() const
671 {
672     return static_cast<uint32_t>(saveOpStateStack_.size()) + 1; // The minimum value for non-recording types is 1
673 }
674 
Discard()675 void RecordingCanvas::Discard()
676 {
677     if (!addDrawOpImmediate_) {
678         cmdList_->AddDrawOp(std::make_shared<DiscardOpItem>());
679         return;
680     }
681     cmdList_->AddDrawOp<DiscardOpItem::ConstructorHandle>();
682 }
683 
ClipAdaptiveRoundRect(const std::vector<Point> & radius)684 void RecordingCanvas::ClipAdaptiveRoundRect(const std::vector<Point>& radius)
685 {
686     if (!addDrawOpImmediate_) {
687         cmdList_->AddDrawOp(std::make_shared<ClipAdaptiveRoundRectOpItem>(radius));
688         return;
689     }
690     auto radiusData = CmdListHelper::AddVectorToCmdList<Point>(*cmdList_, radius);
691     cmdList_->AddDrawOp<ClipAdaptiveRoundRectOpItem::ConstructorHandle>(radiusData);
692 }
693 
SetIsCustomTextType(bool isCustomTextType)694 void RecordingCanvas::SetIsCustomTextType(bool isCustomTextType)
695 {
696     isCustomTextType_ = isCustomTextType;
697 }
698 
IsCustomTextType() const699 bool RecordingCanvas::IsCustomTextType() const
700 {
701     return isCustomTextType_;
702 }
703 
SetIsCustomTypeface(bool isCustomTypeface)704 void RecordingCanvas::SetIsCustomTypeface(bool isCustomTypeface)
705 {
706     isCustomTypeface_ = isCustomTypeface;
707 }
708 
IsCustomTypeface() const709 bool RecordingCanvas::IsCustomTypeface() const
710 {
711     return isCustomTypeface_;
712 }
713 
SetIsRecordCmd(bool isRecordCmd)714 void RecordingCanvas::SetIsRecordCmd(bool isRecordCmd)
715 {
716     isRecordCmd_ = isRecordCmd;
717 }
718 
CheckForLazySave()719 void RecordingCanvas::CheckForLazySave()
720 {
721     if (!saveOpStateStack_.empty() && saveOpStateStack_.top() == LazySaveOp) {
722         Canvas::Save();
723         if (!addDrawOpImmediate_) {
724             cmdList_->AddDrawOp(std::make_shared<SaveOpItem>());
725         } else {
726             cmdList_->AddDrawOp<SaveOpItem::ConstructorHandle>();
727         }
728         saveOpStateStack_.top() = RealSaveOp;
729     }
730 }
731 
732 template<typename T, typename... Args>
AddDrawOpImmediate(Args &&...args)733 void RecordingCanvas::AddDrawOpImmediate(Args&&... args)
734 {
735     if (opCount > 40000) { //image opitems upper limit
736         return;
737     }
738     bool brushValid = paintBrush_.IsValid();
739     bool penValid = paintPen_.IsValid();
740     if (!brushValid && !penValid) {
741         PaintHandle paintHandle;
742         paintHandle.isAntiAlias = true;
743         paintHandle.style = Paint::PaintStyle::PAINT_FILL;
744         cmdList_->AddDrawOp<T>(std::forward<Args>(args)..., paintHandle);
745         return;
746     }
747     if (brushValid && penValid && Paint::CanCombinePaint(paintBrush_, paintPen_)) {
748         PaintHandle paintHandle;
749         paintPen_.SetStyle(Paint::PaintStyle::PAINT_FILL_STROKE);
750         DrawOpItem::GenerateHandleFromPaint(*cmdList_, paintPen_, paintHandle);
751         cmdList_->AddDrawOp<T>(std::forward<Args>(args)..., paintHandle);
752         paintPen_.SetStyle(Paint::PaintStyle::PAINT_STROKE);
753         return;
754     }
755     if (brushValid) {
756         PaintHandle paintHandle;
757         DrawOpItem::GenerateHandleFromPaint(*cmdList_, paintBrush_, paintHandle);
758         cmdList_->AddDrawOp<T>(std::forward<Args>(args)..., paintHandle);
759     }
760     if (penValid) {
761         PaintHandle paintHandle;
762         DrawOpItem::GenerateHandleFromPaint(*cmdList_, paintPen_, paintHandle);
763         cmdList_->AddDrawOp<T>(std::forward<Args>(args)..., paintHandle);
764     }
765 }
766 
767 template<typename T, typename... Args>
AddDrawOpDeferred(Args &&...args)768 void RecordingCanvas::AddDrawOpDeferred(Args&&... args)
769 {
770     bool brushValid = paintBrush_.IsValid();
771     bool penValid = paintPen_.IsValid();
772     if (!brushValid && !penValid) {
773         cmdList_->AddDrawOp(std::make_shared<T>(std::forward<Args>(args)..., defaultPaint_));
774         return;
775     }
776     if (brushValid && penValid && Paint::CanCombinePaint(paintBrush_, paintPen_)) {
777         paintPen_.SetStyle(Paint::PaintStyle::PAINT_FILL_STROKE);
778         cmdList_->AddDrawOp(std::make_shared<T>(std::forward<Args>(args)..., paintPen_));
779         paintPen_.SetStyle(Paint::PaintStyle::PAINT_STROKE);
780         return;
781     }
782     if (brushValid) {
783         cmdList_->AddDrawOp(std::make_shared<T>(std::forward<Args>(args)..., paintBrush_));
784     }
785     if (penValid) {
786         cmdList_->AddDrawOp(std::make_shared<T>(std::forward<Args>(args)..., paintPen_));
787     }
788 }
789 
GenerateCachedOpForTextblob(const TextBlob * blob,const scalar x,const scalar y)790 void RecordingCanvas::GenerateCachedOpForTextblob(const TextBlob* blob, const scalar x, const scalar y)
791 {
792     bool brushValid = paintBrush_.IsValid();
793     bool penValid = paintPen_.IsValid();
794     if (!brushValid && !penValid) {
795         GenerateCachedOpForTextblob(blob, x, y, defaultPaint_);
796         return;
797     }
798     if (brushValid && penValid && Paint::CanCombinePaint(paintBrush_, paintPen_)) {
799         paintPen_.SetStyle(Paint::PaintStyle::PAINT_FILL_STROKE);
800         GenerateCachedOpForTextblob(blob, x, y, paintPen_);
801         paintPen_.SetStyle(Paint::PaintStyle::PAINT_STROKE);
802         return;
803     }
804     if (brushValid) {
805         GenerateCachedOpForTextblob(blob, x, y, paintBrush_);
806     }
807     if (penValid) {
808         GenerateCachedOpForTextblob(blob, x, y, paintPen_);
809     }
810 }
811 
GenerateCachedOpForTextblob(const TextBlob * blob,const scalar x,const scalar y,Paint & paint)812 void RecordingCanvas::GenerateCachedOpForTextblob(const TextBlob* blob, const scalar x, const scalar y, Paint& paint)
813 {
814     if (!addDrawOpImmediate_) {
815         std::shared_ptr<DrawTextBlobOpItem> op = std::make_shared<DrawTextBlobOpItem>(blob, x, y, paint);
816         cmdList_->AddDrawOp(op->GenerateCachedOpItem(nullptr));
817     } else {
818         DrawTextBlobOpItem::ConstructorHandle::GenerateCachedOpItem(*cmdList_, blob, x, y, paint);
819     }
820 }
821 } // namespace Drawing
822 } // namespace Rosen
823 } // namespace OHOS
824