41std::optional<std::pair<DlRoundRect, DlPaint>> DiffRoundRectToRoundRect(
44 const DlPaint& paint) {
52 const DlRect& outer_bounds = outer.GetBounds();
53 const DlRect& inner_bounds = inner.GetBounds();
54 const DlScalar stroke_width = inner_bounds.
GetLeft() - outer_bounds.GetLeft();
60 if (stroke_width <= 0) {
77 if (!outer_radii.AreAllCornersCircular() ||
78 !inner_radii.AreAllCornersCircular()) {
84 outer_radii.top_left.width - inner_radii.top_left.width,
87 outer_radii.top_right.width - inner_radii.top_right.width,
90 outer_radii.bottom_left.width - inner_radii.bottom_left.width,
93 outer_radii.bottom_right.width - inner_radii.bottom_right.width,
102 const DlScalar half_stroke_width = stroke_width * 0.5f;
104 inner_bounds.Expand(half_stroke_width),
106 DlSize(inner_radii.top_left.width + half_stroke_width),
107 DlSize(inner_radii.top_right.width + half_stroke_width),
108 DlSize(inner_radii.bottom_left.width + half_stroke_width),
109 DlSize(inner_radii.bottom_right.width + half_stroke_width),
112 return std::make_pair(stroked_rrect, stroke_paint);
120template <
typename S,
typename... Rest>
121static void CopyV(
void* dst,
const S* src,
int n, Rest&&... rest) {
122 FML_DCHECK(((uintptr_t)dst & (
alignof(S) - 1)) == 0)
123 <<
"Expected " << dst <<
" to be aligned for at least " <<
alignof(S)
127 memcpy(dst, src, n *
sizeof(S));
128 dst =
reinterpret_cast<void*
>(
reinterpret_cast<uint8_t*
>(dst) +
132 CopyV(dst, std::forward<Rest>(rest)...);
135template <
typename T,
typename... Args>
136void* DisplayListBuilder::Push(
size_t pod, Args&&...
args) {
138 size_t size = SkAlignPtr(
sizeof(T) + pod);
139 size_t offset = storage_.
size();
146 auto op =
reinterpret_cast<T*
>(ptr);
147 new (op) T{std::forward<Args>(
args)...};
153 offsets_.push_back(offset);
154 render_op_count_ += T::kRenderOpInc;
155 depth_ += T::kDepthInc * render_op_depth_cost_;
162 while (save_stack_.size() > 1) {
166 int count = render_op_count_;
167 size_t nested_bytes = nested_bytes_;
168 int nested_count = nested_op_count_;
169 uint32_t total_depth = depth_;
170 bool opacity_compatible = current_layer().is_group_opacity_compatible();
171 bool is_safe = is_ui_thread_safe_;
172 bool affects_transparency = current_layer().affects_transparent_layer;
173 bool root_has_backdrop_filter = current_layer().contains_backdrop_filter;
174 bool root_is_unbounded = current_layer().is_unbounded;
175 DlBlendMode max_root_blend_mode = current_layer().max_blend_mode;
177 sk_sp<DlRTree> rtree;
179 if (rtree_data_.has_value()) {
180 auto& rects = rtree_data_->rects;
181 auto& indices = rtree_data_->indices;
182 rtree = sk_make_sp<DlRTree>(rects.data(), rects.size(), indices.data(),
183 [](
int id) { return id >= 0; });
187 bounds = rtree->bounds();
190 bounds = current_layer().global_space_accumulator.GetBounds();
193 render_op_count_ = op_index_ = 0;
194 nested_bytes_ = nested_op_count_ = 0;
196 is_ui_thread_safe_ =
true;
197 current_opacity_compatibility_ =
true;
198 render_op_depth_cost_ = 1u;
201 save_stack_.pop_back();
202 Init(rtree !=
nullptr);
206 std::vector<size_t> offsets;
207 std::swap(offsets, offsets_);
208 std::swap(storage, storage_);
211 std::move(storage), std::move(offsets), count, nested_bytes, nested_count,
212 total_depth, bounds, opacity_compatible, is_safe, affects_transparency,
213 max_root_blend_mode, root_has_backdrop_filter, root_is_unbounded,
230void DisplayListBuilder::Init(
bool prepare_rtree) {
234 save_stack_.emplace_back(original_cull_rect_);
235 current_info().is_nop = original_cull_rect_.
IsEmpty();
237 rtree_data_.emplace();
242 DisplayList::DisposeOps(storage_, offsets_);
246 return offsets_.size();
250 return offsets_.empty();
259 return SkImageInfo::MakeUnknown(
size.width,
size.height);
262void DisplayListBuilder::onSetAntiAlias(
bool aa) {
264 Push<SetAntiAliasOp>(0, aa);
266void DisplayListBuilder::onSetInvertColors(
bool invert) {
268 Push<SetInvertColorsOp>(0, invert);
269 UpdateCurrentOpacityCompatibility();
271void DisplayListBuilder::onSetStrokeCap(
DlStrokeCap cap) {
273 Push<SetStrokeCapOp>(0, cap);
275void DisplayListBuilder::onSetStrokeJoin(
DlStrokeJoin join) {
277 Push<SetStrokeJoinOp>(0, join);
279void DisplayListBuilder::onSetDrawStyle(
DlDrawStyle style) {
281 Push<SetStyleOp>(0, style);
283void DisplayListBuilder::onSetStrokeWidth(
float width) {
285 Push<SetStrokeWidthOp>(0,
width);
287void DisplayListBuilder::onSetStrokeMiter(
float limit) {
289 Push<SetStrokeMiterOp>(0, limit);
291void DisplayListBuilder::onSetColor(DlColor color) {
293 Push<SetColorOp>(0, color);
295void DisplayListBuilder::onSetBlendMode(
DlBlendMode mode) {
297 Push<SetBlendModeOp>(0, mode);
298 UpdateCurrentOpacityCompatibility();
301void DisplayListBuilder::onSetColorSource(
const DlColorSource* source) {
302 if (source ==
nullptr) {
304 Push<ClearColorSourceOp>(0);
307 is_ui_thread_safe_ = is_ui_thread_safe_ && source->isUIThreadSafe();
308 switch (source->type()) {
310 const DlImageColorSource* image_source = source->asImage();
312 Push<SetImageColorSourceOp>(0, image_source);
316 const DlLinearGradientColorSource* linear = source->asLinearGradient();
318 void* pod = Push<SetPodColorSourceOp>(linear->size());
319 new (pod) DlLinearGradientColorSource(linear);
323 const DlRadialGradientColorSource* radial = source->asRadialGradient();
325 void* pod = Push<SetPodColorSourceOp>(radial->size());
326 new (pod) DlRadialGradientColorSource(radial);
330 const DlConicalGradientColorSource* conical =
331 source->asConicalGradient();
333 void* pod = Push<SetPodColorSourceOp>(conical->size());
334 new (pod) DlConicalGradientColorSource(conical);
338 const DlSweepGradientColorSource* sweep = source->asSweepGradient();
340 void* pod = Push<SetPodColorSourceOp>(sweep->size());
341 new (pod) DlSweepGradientColorSource(sweep);
345 const DlRuntimeEffectColorSource* effect = source->asRuntimeEffect();
347 Push<SetRuntimeEffectColorSourceOp>(0, effect);
352 UpdateCurrentOpacityCompatibility();
354void DisplayListBuilder::onSetImageFilter(
const DlImageFilter* filter) {
355 if (filter ==
nullptr) {
357 Push<ClearImageFilterOp>(0);
360 switch (filter->type()) {
362 const DlBlurImageFilter* blur_filter = filter->asBlur();
364 void* pod = Push<SetPodImageFilterOp>(blur_filter->size());
365 new (pod) DlBlurImageFilter(blur_filter);
369 const DlDilateImageFilter* dilate_filter = filter->asDilate();
371 void* pod = Push<SetPodImageFilterOp>(dilate_filter->size());
372 new (pod) DlDilateImageFilter(dilate_filter);
376 const DlErodeImageFilter* erode_filter = filter->asErode();
378 void* pod = Push<SetPodImageFilterOp>(erode_filter->size());
379 new (pod) DlErodeImageFilter(erode_filter);
383 const DlMatrixImageFilter* matrix_filter = filter->asMatrix();
385 void* pod = Push<SetPodImageFilterOp>(matrix_filter->size());
386 new (pod) DlMatrixImageFilter(matrix_filter);
393 Push<SetSharedImageFilterOp>(0, filter);
398 UpdateCurrentOpacityCompatibility();
400void DisplayListBuilder::onSetColorFilter(
const DlColorFilter* filter) {
401 if (filter ==
nullptr) {
403 Push<ClearColorFilterOp>(0);
406 switch (filter->type()) {
408 const DlBlendColorFilter* blend_filter = filter->asBlend();
410 void* pod = Push<SetPodColorFilterOp>(blend_filter->size());
411 new (pod) DlBlendColorFilter(blend_filter);
415 const DlMatrixColorFilter* matrix_filter = filter->asMatrix();
417 void* pod = Push<SetPodColorFilterOp>(matrix_filter->size());
418 new (pod) DlMatrixColorFilter(matrix_filter);
422 void* pod = Push<SetPodColorFilterOp>(filter->size());
423 new (pod) DlSrgbToLinearGammaColorFilter();
427 void* pod = Push<SetPodColorFilterOp>(filter->size());
428 new (pod) DlLinearToSrgbGammaColorFilter();
433 UpdateCurrentOpacityCompatibility();
435void DisplayListBuilder::onSetMaskFilter(
const DlMaskFilter* filter) {
436 if (filter ==
nullptr) {
438 render_op_depth_cost_ = 1u;
439 Push<ClearMaskFilterOp>(0);
442 render_op_depth_cost_ = 2u;
443 switch (filter->type()) {
445 const DlBlurMaskFilter* blur_filter = filter->asBlur();
447 void* pod = Push<SetPodMaskFilterOp>(blur_filter->size());
448 new (pod) DlBlurMaskFilter(blur_filter);
455void DisplayListBuilder::SetAttributesFromPaint(
456 const DlPaint& paint,
457 const DisplayListAttributeFlags flags) {
458 if (flags.applies_anti_alias()) {
459 setAntiAlias(paint.isAntiAlias());
461 if (flags.applies_alpha_or_color()) {
462 setColor(paint.getColor());
464 if (flags.applies_blend()) {
465 setBlendMode(paint.getBlendMode());
467 if (flags.applies_style()) {
468 setDrawStyle(paint.getDrawStyle());
470 if (flags.is_stroked(paint.getDrawStyle())) {
471 setStrokeWidth(paint.getStrokeWidth());
472 setStrokeMiter(paint.getStrokeMiter());
473 setStrokeCap(paint.getStrokeCap());
474 setStrokeJoin(paint.getStrokeJoin());
476 if (flags.applies_shader()) {
477 setColorSource(paint.getColorSourcePtr());
479 if (flags.applies_color_filter()) {
480 setInvertColors(paint.isInvertColors());
481 setColorFilter(paint.getColorFilterPtr());
483 if (flags.applies_image_filter()) {
484 setImageFilter(paint.getImageFilterPtr());
486 if (flags.applies_mask_filter()) {
487 setMaskFilter(paint.getMaskFilterPtr());
491void DisplayListBuilder::checkForDeferredSave() {
492 if (current_info().has_deferred_save_op) {
493 size_t save_offset = storage_.
size();
495 current_info().save_offset = save_offset;
496 current_info().save_depth = depth_;
497 current_info().has_deferred_save_op =
false;
502 bool was_nop = current_info().is_nop;
503 save_stack_.emplace_back(¤t_info());
504 current_info().is_nop = was_nop;
507 FML_DCHECK(current_info().has_deferred_save_op);
510void DisplayListBuilder::saveLayer(
const DlRect& bounds,
513 std::optional<int64_t> backdrop_id) {
518 OpResult result = PaintResult(current_, flags);
519 if (result == OpResult::kNoEffect) {
527 current_info().is_nop =
true;
531 if (backdrop !=
nullptr) {
532 current_layer().contains_backdrop_filter =
true;
538 size_t save_offset = storage_.
size();
539 uint32_t save_depth = depth_;
542 bool will_be_unbounded = (backdrop !=
nullptr);
543 std::shared_ptr<DlImageFilter> filter;
546 if (!paint_nops_on_transparency()) {
548 will_be_unbounded =
true;
551 CheckLayerOpacityCompatibility(
true);
552 UpdateLayerResult(result,
true);
554 CheckLayerOpacityCompatibility(
false);
555 UpdateLayerResult(result,
false);
566 if (will_be_unbounded) {
567 AccumulateUnbounded();
574 rtree_data_.has_value() ? rtree_data_->rects.size() : 0u;
576 save_stack_.emplace_back(¤t_info(), filter, rtree_index);
579 FML_DCHECK(!current_info().has_deferred_save_op);
580 current_info().save_offset = save_offset;
581 current_info().save_depth = save_depth;
588 current_info().global_state.GetDeviceCullCoverage();
589 DlMatrix matrix = current_info().global_state.matrix();
593 if (filter->get_input_device_bounds(output_bounds, matrix,
595 current_info().global_state.resetDeviceCullRect(
601 current_info().global_state.resetDeviceCullRect(
kMaxCullRect);
619 record_bounds = bounds;
625 Push<SaveLayerBackdropOp>(0, options, record_bounds, backdrop,
628 Push<SaveLayerOp>(0, options, record_bounds);
637 if (!current_opacity_compatibility_ || filter) {
638 UpdateLayerOpacityCompatibility(
false);
645 std::optional<int64_t> backdrop_id) {
648 if (bounds.has_value()) {
650 temp_bounds = *bounds;
654 if (paint !=
nullptr) {
656 SetAttributesFromPaint(*paint,
659 saveLayer(temp_bounds, options, backdrop, backdrop_id);
663 if (save_stack_.size() <= 1) {
667 if (!current_info().has_deferred_save_op) {
669 current_info().save_offset);
671 op->
type == DisplayListOpType::kSaveLayer ||
672 op->
type == DisplayListOpType::kSaveLayerBackdrop);
677 if (current_info().is_save_layer) {
689 save_stack_.pop_back();
692void DisplayListBuilder::RestoreLayer() {
695 FML_DCHECK(!current_info().has_deferred_save_op);
700 depth_ += render_op_depth_cost_;
702 DlRect content_bounds = current_layer().layer_local_accumulator.GetBounds();
705 storage_.
base() + current_info().save_offset);
707 layer_op->
type == DisplayListOpType::kSaveLayerBackdrop);
711 if (!content_bounds.
IsEmpty() && !user_bounds.
Contains(content_bounds)) {
716 layer_op->
rect = content_bounds;
719 if (current_layer().contains_backdrop_filter) {
723 if (current_layer().is_group_opacity_compatible()) {
727 if (current_layer().is_unbounded) {
734 TransferLayerBounds(content_bounds);
768void DisplayListBuilder::TransferLayerBounds(
const DlRect& content_bounds) {
769 auto& filter = current_layer().filter;
775 current_layer().global_space_accumulator.is_empty());
777 parent_info().AccumulateBoundsLocal(content_bounds);
778 parent_layer().global_space_accumulator.accumulate(
779 current_layer().global_space_accumulator);
783 bool parent_is_flooded =
false;
784 DlRect bounds_for_parent = content_bounds;
791 const DlRect clip = parent_info().global_state.GetDeviceCullCoverage();
792 const DlMatrix matrix = parent_info().global_state.matrix();
794 if (rtree_data_.has_value()) {
797 FML_DCHECK(current_layer().global_space_accumulator.is_empty());
798 FML_DCHECK(parent_layer().global_space_accumulator.is_empty());
811 if (AdjustRTreeRects(rtree_data_.value(), *filter, matrix, clip,
812 current_layer().rtree_rects_start_index)) {
813 parent_is_flooded =
true;
816 DlRect global_bounds = current_layer().global_space_accumulator.GetBounds();
817 if (!global_bounds.IsEmpty()) {
819 if (!filter->map_device_bounds(global_ibounds, matrix, global_ibounds)) {
820 parent_is_flooded =
true;
823 std::optional<DlRect> clipped_bounds = global_bounds.Intersection(clip);
824 if (clipped_bounds.has_value()) {
825 parent_layer().global_space_accumulator.accumulate(
826 clipped_bounds.value());
842 if (!parent_is_flooded && !bounds_for_parent.IsEmpty()) {
843 DlRect mappable_bounds = bounds_for_parent;
844 if (filter->map_local_bounds(mappable_bounds, mappable_bounds)) {
845 bounds_for_parent = mappable_bounds;
847 parent_is_flooded =
true;
851 if (parent_is_flooded) {
861 AccumulateUnbounded(parent_info());
863 parent_info().AccumulateBoundsLocal(bounds_for_parent);
867bool DisplayListBuilder::AdjustRTreeRects(RTreeData&
data,
868 const DlImageFilter& filter,
871 size_t rect_start_index) {
872 auto& rects =
data.rects;
873 auto& indices =
data.indices;
876 auto rect_keep = rect_start_index;
877 for (
size_t i = rect_start_index;
i < rects.size();
i++) {
880 if (filter.map_device_bounds(ibounds, matrix, ibounds)) {
886 auto clipped_bounds = bounds.Intersection(clip);
887 if (clipped_bounds.has_value()) {
888 indices[rect_keep] = indices[
i];
889 rects[rect_keep] = clipped_bounds.value();
893 indices.resize(rect_keep);
894 rects.resize(rect_keep);
906 if (std::isfinite(tx) && std::isfinite(ty) && (tx != 0.0 || ty != 0.0)) {
907 checkForDeferredSave();
908 Push<TranslateOp>(0, tx, ty);
914 if (std::isfinite(sx) && std::isfinite(sy) && (sx != 1.0 || sy != 1.0)) {
915 checkForDeferredSave();
916 Push<ScaleOp>(0, sx, sy);
917 global_state().
scale(sx, sy);
918 layer_local_state().
scale(sx, sy);
922 if (SkScalarMod(degrees, 360.0) != 0.0) {
923 checkForDeferredSave();
924 Push<RotateOp>(0, degrees);
930 if (std::isfinite(sx) && std::isfinite(sy) && (sx != 0.0 || sy != 0.0)) {
931 checkForDeferredSave();
932 Push<SkewOp>(0, sx, sy);
933 global_state().
skew(sx, sy);
934 layer_local_state().
skew(sx, sy);
944 if (std::isfinite(mxx) && std::isfinite(myx) &&
945 std::isfinite(mxy) && std::isfinite(myy) &&
946 std::isfinite(mxt) && std::isfinite(myt)) {
947 if (mxx == 1 && mxy == 0 &&
948 myx == 0 && myy == 1) {
951 checkForDeferredSave();
952 Push<Transform2DAffineOp>(0,
970 mzx == 0 && mzy == 0 && mzz == 1 && mzt == 0 &&
971 mwx == 0 && mwy == 0 && mwz == 0 && mwt == 1) {
972 transform2DAffine(mxx, mxy, mxt,
974 }
else if (std::isfinite(mxx) && std::isfinite(mxy) &&
975 std::isfinite(mxz) && std::isfinite(mxt) &&
976 std::isfinite(myx) && std::isfinite(myy) &&
977 std::isfinite(myz) && std::isfinite(myt) &&
978 std::isfinite(mzx) && std::isfinite(mzy) &&
979 std::isfinite(mzz) && std::isfinite(mzt) &&
980 std::isfinite(mwx) && std::isfinite(mwy) &&
981 std::isfinite(mwz) && std::isfinite(mwt)) {
982 checkForDeferredSave();
983 Push<TransformFullPerspectiveOp>(0,
1000 checkForDeferredSave();
1001 Push<TransformResetOp>(0);
1014 if (!layer_local_state().inverseTransform(global_state())) {
1027 matrix.
e[0][0], matrix.
e[1][0], matrix.
e[2][0], matrix.
e[3][0],
1028 matrix.
e[0][1], matrix.
e[1][1], matrix.
e[2][1], matrix.
e[3][1],
1029 matrix.
e[0][2], matrix.
e[1][2], matrix.
e[2][2], matrix.
e[3][2],
1030 matrix.
e[0][3], matrix.
e[1][3], matrix.
e[2][3], matrix.
e[3][3]);
1039 if (current_info().is_nop) {
1043 layer_local_state().rect_covers_cull(rect)) {
1046 global_state().
clipRect(rect, clip_op, is_aa);
1047 layer_local_state().
clipRect(rect, clip_op, is_aa);
1048 if (global_state().is_cull_rect_empty() ||
1049 layer_local_state().is_cull_rect_empty()) {
1050 current_info().is_nop =
true;
1053 current_info().has_valid_clip =
true;
1054 checkForDeferredSave();
1057 Push<ClipIntersectRectOp>(0, rect, is_aa);
1060 Push<ClipDifferenceRectOp>(0, rect, is_aa);
1070 if (current_info().is_nop) {
1074 layer_local_state().oval_covers_cull(bounds)) {
1077 global_state().
clipOval(bounds, clip_op, is_aa);
1078 layer_local_state().
clipOval(bounds, clip_op, is_aa);
1079 if (global_state().is_cull_rect_empty() ||
1080 layer_local_state().is_cull_rect_empty()) {
1081 current_info().is_nop =
true;
1084 current_info().has_valid_clip =
true;
1085 checkForDeferredSave();
1088 Push<ClipIntersectOvalOp>(0, bounds, is_aa);
1091 Push<ClipDifferenceOvalOp>(0, bounds, is_aa);
1106 if (current_info().is_nop) {
1110 layer_local_state().rrect_covers_cull(rrect)) {
1113 global_state().
clipRRect(rrect, clip_op, is_aa);
1114 layer_local_state().
clipRRect(rrect, clip_op, is_aa);
1115 if (global_state().is_cull_rect_empty() ||
1116 layer_local_state().is_cull_rect_empty()) {
1117 current_info().is_nop =
true;
1120 current_info().has_valid_clip =
true;
1121 checkForDeferredSave();
1124 Push<ClipIntersectRoundRectOp>(0, rrect, is_aa);
1127 Push<ClipDifferenceRoundRectOp>(0, rrect, is_aa);
1142 if (current_info().is_nop) {
1146 layer_local_state().rsuperellipse_covers_cull(rse)) {
1151 if (global_state().is_cull_rect_empty() ||
1152 layer_local_state().is_cull_rect_empty()) {
1153 current_info().is_nop =
true;
1156 current_info().has_valid_clip =
true;
1157 checkForDeferredSave();
1160 Push<ClipIntersectRoundSuperellipseOp>(0, rse, is_aa);
1163 Push<ClipDifferenceRoundSuperellipseOp>(0, rse, is_aa);
1170 if (current_info().is_nop) {
1175 if (
path.IsRect(&rect)) {
1179 if (
path.IsOval(&rect)) {
1184 if (
path.IsRoundRect(&rrect)) {
1191 if (global_state().is_cull_rect_empty() ||
1192 layer_local_state().is_cull_rect_empty()) {
1193 current_info().is_nop =
true;
1196 current_info().has_valid_clip =
true;
1197 checkForDeferredSave();
1200 Push<ClipIntersectPathOp>(0,
path, is_aa);
1203 Push<ClipDifferencePathOp>(0,
path, is_aa);
1212void DisplayListBuilder::drawPaint() {
1214 if (result != OpResult::kNoEffect && AccumulateUnbounded()) {
1215 Push<DrawPaintOp>(0);
1216 CheckLayerOpacityCompatibility();
1217 UpdateLayerResult(result);
1225 OpResult result = PaintResult(
DlPaint(color).setBlendMode(
mode));
1226 if (result != OpResult::kNoEffect && AccumulateUnbounded()) {
1227 Push<DrawColorOp>(0, color,
mode);
1228 CheckLayerOpacityCompatibility(
mode);
1229 UpdateLayerResult(result,
mode);
1236 OpResult result = PaintResult(current_, flags);
1237 if (result != OpResult::kNoEffect && AccumulateOpBounds(bounds, flags)) {
1238 Push<DrawLineOp>(0, p0,
p1);
1239 CheckLayerOpacityCompatibility();
1240 UpdateLayerResult(result);
1249void DisplayListBuilder::drawDashedLine(
const DlPoint& p0,
1256 OpResult result = PaintResult(current_, flags);
1257 if (result != OpResult::kNoEffect && AccumulateOpBounds(bounds, flags)) {
1258 Push<DrawDashedLineOp>(0, p0,
p1, on_length, off_length);
1259 CheckLayerOpacityCompatibility();
1260 UpdateLayerResult(result);
1269 drawDashedLine(p0,
p1, on_length, off_length);
1271void DisplayListBuilder::drawRect(
const DlRect& rect) {
1273 OpResult result = PaintResult(current_, flags);
1274 if (result != OpResult::kNoEffect &&
1276 Push<DrawRectOp>(0, rect);
1277 CheckLayerOpacityCompatibility();
1278 UpdateLayerResult(result);
1285void DisplayListBuilder::drawOval(
const DlRect& bounds) {
1287 OpResult result = PaintResult(current_, flags);
1288 if (result != OpResult::kNoEffect &&
1289 AccumulateOpBounds(bounds.
GetPositive(), flags)) {
1290 Push<DrawOvalOp>(0, bounds);
1291 CheckLayerOpacityCompatibility();
1292 UpdateLayerResult(result);
1299void DisplayListBuilder::drawCircle(
const DlPoint& center,
DlScalar radius) {
1301 OpResult result = PaintResult(current_, flags);
1302 if (result != OpResult::kNoEffect) {
1304 if (AccumulateOpBounds(bounds, flags)) {
1305 Push<DrawCircleOp>(0, center, radius);
1306 CheckLayerOpacityCompatibility();
1307 UpdateLayerResult(result);
1315 drawCircle(center, radius);
1317void DisplayListBuilder::drawRoundRect(
const DlRoundRect& rrect) {
1320 }
else if (rrect.
IsOval()) {
1324 OpResult result = PaintResult(current_, flags);
1325 if (result != OpResult::kNoEffect &&
1326 AccumulateOpBounds(rrect.
GetBounds(), flags)) {
1327 Push<DrawRoundRectOp>(0, rrect);
1328 CheckLayerOpacityCompatibility();
1329 UpdateLayerResult(result);
1336 drawRoundRect(rrect);
1338void DisplayListBuilder::drawDiffRoundRect(
const DlRoundRect& outer,
1341 OpResult result = PaintResult(current_, flags);
1342 if (result != OpResult::kNoEffect &&
1343 AccumulateOpBounds(outer.
GetBounds(), flags)) {
1344 Push<DrawDiffRoundRectOp>(0, outer, inner);
1345 CheckLayerOpacityCompatibility();
1346 UpdateLayerResult(result);
1352 if (
auto rrect_and_paint = DiffRoundRectToRoundRect(outer, inner, paint)) {
1353 DrawRoundRect(rrect_and_paint->first, rrect_and_paint->second);
1357 drawDiffRoundRect(outer, inner);
1362 }
else if (rse.
IsOval()) {
1366 OpResult result = PaintResult(current_, flags);
1367 if (result != OpResult::kNoEffect &&
1368 AccumulateOpBounds(rse.
GetBounds(), flags)) {
1372 Push<DrawRoundSuperellipseOp>(0, rse);
1374 DlPathBuilder builder;
1377 Push<DrawPathOp>(0, builder.TakePath());
1379 CheckLayerOpacityCompatibility();
1380 UpdateLayerResult(result);
1387 drawRoundSuperellipse(rse);
1389void DisplayListBuilder::drawPath(
const DlPath&
path) {
1391 OpResult result = PaintResult(current_, flags);
1392 if (result != OpResult::kNoEffect) {
1393 bool is_visible = AccumulateOpBounds(
path.GetBounds(), flags);
1395 Push<DrawPathOp>(0,
path);
1396 CheckLayerOpacityHairlineCompatibility();
1397 UpdateLayerResult(result);
1404 if (
path.IsRect(&rect, &closed) &&
1411 if (
path.IsRoundRect(&rrect)) {
1417 if (
path.IsOval(&oval_bounds)) {
1433void DisplayListBuilder::drawArc(
const DlRect& bounds,
1441 OpResult result = PaintResult(current_, flags);
1445 if (result != OpResult::kNoEffect && AccumulateOpBounds(bounds, flags)) {
1446 Push<DrawArcOp>(0, bounds, start, sweep, useCenter);
1448 CheckLayerOpacityHairlineCompatibility();
1450 CheckLayerOpacityCompatibility();
1452 UpdateLayerResult(result);
1460 SetAttributesFromPaint(
1462 drawArc(bounds,
start, sweep, useCenter);
1477void DisplayListBuilder::drawPoints(
DlPointMode mode,
1483 DisplayListAttributeFlags flags = FlagsForPointMode(mode);
1484 OpResult result = PaintResult(current_, flags);
1485 if (result == OpResult::kNoEffect) {
1490 int bytes = count *
sizeof(
DlPoint);
1491 AccumulationRect accumulator;
1492 for (
size_t i = 0;
i < count;
i++) {
1493 accumulator.accumulate(pts[
i]);
1495 if (!AccumulateOpBounds(accumulator.GetBounds(), flags)) {
1502 data_ptr = Push<DrawPointsOp>(bytes, count);
1505 data_ptr = Push<DrawLinesOp>(bytes, count);
1508 data_ptr = Push<DrawPolygonOp>(bytes, count);
1514 CopyV(data_ptr, pts, count);
1520 current_layer().layer_local_accumulator.record_overlapping_bounds();
1525 CheckLayerOpacityCompatibility();
1526 UpdateLayerResult(result);
1532 SetAttributesFromPaint(paint, FlagsForPointMode(
mode));
1533 drawPoints(
mode, count, pts);
1535void DisplayListBuilder::drawVertices(
1536 const std::shared_ptr<DlVertices>& vertices,
1539 OpResult result = PaintResult(current_, flags);
1540 if (result != OpResult::kNoEffect &&
1541 AccumulateOpBounds(vertices->GetBounds(), flags)) {
1542 Push<DrawVerticesOp>(0, vertices, mode);
1547 UpdateLayerOpacityCompatibility(
false);
1548 UpdateLayerResult(result);
1557 current_layer().layer_local_accumulator.record_overlapping_bounds();
1561 const std::shared_ptr<DlVertices>& vertices,
1565 drawVertices(vertices,
mode);
1568void DisplayListBuilder::drawImage(
const sk_sp<DlImage>
image,
1571 bool render_with_attributes) {
1575 OpResult result = PaintResult(current_, flags);
1576 if (result == OpResult::kNoEffect) {
1581 if (AccumulateOpBounds(bounds, flags)) {
1582 render_with_attributes
1583 ? Push<DrawImageWithAttrOp>(0,
image, point, sampling)
1584 : Push<DrawImageOp>(0,
image, point, sampling);
1585 CheckLayerOpacityCompatibility(render_with_attributes);
1586 UpdateLayerResult(result, render_with_attributes);
1587 is_ui_thread_safe_ = is_ui_thread_safe_ &&
image->isUIThreadSafe();
1594 if (paint !=
nullptr) {
1595 SetAttributesFromPaint(*paint,
1597 drawImage(
image, point, sampling,
true);
1599 drawImage(
image, point, sampling,
false);
1602void DisplayListBuilder::drawImageRect(
const sk_sp<DlImage>
image,
1606 bool render_with_attributes,
1611 OpResult result = PaintResult(current_, flags);
1612 if (result != OpResult::kNoEffect && AccumulateOpBounds(dst, flags)) {
1613 Push<DrawImageRectOp>(0,
image, src, dst, sampling, render_with_attributes,
1615 CheckLayerOpacityCompatibility(render_with_attributes);
1616 UpdateLayerResult(result, render_with_attributes);
1617 is_ui_thread_safe_ = is_ui_thread_safe_ &&
image->isUIThreadSafe();
1626 if (paint !=
nullptr) {
1627 SetAttributesFromPaint(*paint,
1629 drawImageRect(
image, src, dst, sampling,
true, constraint);
1631 drawImageRect(
image, src, dst, sampling,
false, constraint);
1634void DisplayListBuilder::drawImageNine(
const sk_sp<DlImage>
image,
1638 bool render_with_attributes) {
1642 OpResult result = PaintResult(current_, flags);
1643 if (result != OpResult::kNoEffect && AccumulateOpBounds(dst, flags)) {
1644 render_with_attributes
1645 ? Push<DrawImageNineWithAttrOp>(0,
image, center, dst, filter)
1646 : Push<DrawImageNineOp>(0,
image, center, dst, filter);
1647 CheckLayerOpacityCompatibility(render_with_attributes);
1648 UpdateLayerResult(result, render_with_attributes);
1649 is_ui_thread_safe_ = is_ui_thread_safe_ &&
image->isUIThreadSafe();
1657 if (paint !=
nullptr) {
1658 SetAttributesFromPaint(*paint,
1660 drawImageNine(
image, center, dst, filter,
true);
1662 drawImageNine(
image, center, dst, filter,
false);
1665void DisplayListBuilder::drawAtlas(
const sk_sp<DlImage> atlas,
1673 bool render_with_attributes) {
1677 OpResult result = PaintResult(current_, flags);
1678 if (result == OpResult::kNoEffect) {
1682 AccumulationRect accumulator;
1683 for (
int i = 0;
i < count;
i++) {
1685 xform[
i].
GetQuad(src.GetWidth(), src.GetHeight(), quad);
1686 for (
int j = 0; j < 4; j++) {
1687 accumulator.accumulate(quad[j]);
1690 if (accumulator.is_empty() ||
1691 !AccumulateOpBounds(accumulator.GetBounds(), flags)) {
1705 if (accumulator.overlap_detected()) {
1706 current_layer().layer_local_accumulator.record_overlapping_bounds();
1711 if (colors !=
nullptr) {
1712 bytes += count *
sizeof(
DlColor);
1713 if (cull_rect !=
nullptr) {
1715 Push<DrawAtlasCulledOp>(bytes, atlas, count, mode, sampling,
true,
1716 *cull_rect, render_with_attributes);
1718 data_ptr = Push<DrawAtlasOp>(bytes, atlas, count, mode, sampling,
true,
1719 render_with_attributes);
1721 CopyV(data_ptr, xform, count, tex, count, colors, count);
1723 if (cull_rect !=
nullptr) {
1725 Push<DrawAtlasCulledOp>(bytes, atlas, count, mode, sampling,
false,
1726 *cull_rect, render_with_attributes);
1728 data_ptr = Push<DrawAtlasOp>(bytes, atlas, count, mode, sampling,
false,
1729 render_with_attributes);
1731 CopyV(data_ptr, xform, count, tex, count);
1736 UpdateLayerOpacityCompatibility(
false);
1737 UpdateLayerResult(result, render_with_attributes);
1738 is_ui_thread_safe_ = is_ui_thread_safe_ && atlas->isUIThreadSafe();
1749 if (paint !=
nullptr) {
1750 SetAttributesFromPaint(*paint,
1752 drawAtlas(atlas, xform, tex, colors, count,
mode, sampling, cull_rect,
1755 drawAtlas(atlas, xform, tex, colors, count,
mode, sampling, cull_rect,
1762 if (!std::isfinite(opacity) || opacity <= SK_ScalarNearlyZero ||
1763 display_list->op_count() == 0 || display_list->GetBounds().IsEmpty() ||
1764 current_info().is_nop) {
1767 const DlRect bounds = display_list->GetBounds();
1769 sk_sp<const DlRTree> rtree;
1770 if (display_list->root_is_unbounded()) {
1771 accumulated = AccumulateUnbounded();
1772 }
else if (!rtree_data_.has_value() || !(rtree = display_list->rtree())) {
1775 std::list<DlRect> rects =
1777 accumulated =
false;
1778 for (
const DlRect& rect : rects) {
1790 DlPaint current_paint = current_;
1791 Push<DrawDisplayListOp>(0, display_list,
1792 opacity < SK_Scalar1 ? opacity : SK_Scalar1);
1802 depth_ += display_list->total_depth();
1804 is_ui_thread_safe_ = is_ui_thread_safe_ && display_list->isUIThreadSafe();
1808 SetAttributesFromPaint(current_paint,
1817 nested_op_count_ += display_list->op_count(
true) - 1;
1818 nested_bytes_ += display_list->bytes(
true);
1819 UpdateLayerOpacityCompatibility(display_list->can_apply_group_opacity());
1822 UpdateLayerResult(display_list->modifies_transparent_black()
1823 ? OpResult::kAffectsAll
1824 : OpResult::kPreservesTransparency,
1825 display_list->max_root_blend_mode());
1826 if (display_list->root_has_backdrop_filter()) {
1827 current_layer().contains_backdrop_filter =
true;
1831void DisplayListBuilder::drawText(
const std::shared_ptr<DlText>&
text,
1835 OpResult result = PaintResult(current_, flags);
1836 if (result == OpResult::kNoEffect) {
1840 bool unclipped = AccumulateOpBounds(bounds, flags);
1845#if defined(OS_FUCHSIA)
1849 Push<DrawTextOp>(0,
text,
x,
y);
1855 UpdateLayerOpacityCompatibility(
false);
1856 UpdateLayerResult(result);
1871 bool transparent_occluder,
1873 OpResult result = PaintResult(
DlPaint(color));
1874 if (result != OpResult::kNoEffect) {
1878 transparent_occluder
1879 ? Push<DrawShadowTransparentOccluderOp>(0,
path, color, elevation,
1881 : Push<DrawShadowOp>(0,
path, color, elevation, dpr);
1882 UpdateLayerOpacityCompatibility(
false);
1883 UpdateLayerResult(result, DlBlendMode::kSrcOver);
1888bool DisplayListBuilder::AdjustBoundsForPaint(
DlRect& bounds,
1897 DisplayListSpecialGeometryFlags special_flags =
1904 special_flags.may_have_acute_joins()) {
1908 special_flags.may_have_diagonal_caps()) {
1909 pad = std::max(pad, SK_ScalarSqrt2);
1912 pad *= std::max(current_.
getStrokeWidth() * 0.5f, min_stroke_width);
1913 bounds = bounds.
Expand(pad, pad);
1920 switch (filter->type()) {
1923 DlScalar mask_sigma_pad = filter->asBlur()->sigma() * 3.0;
1924 bounds = bounds.
Expand(mask_sigma_pad, mask_sigma_pad);
1939 if (!filter->map_local_bounds(bounds, dl_bounds)) {
1949bool DisplayListBuilder::AccumulateUnbounded(
const SaveInfo& save) {
1950 if (!save.has_valid_clip) {
1951 save.layer_info->is_unbounded =
true;
1953 DlRect global_clip = save.global_state.GetDeviceCullCoverage();
1954 DlRect layer_clip = save.global_state.GetLocalCullCoverage();
1955 if (global_clip.IsEmpty() || !save.layer_state.mapAndClipRect(&layer_clip)) {
1958 if (rtree_data_.has_value()) {
1959 FML_DCHECK(save.layer_info->global_space_accumulator.is_empty());
1960 rtree_data_->rects.push_back(global_clip);
1961 rtree_data_->indices.push_back(op_index_);
1963 save.layer_info->global_space_accumulator.accumulate(global_clip);
1965 save.layer_info->layer_local_accumulator.accumulate(layer_clip);
1969bool DisplayListBuilder::AccumulateOpBounds(
DlRect& bounds,
1970 DisplayListAttributeFlags flags) {
1971 if (AdjustBoundsForPaint(bounds, flags)) {
1972 return AccumulateBounds(bounds);
1974 return AccumulateUnbounded();
1978bool DisplayListBuilder::AccumulateBounds(
const DlRect& bounds,
1981 if (bounds.IsEmpty()) {
1986 if (!layer.global_state.mapAndClipRect(bounds, &global_bounds) ||
1987 !layer.layer_state.mapAndClipRect(bounds, &layer_bounds)) {
1990 if (rtree_data_.has_value()) {
1991 FML_DCHECK(layer.layer_info->global_space_accumulator.is_empty());
1993 rtree_data_->rects.push_back(global_bounds);
1994 rtree_data_->indices.push_back(
id);
1997 layer.layer_info->global_space_accumulator.accumulate(global_bounds);
1999 layer.layer_info->layer_local_accumulator.accumulate(layer_bounds);
2003bool DisplayListBuilder::SaveInfo::AccumulateBoundsLocal(
const DlRect& bounds) {
2004 if (bounds.IsEmpty()) {
2008 if (!layer_state.mapAndClipRect(bounds, &local_bounds)) {
2011 layer_info->layer_local_accumulator.accumulate(local_bounds);
2015bool DisplayListBuilder::paint_nops_on_transparency() {
2047 case DlBlendMode::kClear:
2048 case DlBlendMode::kSrc:
2049 case DlBlendMode::kSrcIn:
2050 case DlBlendMode::kDstIn:
2051 case DlBlendMode::kSrcOut:
2052 case DlBlendMode::kDstATop:
2053 case DlBlendMode::kModulate:
2059 case DlBlendMode::kDst:
2060 case DlBlendMode::kSrcOver:
2061 case DlBlendMode::kDstOver:
2062 case DlBlendMode::kDstOut:
2063 case DlBlendMode::kSrcATop:
2064 case DlBlendMode::kXor:
2065 case DlBlendMode::kPlus:
2066 case DlBlendMode::kScreen:
2067 case DlBlendMode::kOverlay:
2068 case DlBlendMode::kDarken:
2070 case DlBlendMode::kLighten:
2072 case DlBlendMode::kColorDodge:
2073 case DlBlendMode::kColorBurn:
2074 case DlBlendMode::kHardLight:
2075 case DlBlendMode::kSoftLight:
2076 case DlBlendMode::kDifference:
2078 case DlBlendMode::kExclusion:
2079 case DlBlendMode::kMultiply:
2080 case DlBlendMode::kHue:
2081 case DlBlendMode::kSaturation:
2082 case DlBlendMode::kColor:
2083 case DlBlendMode::kLuminosity:
2089DlColor DisplayListBuilder::GetEffectiveColor(
const DlPaint& paint,
2090 DisplayListAttributeFlags flags) {
2092 if (flags.applies_color()) {
2093 const DlColorSource* source = paint.getColorSourcePtr();
2099 color = paint.getColor();
2101 }
else if (flags.applies_alpha()) {
2112 if (flags.applies_image_filter()) {
2113 auto filter = paint.getImageFilterPtr();
2115 if (!color.isTransparent() || filter->modifies_transparent_black()) {
2120 if (flags.applies_color_filter()) {
2121 auto filter = paint.getColorFilterPtr();
2123 if (!color.isTransparent() || filter->modifies_transparent_black()) {
2131DisplayListBuilder::OpResult DisplayListBuilder::PaintResult(
2132 const DlPaint& paint,
2133 DisplayListAttributeFlags flags) {
2134 if (current_info().is_nop) {
2135 return OpResult::kNoEffect;
2137 if (flags.applies_blend()) {
2138 switch (paint.getBlendMode()) {
2140 case DlBlendMode::kDst:
2141 return OpResult::kNoEffect;
2144 case DlBlendMode::kClear:
2145 return OpResult::kPreservesTransparency;
2147 case DlBlendMode::kHue:
2148 case DlBlendMode::kSaturation:
2149 case DlBlendMode::kColor:
2150 case DlBlendMode::kLuminosity:
2151 case DlBlendMode::kColorBurn:
2153 ? OpResult::kNoEffect
2154 : OpResult::kAffectsAll;
2157 case DlBlendMode::kSrcIn:
2158 return OpResult::kPreservesTransparency;
2161 case DlBlendMode::kSrcATop:
2162 case DlBlendMode::kDstOut:
2164 ? OpResult::kNoEffect
2165 : OpResult::kPreservesTransparency;
2168 case DlBlendMode::kSrc:
2169 case DlBlendMode::kSrcOut:
2170 case DlBlendMode::kDstATop:
2172 ? OpResult::kPreservesTransparency
2173 : OpResult::kAffectsAll;
2177 case DlBlendMode::kDstIn:
2178 return GetEffectiveColor(paint, flags).
isOpaque()
2179 ? OpResult::kNoEffect
2180 : OpResult::kPreservesTransparency;
2184 case DlBlendMode::kSrcOver:
2185 case DlBlendMode::kDstOver:
2186 case DlBlendMode::kXor:
2187 case DlBlendMode::kPlus:
2188 case DlBlendMode::kScreen:
2189 case DlBlendMode::kMultiply:
2190 case DlBlendMode::kOverlay:
2191 case DlBlendMode::kDarken:
2192 case DlBlendMode::kLighten:
2193 case DlBlendMode::kColorDodge:
2194 case DlBlendMode::kHardLight:
2195 case DlBlendMode::kSoftLight:
2196 case DlBlendMode::kDifference:
2197 case DlBlendMode::kExclusion:
2199 ? OpResult::kNoEffect
2200 : OpResult::kAffectsAll;
2203 case DlBlendMode::kModulate:
2205 ? OpResult::kNoEffect
2206 : OpResult::kPreservesTransparency;
2209 return OpResult::kAffectsAll;
constexpr bool is_stroked(DlDrawStyle style=DlDrawStyle::kStroke) const
constexpr bool ignores_paint() const
constexpr bool is_geometric() const
constexpr bool applies_image_filter() const
const DisplayListSpecialGeometryFlags GeometryFlags(bool is_stroked) const
constexpr bool applies_mask_filter() const
void DrawOval(const DlRect &bounds, const DlPaint &paint) override
static constexpr DlRect kMaxCullRect
void ClipRect(const DlRect &rect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
void DrawImageRect(const sk_sp< DlImage > &image, const DlRect &src, const DlRect &dst, DlImageSampling sampling, const DlPaint *paint=nullptr, DlSrcRectConstraint constraint=DlSrcRectConstraint::kFast) override
void DrawVertices(const std::shared_ptr< DlVertices > &vertices, DlBlendMode mode, const DlPaint &paint) override
void DrawImageNine(const sk_sp< DlImage > &image, const DlIRect ¢er, const DlRect &dst, DlFilterMode filter, const DlPaint *paint=nullptr) override
void DrawAtlas(const sk_sp< DlImage > &atlas, const DlRSTransform xform[], const DlRect tex[], const DlColor colors[], int count, DlBlendMode mode, DlImageSampling sampling, const DlRect *cullRect, const DlPaint *paint=nullptr) override
void DrawRoundRect(const DlRoundRect &rrect, const DlPaint &paint) override
void RestoreToCount(int restore_count) override
void DrawArc(const DlRect &bounds, DlScalar start, DlScalar sweep, bool useCenter, const DlPaint &paint) override
void DrawShadow(const DlPath &path, const DlColor color, const DlScalar elevation, bool transparent_occluder, DlScalar dpr) override
Draws the shadow of the given |path| rendered in the provided |color| (which is only consulted for it...
void DrawImage(const sk_sp< DlImage > &image, const DlPoint &point, DlImageSampling sampling, const DlPaint *paint=nullptr) override
void DrawColor(DlColor color, DlBlendMode mode) override
DlMatrix GetMatrix() const override
void DrawCircle(const DlPoint ¢er, DlScalar radius, const DlPaint &paint) override
void TransformReset() override
void SaveLayer(const std::optional< DlRect > &bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr, std::optional< int64_t > backdrop_id=std::nullopt) override
void ClipRoundSuperellipse(const DlRoundSuperellipse &rse, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
void DrawLine(const DlPoint &p0, const DlPoint &p1, const DlPaint &paint) override
DlISize GetBaseLayerDimensions() const override
void ClipRoundRect(const DlRoundRect &rrect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
bool IsEmpty() const
Return true if the builder has not yet recorded any commands.
void Rotate(DlScalar degrees) override
void DrawText(const std::shared_ptr< DlText > &text, DlScalar x, DlScalar y, const DlPaint &paint) override
DisplayListBuilder(bool prepare_rtree)
void DrawRoundSuperellipse(const DlRoundSuperellipse &rse, const DlPaint &paint) override
void Scale(DlScalar sx, DlScalar sy) override
void DrawDisplayList(const sk_sp< DisplayList > display_list, DlScalar opacity=SK_Scalar1) override
SkImageInfo GetImageInfo() const override
void Skew(DlScalar sx, DlScalar sy) override
void Translate(DlScalar tx, DlScalar ty) override
void Transform2DAffine(DlScalar mxx, DlScalar mxy, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myt) override
void DrawPaint(const DlPaint &paint) override
size_t GetRecordCount() const
Return the number of records currently recorded in the builder.
void DrawDashedLine(const DlPoint &p0, const DlPoint &p1, DlScalar on_length, DlScalar off_length, const DlPaint &paint) override
sk_sp< DisplayList > Build()
void DrawPath(const DlPath &path, const DlPaint &paint) override
bool QuickReject(const DlRect &bounds) const override
void ClipPath(const DlPath &path, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
void DrawPoints(DlPointMode mode, uint32_t count, const DlPoint pts[], const DlPaint &paint) override
void ClipOval(const DlRect &bounds, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
DlRect GetLocalClipCoverage() const override
int GetSaveCount() const override
void TransformFullPerspective(DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt, DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt, DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt) override
void DrawDiffRoundRect(const DlRoundRect &outer, const DlRoundRect &inner, const DlPaint &paint) override
void Transform(const DlMatrix &matrix) override
void DrawRect(const DlRect &rect, const DlPaint &paint) override
void translate(DlScalar tx, DlScalar ty)
void transform2DAffine(DlScalar mxx, DlScalar mxy, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myt)
void scale(DlScalar sx, DlScalar sy)
void clipRect(const DlRect &rect, DlClipOp op, bool is_aa)
void clipRRect(const DlRoundRect &rrect, DlClipOp op, bool is_aa)
void clipRSuperellipse(const DlRoundSuperellipse &rse, DlClipOp op, bool is_aa)
void transformFullPerspective(DlScalar mxx, DlScalar mxy, DlScalar mxz, DlScalar mxt, DlScalar myx, DlScalar myy, DlScalar myz, DlScalar myt, DlScalar mzx, DlScalar mzy, DlScalar mzz, DlScalar mzt, DlScalar mwx, DlScalar mwy, DlScalar mwz, DlScalar mwt)
void setTransform(const DlMatrix &matrix)
bool content_culled(const DlRect &content_bounds) const
void rotate(DlRadians angle)
void clipPath(const DlPath &path, DlClipOp op, bool is_aa)
void clipOval(const DlRect &bounds, DlClipOp op, bool is_aa)
void skew(DlScalar skx, DlScalar sky)
static constexpr DisplayListAttributeFlags kDrawAtlasFlags
static constexpr DisplayListAttributeFlags kDrawVerticesFlags
static constexpr DisplayListAttributeFlags kDrawArcWithCenterFlags
static constexpr DisplayListAttributeFlags kDrawPaintFlags
static constexpr DisplayListAttributeFlags kDrawArcNoCenterFlags
static constexpr DisplayListAttributeFlags kDrawImageRectWithPaintFlags
static constexpr DisplayListAttributeFlags kSaveLayerFlags
static constexpr DisplayListAttributeFlags kDrawOvalFlags
static constexpr DisplayListAttributeFlags kDrawPointsAsLinesFlags
static constexpr DisplayListAttributeFlags kDrawPointsAsPolygonFlags
static constexpr DisplayListAttributeFlags kDrawImageRectFlags
static constexpr DisplayListAttributeFlags kDrawCircleFlags
static constexpr DisplayListAttributeFlags kDrawDisplayListFlags
static constexpr DisplayListAttributeFlags kDrawPathFlags
static constexpr DisplayListAttributeFlags kDrawAtlasWithPaintFlags
static constexpr DisplayListAttributeFlags kDrawImageNineFlags
static constexpr DisplayListAttributeFlags kDrawLineFlags
static constexpr DisplayListAttributeFlags kSaveLayerWithPaintFlags
static constexpr DisplayListAttributeFlags kDrawPointsAsPointsFlags
static constexpr DisplayListAttributeFlags kDrawImageWithPaintFlags
static constexpr DisplayListAttributeFlags kDrawImageNineWithPaintFlags
static constexpr DisplayListAttributeFlags kDrawTextFlags
static constexpr DisplayListAttributeFlags kDrawShadowFlags
static constexpr DisplayListAttributeFlags kDrawRSuperellipseFlags
static constexpr DisplayListAttributeFlags kDrawImageFlags
static constexpr DisplayListAttributeFlags kDrawHVLineFlags
static constexpr DisplayListAttributeFlags kDrawRRectFlags
static constexpr DisplayListAttributeFlags kDrawDRRectFlags
static constexpr DisplayListAttributeFlags kDrawRectFlags
uint8_t * base()
Returns a pointer to the base of the storage.
size_t size() const
Returns the currently allocated size.
uint8_t * allocate(size_t needed)
static DlRect ComputeShadowBounds(const DlPath &path, float elevation, DlScalar dpr, const DlMatrix &ctm)
Compute the local coverage for a |DrawShadow| operation using the given parameters (excluding the col...
virtual bool modifies_transparent_black() const =0
virtual bool modifies_transparent_black() const =0
static constexpr int kMaxDrawPointsCount
DlStrokeCap getStrokeCap() const
DlPaint & setColor(DlColor color)
DlPaint & setAntiAlias(bool isAntiAlias)
DlPaint & setInvertColors(bool isInvertColors)
DlBlendMode getBlendMode() const
float getStrokeMiter() const
DlStrokeJoin getStrokeJoin() const
DlPaint & setStrokeCap(DlStrokeCap cap)
const DlMaskFilter * getMaskFilterPtr() const
DlPaint & setStrokeWidth(float width)
const DlColorFilter * getColorFilterPtr() const
DlPaint & setStrokeMiter(float miter)
DlPaint & setBlendMode(DlBlendMode mode)
const DlImageFilter * getImageFilterPtr() const
DlDrawStyle getDrawStyle() const
DlPaint & setImageFilter(std::nullptr_t filter)
const std::shared_ptr< DlImageFilter > & getImageFilter() const
float getStrokeWidth() const
DlPaint & setMaskFilter(std::nullptr_t filter)
DlPaint & setDrawStyle(DlDrawStyle style)
DlPaint & setStrokeJoin(DlStrokeJoin join)
DlPaint & setColorFilter(std::nullptr_t filter)
DlPaint & setColorSource(std::nullptr_t source)
SaveLayerOptions with_content_is_unbounded() const
SaveLayerOptions with_renders_with_attributes() const
SaveLayerOptions with_can_distribute_opacity() const
bool renders_with_attributes() const
SaveLayerOptions with_bounds_from_caller() const
bool bounds_from_caller() const
SaveLayerOptions with_contains_backdrop_filter() const
SaveLayerOptions without_optimizations() const
SaveLayerOptions with_content_is_clipped() const
FlutterVulkanImage * image
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
#define FML_CHECK(condition)
#define FML_UNREACHABLE()
#define FML_DCHECK(condition)
impeller::Scalar DlScalar
impeller::RoundingRadii DlRoundingRadii
static constexpr DlRect kEmpty
@ kMiter
extends to miter limit
constexpr bool DlScalarNearlyEqual(DlScalar x, DlScalar y, DlScalar tolerance=kEhCloseEnough)
impeller::RoundRect DlRoundRect
impeller::RSTransform DlRSTransform
impeller::Matrix DlMatrix
impeller::Degrees DlDegrees
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
@ kLines
draw each separate pair of points as a line segment
@ kPolygon
draw each pair of overlapping points as a line segment
@ kPoints
draw each point separately
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
@ kStroke
strokes boundary of shapes
@ kFill
fills interior of shapes
impeller::IRect32 DlIRect
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
static void CopyV(void *dst)
impeller::BlendMode DlBlendMode
static const DlRect & ProtectEmpty(const DlRect &rect)
const DisplayListOpType type
static constexpr DlColor kWhite()
static constexpr DlColor kBlack()
static constexpr DlColor kTransparent()
constexpr bool isTransparent() const
constexpr bool isOpaque() const
DlBlendMode max_blend_mode
uint32_t total_content_depth
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeScale(const Vector3 &s)
static RoundRect MakeRectRadii(const Rect &rect, const RoundingRadii &radii)
constexpr bool IsRect() const
constexpr const Rect & GetBounds() const
constexpr bool IsOval() const
constexpr const Rect & GetBounds() const
static RoundSuperellipse MakeRectRadii(const Rect &rect, const RoundingRadii &radii)
constexpr bool IsOval() const
constexpr bool IsRect() const
constexpr const RoundingRadii & GetRadii() const
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
constexpr bool Contains(const TPoint< Type > &p) const
Returns true iff the provided point |p| is inside the half-open interior of this rectangle.
static constexpr std::enable_if_t< std::is_floating_point_v< FT >, TRect > Make(const TRect< U > &rect)
constexpr auto GetLeft() const
RoundOut(const TRect< U > &r)
constexpr TRect GetPositive() const
Get a version of this rectangle that has a non-negative size.
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
IsFinite() const
Returns true if all of the fields of this floating point rectangle are finite.
static constexpr TRect MakeCircleBounds(const TPoint< Type > ¢er, Type radius)
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
constexpr TRect IntersectionOrEmpty(const TRect &o) const
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)