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