25template <
typename S,
typename... Rest>
26static void CopyV(
void* dst,
const S* src,
int n, Rest&&... rest) {
27 FML_DCHECK(((uintptr_t)dst & (
alignof(S) - 1)) == 0)
28 <<
"Expected " << dst <<
" to be aligned for at least " <<
alignof(S)
32 memcpy(dst, src, n *
sizeof(S));
33 dst =
reinterpret_cast<void*
>(
reinterpret_cast<uint8_t*
>(dst) +
37 CopyV(dst, std::forward<Rest>(rest)...);
40template <
typename T,
typename... Args>
41void* DisplayListBuilder::Push(
size_t pod, Args&&...
args) {
43 size_t size = SkAlignPtr(
sizeof(T) + pod);
44 size_t offset = storage_.
size();
51 auto op =
reinterpret_cast<T*
>(ptr);
52 new (op) T{std::forward<Args>(
args)...};
58 offsets_.push_back(offset);
59 render_op_count_ += T::kRenderOpInc;
60 depth_ += T::kDepthInc * render_op_depth_cost_;
67 while (save_stack_.size() > 1) {
71 int count = render_op_count_;
72 size_t nested_bytes = nested_bytes_;
73 int nested_count = nested_op_count_;
74 uint32_t total_depth = depth_;
75 bool opacity_compatible = current_layer().is_group_opacity_compatible();
76 bool is_safe = is_ui_thread_safe_;
77 bool affects_transparency = current_layer().affects_transparent_layer;
78 bool root_has_backdrop_filter = current_layer().contains_backdrop_filter;
79 bool root_is_unbounded = current_layer().is_unbounded;
80 DlBlendMode max_root_blend_mode = current_layer().max_blend_mode;
84 if (rtree_data_.has_value()) {
85 auto& rects = rtree_data_->rects;
86 auto& indices = rtree_data_->indices;
87 rtree = sk_make_sp<DlRTree>(rects.data(), rects.size(), indices.data(),
88 [](
int id) { return id >= 0; });
92 bounds = rtree->bounds();
95 bounds = current_layer().global_space_accumulator.GetBounds();
98 render_op_count_ = op_index_ = 0;
99 nested_bytes_ = nested_op_count_ = 0;
101 is_ui_thread_safe_ =
true;
102 current_opacity_compatibility_ =
true;
103 render_op_depth_cost_ = 1u;
106 save_stack_.pop_back();
107 Init(rtree !=
nullptr);
111 std::vector<size_t> offsets;
112 std::swap(offsets, offsets_);
113 std::swap(storage, storage_);
116 std::move(storage), std::move(offsets), count, nested_bytes, nested_count,
117 total_depth, bounds, opacity_compatible, is_safe, affects_transparency,
118 max_root_blend_mode, root_has_backdrop_filter, root_is_unbounded,
135void DisplayListBuilder::Init(
bool prepare_rtree) {
139 save_stack_.emplace_back(original_cull_rect_);
140 current_info().is_nop = original_cull_rect_.
IsEmpty();
142 rtree_data_.emplace();
147 DisplayList::DisposeOps(storage_, offsets_);
156 return SkImageInfo::MakeUnknown(
size.width,
size.height);
159void DisplayListBuilder::onSetAntiAlias(
bool aa) {
161 Push<SetAntiAliasOp>(0, aa);
163void DisplayListBuilder::onSetInvertColors(
bool invert) {
165 Push<SetInvertColorsOp>(0, invert);
166 UpdateCurrentOpacityCompatibility();
168void DisplayListBuilder::onSetStrokeCap(
DlStrokeCap cap) {
170 Push<SetStrokeCapOp>(0, cap);
172void DisplayListBuilder::onSetStrokeJoin(
DlStrokeJoin join) {
174 Push<SetStrokeJoinOp>(0, join);
176void DisplayListBuilder::onSetDrawStyle(
DlDrawStyle style) {
178 Push<SetStyleOp>(0, style);
180void DisplayListBuilder::onSetStrokeWidth(
float width) {
182 Push<SetStrokeWidthOp>(0,
width);
184void DisplayListBuilder::onSetStrokeMiter(
float limit) {
186 Push<SetStrokeMiterOp>(0, limit);
188void DisplayListBuilder::onSetColor(DlColor color) {
190 Push<SetColorOp>(0, color);
192void DisplayListBuilder::onSetBlendMode(
DlBlendMode mode) {
194 Push<SetBlendModeOp>(0, mode);
195 UpdateCurrentOpacityCompatibility();
198void DisplayListBuilder::onSetColorSource(
const DlColorSource* source) {
199 if (source ==
nullptr) {
201 Push<ClearColorSourceOp>(0);
204 is_ui_thread_safe_ = is_ui_thread_safe_ && source->isUIThreadSafe();
205 switch (source->type()) {
207 const DlImageColorSource* image_source = source->asImage();
209 Push<SetImageColorSourceOp>(0, image_source);
213 const DlLinearGradientColorSource* linear = source->asLinearGradient();
215 void* pod = Push<SetPodColorSourceOp>(linear->size());
216 new (pod) DlLinearGradientColorSource(linear);
220 const DlRadialGradientColorSource* radial = source->asRadialGradient();
222 void* pod = Push<SetPodColorSourceOp>(radial->size());
223 new (pod) DlRadialGradientColorSource(radial);
227 const DlConicalGradientColorSource* conical =
228 source->asConicalGradient();
230 void* pod = Push<SetPodColorSourceOp>(conical->size());
231 new (pod) DlConicalGradientColorSource(conical);
235 const DlSweepGradientColorSource* sweep = source->asSweepGradient();
237 void* pod = Push<SetPodColorSourceOp>(sweep->size());
238 new (pod) DlSweepGradientColorSource(sweep);
242 const DlRuntimeEffectColorSource* effect = source->asRuntimeEffect();
244 Push<SetRuntimeEffectColorSourceOp>(0, effect);
249 UpdateCurrentOpacityCompatibility();
251void DisplayListBuilder::onSetImageFilter(
const DlImageFilter* filter) {
252 if (filter ==
nullptr) {
254 Push<ClearImageFilterOp>(0);
257 switch (filter->type()) {
259 const DlBlurImageFilter* blur_filter = filter->asBlur();
261 void* pod = Push<SetPodImageFilterOp>(blur_filter->size());
262 new (pod) DlBlurImageFilter(blur_filter);
266 const DlDilateImageFilter* dilate_filter = filter->asDilate();
268 void* pod = Push<SetPodImageFilterOp>(dilate_filter->size());
269 new (pod) DlDilateImageFilter(dilate_filter);
273 const DlErodeImageFilter* erode_filter = filter->asErode();
275 void* pod = Push<SetPodImageFilterOp>(erode_filter->size());
276 new (pod) DlErodeImageFilter(erode_filter);
280 const DlMatrixImageFilter* matrix_filter = filter->asMatrix();
282 void* pod = Push<SetPodImageFilterOp>(matrix_filter->size());
283 new (pod) DlMatrixImageFilter(matrix_filter);
290 Push<SetSharedImageFilterOp>(0, filter);
295 UpdateCurrentOpacityCompatibility();
297void DisplayListBuilder::onSetColorFilter(
const DlColorFilter* filter) {
298 if (filter ==
nullptr) {
300 Push<ClearColorFilterOp>(0);
303 switch (filter->type()) {
305 const DlBlendColorFilter* blend_filter = filter->asBlend();
307 void* pod = Push<SetPodColorFilterOp>(blend_filter->size());
308 new (pod) DlBlendColorFilter(blend_filter);
312 const DlMatrixColorFilter* matrix_filter = filter->asMatrix();
314 void* pod = Push<SetPodColorFilterOp>(matrix_filter->size());
315 new (pod) DlMatrixColorFilter(matrix_filter);
319 void* pod = Push<SetPodColorFilterOp>(filter->size());
320 new (pod) DlSrgbToLinearGammaColorFilter();
324 void* pod = Push<SetPodColorFilterOp>(filter->size());
325 new (pod) DlLinearToSrgbGammaColorFilter();
330 UpdateCurrentOpacityCompatibility();
332void DisplayListBuilder::onSetMaskFilter(
const DlMaskFilter* filter) {
333 if (filter ==
nullptr) {
335 render_op_depth_cost_ = 1u;
336 Push<ClearMaskFilterOp>(0);
339 render_op_depth_cost_ = 2u;
340 switch (filter->type()) {
342 const DlBlurMaskFilter* blur_filter = filter->asBlur();
344 void* pod = Push<SetPodMaskFilterOp>(blur_filter->size());
345 new (pod) DlBlurMaskFilter(blur_filter);
352void DisplayListBuilder::SetAttributesFromPaint(
353 const DlPaint& paint,
354 const DisplayListAttributeFlags flags) {
355 if (flags.applies_anti_alias()) {
356 setAntiAlias(paint.isAntiAlias());
358 if (flags.applies_alpha_or_color()) {
359 setColor(paint.getColor());
361 if (flags.applies_blend()) {
362 setBlendMode(paint.getBlendMode());
364 if (flags.applies_style()) {
365 setDrawStyle(paint.getDrawStyle());
367 if (flags.is_stroked(paint.getDrawStyle())) {
368 setStrokeWidth(paint.getStrokeWidth());
369 setStrokeMiter(paint.getStrokeMiter());
370 setStrokeCap(paint.getStrokeCap());
371 setStrokeJoin(paint.getStrokeJoin());
373 if (flags.applies_shader()) {
374 setColorSource(paint.getColorSourcePtr());
376 if (flags.applies_color_filter()) {
377 setInvertColors(paint.isInvertColors());
378 setColorFilter(paint.getColorFilterPtr());
380 if (flags.applies_image_filter()) {
381 setImageFilter(paint.getImageFilterPtr());
383 if (flags.applies_mask_filter()) {
384 setMaskFilter(paint.getMaskFilterPtr());
388void DisplayListBuilder::checkForDeferredSave() {
389 if (current_info().has_deferred_save_op) {
390 size_t save_offset = storage_.
size();
392 current_info().save_offset = save_offset;
393 current_info().save_depth = depth_;
394 current_info().has_deferred_save_op =
false;
399 bool was_nop = current_info().is_nop;
400 save_stack_.emplace_back(¤t_info());
401 current_info().is_nop = was_nop;
404 FML_DCHECK(current_info().has_deferred_save_op);
407void DisplayListBuilder::saveLayer(
const DlRect& bounds,
410 std::optional<int64_t> backdrop_id) {
415 OpResult result = PaintResult(current_, flags);
416 if (result == OpResult::kNoEffect) {
424 current_info().is_nop =
true;
428 if (backdrop !=
nullptr) {
429 current_layer().contains_backdrop_filter =
true;
435 size_t save_offset = storage_.
size();
436 uint32_t save_depth = depth_;
439 bool will_be_unbounded = (backdrop !=
nullptr);
440 std::shared_ptr<DlImageFilter> filter;
443 if (!paint_nops_on_transparency()) {
445 will_be_unbounded =
true;
448 CheckLayerOpacityCompatibility(
true);
449 UpdateLayerResult(result,
true);
451 CheckLayerOpacityCompatibility(
false);
452 UpdateLayerResult(result,
false);
463 if (will_be_unbounded) {
467 [[maybe_unused]]
bool unclipped = AccumulateUnbounded();
475 rtree_data_.has_value() ? rtree_data_->rects.size() : 0u;
477 save_stack_.emplace_back(¤t_info(), filter, rtree_index);
480 FML_DCHECK(!current_info().has_deferred_save_op);
481 current_info().save_offset = save_offset;
482 current_info().save_depth = save_depth;
489 current_info().global_state.GetDeviceCullCoverage();
490 DlMatrix matrix = current_info().global_state.matrix();
494 if (filter->get_input_device_bounds(output_bounds, matrix,
496 current_info().global_state.resetDeviceCullRect(
502 current_info().global_state.resetDeviceCullRect(
kMaxCullRect);
520 record_bounds = bounds;
526 Push<SaveLayerBackdropOp>(0, options, record_bounds, backdrop,
529 Push<SaveLayerOp>(0, options, record_bounds);
538 if (!current_opacity_compatibility_ || filter) {
539 UpdateLayerOpacityCompatibility(
false);
546 std::optional<int64_t> backdrop_id) {
549 if (bounds.has_value()) {
551 temp_bounds = *bounds;
555 if (paint !=
nullptr) {
557 SetAttributesFromPaint(*paint,
560 saveLayer(temp_bounds, options, backdrop, backdrop_id);
564 if (save_stack_.size() <= 1) {
568 if (!current_info().has_deferred_save_op) {
570 current_info().save_offset);
572 op->
type == DisplayListOpType::kSaveLayer ||
573 op->
type == DisplayListOpType::kSaveLayerBackdrop);
578 if (current_info().is_save_layer) {
590 save_stack_.pop_back();
593void DisplayListBuilder::RestoreLayer() {
596 FML_DCHECK(!current_info().has_deferred_save_op);
601 depth_ += render_op_depth_cost_;
603 DlRect content_bounds = current_layer().layer_local_accumulator.GetBounds();
606 storage_.
base() + current_info().save_offset);
608 layer_op->
type == DisplayListOpType::kSaveLayerBackdrop);
612 if (!content_bounds.
IsEmpty() && !user_bounds.
Contains(content_bounds)) {
617 layer_op->
rect = content_bounds;
620 if (current_layer().contains_backdrop_filter) {
624 if (current_layer().is_group_opacity_compatible()) {
628 if (current_layer().is_unbounded) {
635 TransferLayerBounds(content_bounds);
669void DisplayListBuilder::TransferLayerBounds(
const DlRect& content_bounds) {
670 auto& filter = current_layer().filter;
676 current_layer().global_space_accumulator.is_empty());
678 parent_info().AccumulateBoundsLocal(content_bounds);
679 parent_layer().global_space_accumulator.accumulate(
680 current_layer().global_space_accumulator);
684 bool parent_is_flooded =
false;
685 DlRect bounds_for_parent = content_bounds;
692 const DlRect clip = parent_info().global_state.GetDeviceCullCoverage();
693 const DlMatrix matrix = parent_info().global_state.matrix();
695 if (rtree_data_.has_value()) {
698 FML_DCHECK(current_layer().global_space_accumulator.is_empty());
699 FML_DCHECK(parent_layer().global_space_accumulator.is_empty());
712 if (AdjustRTreeRects(rtree_data_.value(), *filter, matrix, clip,
713 current_layer().rtree_rects_start_index)) {
714 parent_is_flooded =
true;
717 DlRect global_bounds = current_layer().global_space_accumulator.GetBounds();
718 if (!global_bounds.IsEmpty()) {
720 if (!filter->map_device_bounds(global_ibounds, matrix, global_ibounds)) {
721 parent_is_flooded =
true;
724 std::optional<DlRect> clipped_bounds = global_bounds.Intersection(clip);
725 if (clipped_bounds.has_value()) {
726 parent_layer().global_space_accumulator.accumulate(
727 clipped_bounds.value());
743 if (!parent_is_flooded && !bounds_for_parent.IsEmpty()) {
744 DlRect mappable_bounds = bounds_for_parent;
745 if (filter->map_local_bounds(mappable_bounds, mappable_bounds)) {
746 bounds_for_parent = mappable_bounds;
748 parent_is_flooded =
true;
752 if (parent_is_flooded) {
762 AccumulateUnbounded(parent_info());
764 parent_info().AccumulateBoundsLocal(bounds_for_parent);
768bool DisplayListBuilder::AdjustRTreeRects(RTreeData&
data,
769 const DlImageFilter& filter,
772 size_t rect_start_index) {
773 auto& rects =
data.rects;
774 auto& indices =
data.indices;
777 auto rect_keep = rect_start_index;
778 for (
size_t i = rect_start_index;
i < rects.size();
i++) {
781 if (filter.map_device_bounds(ibounds, matrix, ibounds)) {
787 auto clipped_bounds = bounds.Intersection(clip);
788 if (clipped_bounds.has_value()) {
789 indices[rect_keep] = indices[
i];
790 rects[rect_keep] = clipped_bounds.value();
794 indices.resize(rect_keep);
795 rects.resize(rect_keep);
807 if (std::isfinite(tx) && std::isfinite(ty) && (tx != 0.0 || ty != 0.0)) {
808 checkForDeferredSave();
809 Push<TranslateOp>(0, tx, ty);
815 if (std::isfinite(sx) && std::isfinite(sy) && (sx != 1.0 || sy != 1.0)) {
816 checkForDeferredSave();
817 Push<ScaleOp>(0, sx, sy);
818 global_state().
scale(sx, sy);
819 layer_local_state().
scale(sx, sy);
823 if (SkScalarMod(degrees, 360.0) != 0.0) {
824 checkForDeferredSave();
825 Push<RotateOp>(0, degrees);
831 if (std::isfinite(sx) && std::isfinite(sy) && (sx != 0.0 || sy != 0.0)) {
832 checkForDeferredSave();
833 Push<SkewOp>(0, sx, sy);
834 global_state().
skew(sx, sy);
835 layer_local_state().
skew(sx, sy);
845 if (std::isfinite(mxx) && std::isfinite(myx) &&
846 std::isfinite(mxy) && std::isfinite(myy) &&
847 std::isfinite(mxt) && std::isfinite(myt)) {
848 if (mxx == 1 && mxy == 0 &&
849 myx == 0 && myy == 1) {
852 checkForDeferredSave();
853 Push<Transform2DAffineOp>(0,
871 mzx == 0 && mzy == 0 && mzz == 1 && mzt == 0 &&
872 mwx == 0 && mwy == 0 && mwz == 0 && mwt == 1) {
873 transform2DAffine(mxx, mxy, mxt,
875 }
else if (std::isfinite(mxx) && std::isfinite(mxy) &&
876 std::isfinite(mxz) && std::isfinite(mxt) &&
877 std::isfinite(myx) && std::isfinite(myy) &&
878 std::isfinite(myz) && std::isfinite(myt) &&
879 std::isfinite(mzx) && std::isfinite(mzy) &&
880 std::isfinite(mzz) && std::isfinite(mzt) &&
881 std::isfinite(mwx) && std::isfinite(mwy) &&
882 std::isfinite(mwz) && std::isfinite(mwt)) {
883 checkForDeferredSave();
884 Push<TransformFullPerspectiveOp>(0,
901 checkForDeferredSave();
902 Push<TransformResetOp>(0);
915 if (!layer_local_state().inverseTransform(global_state())) {
928 matrix.
e[0][0], matrix.
e[1][0], matrix.
e[2][0], matrix.
e[3][0],
929 matrix.
e[0][1], matrix.
e[1][1], matrix.
e[2][1], matrix.
e[3][1],
930 matrix.
e[0][2], matrix.
e[1][2], matrix.
e[2][2], matrix.
e[3][2],
931 matrix.
e[0][3], matrix.
e[1][3], matrix.
e[2][3], matrix.
e[3][3]);
940 if (current_info().is_nop) {
944 layer_local_state().rect_covers_cull(rect)) {
947 global_state().
clipRect(rect, clip_op, is_aa);
948 layer_local_state().
clipRect(rect, clip_op, is_aa);
949 if (global_state().is_cull_rect_empty() ||
950 layer_local_state().is_cull_rect_empty()) {
951 current_info().is_nop =
true;
954 current_info().has_valid_clip =
true;
955 checkForDeferredSave();
958 Push<ClipIntersectRectOp>(0, rect, is_aa);
961 Push<ClipDifferenceRectOp>(0, rect, is_aa);
971 if (current_info().is_nop) {
975 layer_local_state().oval_covers_cull(bounds)) {
978 global_state().
clipOval(bounds, clip_op, is_aa);
979 layer_local_state().
clipOval(bounds, clip_op, is_aa);
980 if (global_state().is_cull_rect_empty() ||
981 layer_local_state().is_cull_rect_empty()) {
982 current_info().is_nop =
true;
985 current_info().has_valid_clip =
true;
986 checkForDeferredSave();
989 Push<ClipIntersectOvalOp>(0, bounds, is_aa);
992 Push<ClipDifferenceOvalOp>(0, bounds, is_aa);
1007 if (current_info().is_nop) {
1011 layer_local_state().rrect_covers_cull(rrect)) {
1014 global_state().
clipRRect(rrect, clip_op, is_aa);
1015 layer_local_state().
clipRRect(rrect, clip_op, is_aa);
1016 if (global_state().is_cull_rect_empty() ||
1017 layer_local_state().is_cull_rect_empty()) {
1018 current_info().is_nop =
true;
1021 current_info().has_valid_clip =
true;
1022 checkForDeferredSave();
1025 Push<ClipIntersectRoundRectOp>(0, rrect, is_aa);
1028 Push<ClipDifferenceRoundRectOp>(0, rrect, is_aa);
1043 if (current_info().is_nop) {
1047 layer_local_state().rsuperellipse_covers_cull(rse)) {
1052 if (global_state().is_cull_rect_empty() ||
1053 layer_local_state().is_cull_rect_empty()) {
1054 current_info().is_nop =
true;
1057 current_info().has_valid_clip =
true;
1058 checkForDeferredSave();
1061 Push<ClipIntersectRoundSuperellipseOp>(0, rse, is_aa);
1064 Push<ClipDifferenceRoundSuperellipseOp>(0, rse, is_aa);
1071 if (current_info().is_nop) {
1076 if (
path.IsRect(&rect)) {
1080 if (
path.IsOval(&rect)) {
1085 if (
path.IsRoundRect(&rrect)) {
1092 if (global_state().is_cull_rect_empty() ||
1093 layer_local_state().is_cull_rect_empty()) {
1094 current_info().is_nop =
true;
1097 current_info().has_valid_clip =
true;
1098 checkForDeferredSave();
1101 Push<ClipIntersectPathOp>(0,
path, is_aa);
1104 Push<ClipDifferencePathOp>(0,
path, is_aa);
1113void DisplayListBuilder::drawPaint() {
1115 if (result != OpResult::kNoEffect && AccumulateUnbounded()) {
1116 Push<DrawPaintOp>(0);
1117 CheckLayerOpacityCompatibility();
1118 UpdateLayerResult(result);
1126 OpResult result = PaintResult(
DlPaint(color).setBlendMode(
mode));
1127 if (result != OpResult::kNoEffect && AccumulateUnbounded()) {
1128 Push<DrawColorOp>(0, color,
mode);
1129 CheckLayerOpacityCompatibility(
mode);
1130 UpdateLayerResult(result,
mode);
1133void DisplayListBuilder::drawLine(
const DlPoint& p0,
const DlPoint& p1) {
1137 OpResult result = PaintResult(current_, flags);
1138 if (result != OpResult::kNoEffect && AccumulateOpBounds(bounds, flags)) {
1139 Push<DrawLineOp>(0, p0, p1);
1140 CheckLayerOpacityCompatibility();
1141 UpdateLayerResult(result);
1150void DisplayListBuilder::drawDashedLine(
const DlPoint& p0,
1157 OpResult result = PaintResult(current_, flags);
1158 if (result != OpResult::kNoEffect && AccumulateOpBounds(bounds, flags)) {
1159 Push<DrawDashedLineOp>(0, p0, p1, on_length, off_length);
1160 CheckLayerOpacityCompatibility();
1161 UpdateLayerResult(result);
1170 drawDashedLine(p0, p1, on_length, off_length);
1172void DisplayListBuilder::drawRect(
const DlRect& rect) {
1174 OpResult result = PaintResult(current_, flags);
1175 if (result != OpResult::kNoEffect &&
1177 Push<DrawRectOp>(0, rect);
1178 CheckLayerOpacityCompatibility();
1179 UpdateLayerResult(result);
1186void DisplayListBuilder::drawOval(
const DlRect& bounds) {
1188 OpResult result = PaintResult(current_, flags);
1189 if (result != OpResult::kNoEffect &&
1190 AccumulateOpBounds(bounds.
GetPositive(), flags)) {
1191 Push<DrawOvalOp>(0, bounds);
1192 CheckLayerOpacityCompatibility();
1193 UpdateLayerResult(result);
1200void DisplayListBuilder::drawCircle(
const DlPoint& center,
DlScalar radius) {
1202 OpResult result = PaintResult(current_, flags);
1203 if (result != OpResult::kNoEffect) {
1205 center.x + radius, center.y + radius);
1206 if (AccumulateOpBounds(bounds, flags)) {
1207 Push<DrawCircleOp>(0, center, radius);
1208 CheckLayerOpacityCompatibility();
1209 UpdateLayerResult(result);
1217 drawCircle(center, radius);
1219void DisplayListBuilder::drawRoundRect(
const DlRoundRect& rrect) {
1222 }
else if (rrect.
IsOval()) {
1226 OpResult result = PaintResult(current_, flags);
1227 if (result != OpResult::kNoEffect &&
1228 AccumulateOpBounds(rrect.
GetBounds(), flags)) {
1229 Push<DrawRoundRectOp>(0, rrect);
1230 CheckLayerOpacityCompatibility();
1231 UpdateLayerResult(result);
1238 drawRoundRect(rrect);
1240void DisplayListBuilder::drawDiffRoundRect(
const DlRoundRect& outer,
1243 OpResult result = PaintResult(current_, flags);
1244 if (result != OpResult::kNoEffect &&
1245 AccumulateOpBounds(outer.
GetBounds(), flags)) {
1246 Push<DrawDiffRoundRectOp>(0, outer, inner);
1247 CheckLayerOpacityCompatibility();
1248 UpdateLayerResult(result);
1255 drawDiffRoundRect(outer, inner);
1260 }
else if (rse.
IsOval()) {
1264 OpResult result = PaintResult(current_, flags);
1265 if (result != OpResult::kNoEffect &&
1266 AccumulateOpBounds(rse.
GetBounds(), flags)) {
1270 Push<DrawRoundSuperellipseOp>(0, rse);
1272 DlPathBuilder builder;
1275 Push<DrawPathOp>(0, builder.TakePath());
1277 CheckLayerOpacityCompatibility();
1278 UpdateLayerResult(result);
1285 drawRoundSuperellipse(rse);
1287void DisplayListBuilder::drawPath(
const DlPath&
path) {
1289 OpResult result = PaintResult(current_, flags);
1290 if (result != OpResult::kNoEffect) {
1291 bool is_visible = AccumulateOpBounds(
path.GetBounds(), flags);
1293 Push<DrawPathOp>(0,
path);
1294 CheckLayerOpacityHairlineCompatibility();
1295 UpdateLayerResult(result);
1304void DisplayListBuilder::drawArc(
const DlRect& bounds,
1312 OpResult result = PaintResult(current_, flags);
1316 if (result != OpResult::kNoEffect && AccumulateOpBounds(bounds, flags)) {
1317 Push<DrawArcOp>(0, bounds, start, sweep, useCenter);
1319 CheckLayerOpacityHairlineCompatibility();
1321 CheckLayerOpacityCompatibility();
1323 UpdateLayerResult(result);
1331 SetAttributesFromPaint(
1333 drawArc(bounds,
start, sweep, useCenter);
1348void DisplayListBuilder::drawPoints(
DlPointMode mode,
1354 DisplayListAttributeFlags flags = FlagsForPointMode(mode);
1355 OpResult result = PaintResult(current_, flags);
1356 if (result == OpResult::kNoEffect) {
1361 int bytes = count *
sizeof(
DlPoint);
1362 AccumulationRect accumulator;
1363 for (
size_t i = 0;
i < count;
i++) {
1364 accumulator.accumulate(pts[
i]);
1366 if (!AccumulateOpBounds(accumulator.GetBounds(), flags)) {
1373 data_ptr = Push<DrawPointsOp>(bytes, count);
1376 data_ptr = Push<DrawLinesOp>(bytes, count);
1379 data_ptr = Push<DrawPolygonOp>(bytes, count);
1385 CopyV(data_ptr, pts, count);
1391 current_layer().layer_local_accumulator.record_overlapping_bounds();
1396 CheckLayerOpacityCompatibility();
1397 UpdateLayerResult(result);
1403 SetAttributesFromPaint(paint, FlagsForPointMode(
mode));
1404 drawPoints(
mode, count, pts);
1406void DisplayListBuilder::drawVertices(
1407 const std::shared_ptr<DlVertices>& vertices,
1410 OpResult result = PaintResult(current_, flags);
1411 if (result != OpResult::kNoEffect &&
1412 AccumulateOpBounds(vertices->GetBounds(), flags)) {
1413 Push<DrawVerticesOp>(0, vertices, mode);
1418 UpdateLayerOpacityCompatibility(
false);
1419 UpdateLayerResult(result);
1428 current_layer().layer_local_accumulator.record_overlapping_bounds();
1432 const std::shared_ptr<DlVertices>& vertices,
1436 drawVertices(vertices,
mode);
1439void DisplayListBuilder::drawImage(
const sk_sp<DlImage>
image,
1442 bool render_with_attributes) {
1446 OpResult result = PaintResult(current_, flags);
1447 if (result == OpResult::kNoEffect) {
1452 if (AccumulateOpBounds(bounds, flags)) {
1453 render_with_attributes
1454 ? Push<DrawImageWithAttrOp>(0,
image, point, sampling)
1455 : Push<DrawImageOp>(0,
image, point, sampling);
1456 CheckLayerOpacityCompatibility(render_with_attributes);
1457 UpdateLayerResult(result, render_with_attributes);
1458 is_ui_thread_safe_ = is_ui_thread_safe_ &&
image->isUIThreadSafe();
1465 if (paint !=
nullptr) {
1466 SetAttributesFromPaint(*paint,
1468 drawImage(
image, point, sampling,
true);
1470 drawImage(
image, point, sampling,
false);
1473void DisplayListBuilder::drawImageRect(
const sk_sp<DlImage>
image,
1477 bool render_with_attributes,
1482 OpResult result = PaintResult(current_, flags);
1483 if (result != OpResult::kNoEffect && AccumulateOpBounds(dst, flags)) {
1484 Push<DrawImageRectOp>(0,
image, src, dst, sampling, render_with_attributes,
1486 CheckLayerOpacityCompatibility(render_with_attributes);
1487 UpdateLayerResult(result, render_with_attributes);
1488 is_ui_thread_safe_ = is_ui_thread_safe_ &&
image->isUIThreadSafe();
1497 if (paint !=
nullptr) {
1498 SetAttributesFromPaint(*paint,
1500 drawImageRect(
image, src, dst, sampling,
true, constraint);
1502 drawImageRect(
image, src, dst, sampling,
false, constraint);
1505void DisplayListBuilder::drawImageNine(
const sk_sp<DlImage>
image,
1509 bool render_with_attributes) {
1513 OpResult result = PaintResult(current_, flags);
1514 if (result != OpResult::kNoEffect && AccumulateOpBounds(dst, flags)) {
1515 render_with_attributes
1516 ? Push<DrawImageNineWithAttrOp>(0,
image, center, dst, filter)
1517 : Push<DrawImageNineOp>(0,
image, center, dst, filter);
1518 CheckLayerOpacityCompatibility(render_with_attributes);
1519 UpdateLayerResult(result, render_with_attributes);
1520 is_ui_thread_safe_ = is_ui_thread_safe_ &&
image->isUIThreadSafe();
1528 if (paint !=
nullptr) {
1529 SetAttributesFromPaint(*paint,
1531 drawImageNine(
image, center, dst, filter,
true);
1533 drawImageNine(
image, center, dst, filter,
false);
1536void DisplayListBuilder::drawAtlas(
const sk_sp<DlImage> atlas,
1544 bool render_with_attributes) {
1548 OpResult result = PaintResult(current_, flags);
1549 if (result == OpResult::kNoEffect) {
1553 AccumulationRect accumulator;
1554 for (
int i = 0;
i < count;
i++) {
1556 xform[
i].
GetQuad(src.GetWidth(), src.GetHeight(), quad);
1557 for (
int j = 0; j < 4; j++) {
1558 accumulator.accumulate(quad[j]);
1561 if (accumulator.is_empty() ||
1562 !AccumulateOpBounds(accumulator.GetBounds(), flags)) {
1576 if (accumulator.overlap_detected()) {
1577 current_layer().layer_local_accumulator.record_overlapping_bounds();
1582 if (colors !=
nullptr) {
1583 bytes += count *
sizeof(
DlColor);
1584 if (cull_rect !=
nullptr) {
1586 Push<DrawAtlasCulledOp>(bytes, atlas, count, mode, sampling,
true,
1587 *cull_rect, render_with_attributes);
1589 data_ptr = Push<DrawAtlasOp>(bytes, atlas, count, mode, sampling,
true,
1590 render_with_attributes);
1592 CopyV(data_ptr, xform, count, tex, count, colors, count);
1594 if (cull_rect !=
nullptr) {
1596 Push<DrawAtlasCulledOp>(bytes, atlas, count, mode, sampling,
false,
1597 *cull_rect, render_with_attributes);
1599 data_ptr = Push<DrawAtlasOp>(bytes, atlas, count, mode, sampling,
false,
1600 render_with_attributes);
1602 CopyV(data_ptr, xform, count, tex, count);
1607 UpdateLayerOpacityCompatibility(
false);
1608 UpdateLayerResult(result, render_with_attributes);
1609 is_ui_thread_safe_ = is_ui_thread_safe_ && atlas->isUIThreadSafe();
1620 if (paint !=
nullptr) {
1621 SetAttributesFromPaint(*paint,
1623 drawAtlas(atlas, xform, tex, colors, count,
mode, sampling, cull_rect,
1626 drawAtlas(atlas, xform, tex, colors, count,
mode, sampling, cull_rect,
1633 if (!std::isfinite(opacity) || opacity <= SK_ScalarNearlyZero ||
1634 display_list->op_count() == 0 || display_list->GetBounds().IsEmpty() ||
1635 current_info().is_nop) {
1638 const DlRect bounds = display_list->GetBounds();
1640 sk_sp<const DlRTree> rtree;
1641 if (display_list->root_is_unbounded()) {
1642 accumulated = AccumulateUnbounded();
1643 }
else if (!rtree_data_.has_value() || !(rtree = display_list->rtree())) {
1646 std::list<DlRect> rects =
1648 accumulated =
false;
1649 for (
const DlRect& rect : rects) {
1661 DlPaint current_paint = current_;
1662 Push<DrawDisplayListOp>(0, display_list,
1663 opacity < SK_Scalar1 ? opacity : SK_Scalar1);
1673 depth_ += display_list->total_depth();
1675 is_ui_thread_safe_ = is_ui_thread_safe_ && display_list->isUIThreadSafe();
1679 SetAttributesFromPaint(current_paint,
1688 nested_op_count_ += display_list->op_count(
true) - 1;
1689 nested_bytes_ += display_list->bytes(
true);
1690 UpdateLayerOpacityCompatibility(display_list->can_apply_group_opacity());
1693 UpdateLayerResult(display_list->modifies_transparent_black()
1694 ? OpResult::kAffectsAll
1695 : OpResult::kPreservesTransparency,
1696 display_list->max_root_blend_mode());
1697 if (display_list->root_has_backdrop_filter()) {
1698 current_layer().contains_backdrop_filter =
true;
1702void DisplayListBuilder::drawText(
const std::shared_ptr<DlText>&
text,
1706 OpResult result = PaintResult(current_, flags);
1707 if (result == OpResult::kNoEffect) {
1711 bool unclipped = AccumulateOpBounds(bounds, flags);
1716#if defined(OS_FUCHSIA)
1720 Push<DrawTextOp>(0,
text,
x,
y);
1726 UpdateLayerOpacityCompatibility(
false);
1727 UpdateLayerResult(result);
1742 bool transparent_occluder,
1744 OpResult result = PaintResult(
DlPaint(color));
1745 if (result != OpResult::kNoEffect) {
1749 transparent_occluder
1750 ? Push<DrawShadowTransparentOccluderOp>(0,
path, color, elevation,
1752 : Push<DrawShadowOp>(0,
path, color, elevation, dpr);
1753 UpdateLayerOpacityCompatibility(
false);
1754 UpdateLayerResult(result, DlBlendMode::kSrcOver);
1759bool DisplayListBuilder::AdjustBoundsForPaint(
DlRect& bounds,
1768 DisplayListSpecialGeometryFlags special_flags =
1775 special_flags.may_have_acute_joins()) {
1779 special_flags.may_have_diagonal_caps()) {
1780 pad = std::max(pad, SK_ScalarSqrt2);
1783 pad *= std::max(current_.
getStrokeWidth() * 0.5f, min_stroke_width);
1784 bounds = bounds.
Expand(pad, pad);
1791 switch (filter->type()) {
1794 DlScalar mask_sigma_pad = filter->asBlur()->sigma() * 3.0;
1795 bounds = bounds.
Expand(mask_sigma_pad, mask_sigma_pad);
1810 if (!filter->map_local_bounds(bounds, dl_bounds)) {
1820bool DisplayListBuilder::AccumulateUnbounded(
const SaveInfo& save) {
1821 if (!save.has_valid_clip) {
1822 save.layer_info->is_unbounded =
true;
1824 DlRect global_clip = save.global_state.GetDeviceCullCoverage();
1825 DlRect layer_clip = save.global_state.GetLocalCullCoverage();
1826 if (global_clip.IsEmpty() || !save.layer_state.mapAndClipRect(&layer_clip)) {
1829 if (rtree_data_.has_value()) {
1830 FML_DCHECK(save.layer_info->global_space_accumulator.is_empty());
1831 rtree_data_->rects.push_back(global_clip);
1832 rtree_data_->indices.push_back(op_index_);
1834 save.layer_info->global_space_accumulator.accumulate(global_clip);
1836 save.layer_info->layer_local_accumulator.accumulate(layer_clip);
1840bool DisplayListBuilder::AccumulateOpBounds(
DlRect& bounds,
1841 DisplayListAttributeFlags flags) {
1842 if (AdjustBoundsForPaint(bounds, flags)) {
1843 return AccumulateBounds(bounds);
1845 return AccumulateUnbounded();
1849bool DisplayListBuilder::AccumulateBounds(
const DlRect& bounds,
1852 if (bounds.IsEmpty()) {
1857 if (!layer.global_state.mapAndClipRect(bounds, &global_bounds) ||
1858 !layer.layer_state.mapAndClipRect(bounds, &layer_bounds)) {
1861 if (rtree_data_.has_value()) {
1862 FML_DCHECK(layer.layer_info->global_space_accumulator.is_empty());
1864 rtree_data_->rects.push_back(global_bounds);
1865 rtree_data_->indices.push_back(
id);
1868 layer.layer_info->global_space_accumulator.accumulate(global_bounds);
1870 layer.layer_info->layer_local_accumulator.accumulate(layer_bounds);
1874bool DisplayListBuilder::SaveInfo::AccumulateBoundsLocal(
const DlRect& bounds) {
1875 if (bounds.IsEmpty()) {
1879 if (!layer_state.mapAndClipRect(bounds, &local_bounds)) {
1882 layer_info->layer_local_accumulator.accumulate(local_bounds);
1886bool DisplayListBuilder::paint_nops_on_transparency() {
1918 case DlBlendMode::kClear:
1919 case DlBlendMode::kSrc:
1920 case DlBlendMode::kSrcIn:
1921 case DlBlendMode::kDstIn:
1922 case DlBlendMode::kSrcOut:
1923 case DlBlendMode::kDstATop:
1924 case DlBlendMode::kModulate:
1930 case DlBlendMode::kDst:
1931 case DlBlendMode::kSrcOver:
1932 case DlBlendMode::kDstOver:
1933 case DlBlendMode::kDstOut:
1934 case DlBlendMode::kSrcATop:
1935 case DlBlendMode::kXor:
1936 case DlBlendMode::kPlus:
1937 case DlBlendMode::kScreen:
1938 case DlBlendMode::kOverlay:
1939 case DlBlendMode::kDarken:
1941 case DlBlendMode::kLighten:
1943 case DlBlendMode::kColorDodge:
1944 case DlBlendMode::kColorBurn:
1945 case DlBlendMode::kHardLight:
1946 case DlBlendMode::kSoftLight:
1947 case DlBlendMode::kDifference:
1949 case DlBlendMode::kExclusion:
1950 case DlBlendMode::kMultiply:
1951 case DlBlendMode::kHue:
1952 case DlBlendMode::kSaturation:
1953 case DlBlendMode::kColor:
1954 case DlBlendMode::kLuminosity:
1960DlColor DisplayListBuilder::GetEffectiveColor(
const DlPaint& paint,
1961 DisplayListAttributeFlags flags) {
1963 if (flags.applies_color()) {
1964 const DlColorSource* source = paint.getColorSourcePtr();
1970 color = paint.getColor();
1972 }
else if (flags.applies_alpha()) {
1983 if (flags.applies_image_filter()) {
1984 auto filter = paint.getImageFilterPtr();
1986 if (!color.isTransparent() || filter->modifies_transparent_black()) {
1991 if (flags.applies_color_filter()) {
1992 auto filter = paint.getColorFilterPtr();
1994 if (!color.isTransparent() || filter->modifies_transparent_black()) {
2002DisplayListBuilder::OpResult DisplayListBuilder::PaintResult(
2003 const DlPaint& paint,
2004 DisplayListAttributeFlags flags) {
2005 if (current_info().is_nop) {
2006 return OpResult::kNoEffect;
2008 if (flags.applies_blend()) {
2009 switch (paint.getBlendMode()) {
2011 case DlBlendMode::kDst:
2012 return OpResult::kNoEffect;
2015 case DlBlendMode::kClear:
2016 return OpResult::kPreservesTransparency;
2018 case DlBlendMode::kHue:
2019 case DlBlendMode::kSaturation:
2020 case DlBlendMode::kColor:
2021 case DlBlendMode::kLuminosity:
2022 case DlBlendMode::kColorBurn:
2024 ? OpResult::kNoEffect
2025 : OpResult::kAffectsAll;
2028 case DlBlendMode::kSrcIn:
2029 return OpResult::kPreservesTransparency;
2032 case DlBlendMode::kSrcATop:
2033 case DlBlendMode::kDstOut:
2035 ? OpResult::kNoEffect
2036 : OpResult::kPreservesTransparency;
2039 case DlBlendMode::kSrc:
2040 case DlBlendMode::kSrcOut:
2041 case DlBlendMode::kDstATop:
2043 ? OpResult::kPreservesTransparency
2044 : OpResult::kAffectsAll;
2048 case DlBlendMode::kDstIn:
2049 return GetEffectiveColor(paint, flags).
isOpaque()
2050 ? OpResult::kNoEffect
2051 : OpResult::kPreservesTransparency;
2055 case DlBlendMode::kSrcOver:
2056 case DlBlendMode::kDstOver:
2057 case DlBlendMode::kXor:
2058 case DlBlendMode::kPlus:
2059 case DlBlendMode::kScreen:
2060 case DlBlendMode::kMultiply:
2061 case DlBlendMode::kOverlay:
2062 case DlBlendMode::kDarken:
2063 case DlBlendMode::kLighten:
2064 case DlBlendMode::kColorDodge:
2065 case DlBlendMode::kHardLight:
2066 case DlBlendMode::kSoftLight:
2067 case DlBlendMode::kDifference:
2068 case DlBlendMode::kExclusion:
2070 ? OpResult::kNoEffect
2071 : OpResult::kAffectsAll;
2074 case DlBlendMode::kModulate:
2076 ? OpResult::kNoEffect
2077 : OpResult::kPreservesTransparency;
2080 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
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
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
static constexpr DlRect kEmpty
@ kMiter
extends to miter limit
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
@ 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)
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)
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.
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)