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