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) {
464 AccumulateUnbounded();
471 rtree_data_.has_value() ? rtree_data_->rects.size() : 0u;
473 save_stack_.emplace_back(¤t_info(), filter, rtree_index);
476 FML_DCHECK(!current_info().has_deferred_save_op);
477 current_info().save_offset = save_offset;
478 current_info().save_depth = save_depth;
485 current_info().global_state.GetDeviceCullCoverage();
486 DlMatrix matrix = current_info().global_state.matrix();
490 if (filter->get_input_device_bounds(output_bounds, matrix,
492 current_info().global_state.resetDeviceCullRect(
498 current_info().global_state.resetDeviceCullRect(
kMaxCullRect);
516 record_bounds = bounds;
522 Push<SaveLayerBackdropOp>(0, options, record_bounds, backdrop,
525 Push<SaveLayerOp>(0, options, record_bounds);
534 if (!current_opacity_compatibility_ || filter) {
535 UpdateLayerOpacityCompatibility(
false);
542 std::optional<int64_t> backdrop_id) {
545 if (bounds.has_value()) {
547 temp_bounds = *bounds;
551 if (paint !=
nullptr) {
553 SetAttributesFromPaint(*paint,
556 saveLayer(temp_bounds, options, backdrop, backdrop_id);
560 if (save_stack_.size() <= 1) {
564 if (!current_info().has_deferred_save_op) {
566 current_info().save_offset);
568 op->
type == DisplayListOpType::kSaveLayer ||
569 op->
type == DisplayListOpType::kSaveLayerBackdrop);
574 if (current_info().is_save_layer) {
586 save_stack_.pop_back();
589void DisplayListBuilder::RestoreLayer() {
592 FML_DCHECK(!current_info().has_deferred_save_op);
597 depth_ += render_op_depth_cost_;
599 DlRect content_bounds = current_layer().layer_local_accumulator.GetBounds();
602 storage_.
base() + current_info().save_offset);
604 layer_op->
type == DisplayListOpType::kSaveLayerBackdrop);
608 if (!content_bounds.
IsEmpty() && !user_bounds.
Contains(content_bounds)) {
613 layer_op->
rect = content_bounds;
616 if (current_layer().contains_backdrop_filter) {
620 if (current_layer().is_group_opacity_compatible()) {
624 if (current_layer().is_unbounded) {
631 TransferLayerBounds(content_bounds);
665void DisplayListBuilder::TransferLayerBounds(
const DlRect& content_bounds) {
666 auto& filter = current_layer().filter;
672 current_layer().global_space_accumulator.is_empty());
674 parent_info().AccumulateBoundsLocal(content_bounds);
675 parent_layer().global_space_accumulator.accumulate(
676 current_layer().global_space_accumulator);
680 bool parent_is_flooded =
false;
681 DlRect bounds_for_parent = content_bounds;
688 const DlRect clip = parent_info().global_state.GetDeviceCullCoverage();
689 const DlMatrix matrix = parent_info().global_state.matrix();
691 if (rtree_data_.has_value()) {
694 FML_DCHECK(current_layer().global_space_accumulator.is_empty());
695 FML_DCHECK(parent_layer().global_space_accumulator.is_empty());
708 if (AdjustRTreeRects(rtree_data_.value(), *filter, matrix, clip,
709 current_layer().rtree_rects_start_index)) {
710 parent_is_flooded =
true;
713 DlRect global_bounds = current_layer().global_space_accumulator.GetBounds();
714 if (!global_bounds.IsEmpty()) {
716 if (!filter->map_device_bounds(global_ibounds, matrix, global_ibounds)) {
717 parent_is_flooded =
true;
720 std::optional<DlRect> clipped_bounds = global_bounds.Intersection(clip);
721 if (clipped_bounds.has_value()) {
722 parent_layer().global_space_accumulator.accumulate(
723 clipped_bounds.value());
739 if (!parent_is_flooded && !bounds_for_parent.IsEmpty()) {
740 DlRect mappable_bounds = bounds_for_parent;
741 if (filter->map_local_bounds(mappable_bounds, mappable_bounds)) {
742 bounds_for_parent = mappable_bounds;
744 parent_is_flooded =
true;
748 if (parent_is_flooded) {
758 AccumulateUnbounded(parent_info());
760 parent_info().AccumulateBoundsLocal(bounds_for_parent);
764bool DisplayListBuilder::AdjustRTreeRects(RTreeData&
data,
765 const DlImageFilter& filter,
768 size_t rect_start_index) {
769 auto& rects =
data.rects;
770 auto& indices =
data.indices;
773 auto rect_keep = rect_start_index;
774 for (
size_t i = rect_start_index;
i < rects.size();
i++) {
777 if (filter.map_device_bounds(ibounds, matrix, ibounds)) {
783 auto clipped_bounds = bounds.Intersection(clip);
784 if (clipped_bounds.has_value()) {
785 indices[rect_keep] = indices[
i];
786 rects[rect_keep] = clipped_bounds.value();
790 indices.resize(rect_keep);
791 rects.resize(rect_keep);
803 if (std::isfinite(tx) && std::isfinite(ty) && (tx != 0.0 || ty != 0.0)) {
804 checkForDeferredSave();
805 Push<TranslateOp>(0, tx, ty);
811 if (std::isfinite(sx) && std::isfinite(sy) && (sx != 1.0 || sy != 1.0)) {
812 checkForDeferredSave();
813 Push<ScaleOp>(0, sx, sy);
814 global_state().
scale(sx, sy);
815 layer_local_state().
scale(sx, sy);
819 if (SkScalarMod(degrees, 360.0) != 0.0) {
820 checkForDeferredSave();
821 Push<RotateOp>(0, degrees);
827 if (std::isfinite(sx) && std::isfinite(sy) && (sx != 0.0 || sy != 0.0)) {
828 checkForDeferredSave();
829 Push<SkewOp>(0, sx, sy);
830 global_state().
skew(sx, sy);
831 layer_local_state().
skew(sx, sy);
841 if (std::isfinite(mxx) && std::isfinite(myx) &&
842 std::isfinite(mxy) && std::isfinite(myy) &&
843 std::isfinite(mxt) && std::isfinite(myt)) {
844 if (mxx == 1 && mxy == 0 &&
845 myx == 0 && myy == 1) {
848 checkForDeferredSave();
849 Push<Transform2DAffineOp>(0,
867 mzx == 0 && mzy == 0 && mzz == 1 && mzt == 0 &&
868 mwx == 0 && mwy == 0 && mwz == 0 && mwt == 1) {
869 transform2DAffine(mxx, mxy, mxt,
871 }
else if (std::isfinite(mxx) && std::isfinite(mxy) &&
872 std::isfinite(mxz) && std::isfinite(mxt) &&
873 std::isfinite(myx) && std::isfinite(myy) &&
874 std::isfinite(myz) && std::isfinite(myt) &&
875 std::isfinite(mzx) && std::isfinite(mzy) &&
876 std::isfinite(mzz) && std::isfinite(mzt) &&
877 std::isfinite(mwx) && std::isfinite(mwy) &&
878 std::isfinite(mwz) && std::isfinite(mwt)) {
879 checkForDeferredSave();
880 Push<TransformFullPerspectiveOp>(0,
897 checkForDeferredSave();
898 Push<TransformResetOp>(0);
911 if (!layer_local_state().inverseTransform(global_state())) {
924 matrix.
e[0][0], matrix.
e[1][0], matrix.
e[2][0], matrix.
e[3][0],
925 matrix.
e[0][1], matrix.
e[1][1], matrix.
e[2][1], matrix.
e[3][1],
926 matrix.
e[0][2], matrix.
e[1][2], matrix.
e[2][2], matrix.
e[3][2],
927 matrix.
e[0][3], matrix.
e[1][3], matrix.
e[2][3], matrix.
e[3][3]);
936 if (current_info().is_nop) {
940 layer_local_state().rect_covers_cull(rect)) {
943 global_state().
clipRect(rect, clip_op, is_aa);
944 layer_local_state().
clipRect(rect, clip_op, is_aa);
945 if (global_state().is_cull_rect_empty() ||
946 layer_local_state().is_cull_rect_empty()) {
947 current_info().is_nop =
true;
950 current_info().has_valid_clip =
true;
951 checkForDeferredSave();
954 Push<ClipIntersectRectOp>(0, rect, is_aa);
957 Push<ClipDifferenceRectOp>(0, rect, is_aa);
967 if (current_info().is_nop) {
971 layer_local_state().oval_covers_cull(bounds)) {
974 global_state().
clipOval(bounds, clip_op, is_aa);
975 layer_local_state().
clipOval(bounds, clip_op, is_aa);
976 if (global_state().is_cull_rect_empty() ||
977 layer_local_state().is_cull_rect_empty()) {
978 current_info().is_nop =
true;
981 current_info().has_valid_clip =
true;
982 checkForDeferredSave();
985 Push<ClipIntersectOvalOp>(0, bounds, is_aa);
988 Push<ClipDifferenceOvalOp>(0, bounds, is_aa);
1003 if (current_info().is_nop) {
1007 layer_local_state().rrect_covers_cull(rrect)) {
1010 global_state().
clipRRect(rrect, clip_op, is_aa);
1011 layer_local_state().
clipRRect(rrect, clip_op, is_aa);
1012 if (global_state().is_cull_rect_empty() ||
1013 layer_local_state().is_cull_rect_empty()) {
1014 current_info().is_nop =
true;
1017 current_info().has_valid_clip =
true;
1018 checkForDeferredSave();
1021 Push<ClipIntersectRoundRectOp>(0, rrect, is_aa);
1024 Push<ClipDifferenceRoundRectOp>(0, rrect, is_aa);
1039 if (current_info().is_nop) {
1043 layer_local_state().rsuperellipse_covers_cull(rse)) {
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<ClipIntersectRoundSuperellipseOp>(0, rse, is_aa);
1060 Push<ClipDifferenceRoundSuperellipseOp>(0, rse, is_aa);
1067 if (current_info().is_nop) {
1072 if (
path.IsRect(&rect)) {
1076 if (
path.IsOval(&rect)) {
1081 if (
path.IsRoundRect(&rrect)) {
1088 if (global_state().is_cull_rect_empty() ||
1089 layer_local_state().is_cull_rect_empty()) {
1090 current_info().is_nop =
true;
1093 current_info().has_valid_clip =
true;
1094 checkForDeferredSave();
1097 Push<ClipIntersectPathOp>(0,
path, is_aa);
1100 Push<ClipDifferencePathOp>(0,
path, is_aa);
1109void DisplayListBuilder::drawPaint() {
1111 if (result != OpResult::kNoEffect && AccumulateUnbounded()) {
1112 Push<DrawPaintOp>(0);
1113 CheckLayerOpacityCompatibility();
1114 UpdateLayerResult(result);
1122 OpResult result = PaintResult(
DlPaint(color).setBlendMode(
mode));
1123 if (result != OpResult::kNoEffect && AccumulateUnbounded()) {
1124 Push<DrawColorOp>(0, color,
mode);
1125 CheckLayerOpacityCompatibility(
mode);
1126 UpdateLayerResult(result,
mode);
1129void DisplayListBuilder::drawLine(
const DlPoint& p0,
const DlPoint& p1) {
1133 OpResult result = PaintResult(current_, flags);
1134 if (result != OpResult::kNoEffect && AccumulateOpBounds(bounds, flags)) {
1135 Push<DrawLineOp>(0, p0, p1);
1136 CheckLayerOpacityCompatibility();
1137 UpdateLayerResult(result);
1146void DisplayListBuilder::drawDashedLine(
const DlPoint& p0,
1153 OpResult result = PaintResult(current_, flags);
1154 if (result != OpResult::kNoEffect && AccumulateOpBounds(bounds, flags)) {
1155 Push<DrawDashedLineOp>(0, p0, p1, on_length, off_length);
1156 CheckLayerOpacityCompatibility();
1157 UpdateLayerResult(result);
1166 drawDashedLine(p0, p1, on_length, off_length);
1168void DisplayListBuilder::drawRect(
const DlRect& rect) {
1170 OpResult result = PaintResult(current_, flags);
1171 if (result != OpResult::kNoEffect &&
1173 Push<DrawRectOp>(0, rect);
1174 CheckLayerOpacityCompatibility();
1175 UpdateLayerResult(result);
1182void DisplayListBuilder::drawOval(
const DlRect& bounds) {
1184 OpResult result = PaintResult(current_, flags);
1185 if (result != OpResult::kNoEffect &&
1186 AccumulateOpBounds(bounds.
GetPositive(), flags)) {
1187 Push<DrawOvalOp>(0, bounds);
1188 CheckLayerOpacityCompatibility();
1189 UpdateLayerResult(result);
1196void DisplayListBuilder::drawCircle(
const DlPoint& center,
DlScalar radius) {
1198 OpResult result = PaintResult(current_, flags);
1199 if (result != OpResult::kNoEffect) {
1201 center.x + radius, center.y + radius);
1202 if (AccumulateOpBounds(bounds, flags)) {
1203 Push<DrawCircleOp>(0, center, radius);
1204 CheckLayerOpacityCompatibility();
1205 UpdateLayerResult(result);
1213 drawCircle(center, radius);
1215void DisplayListBuilder::drawRoundRect(
const DlRoundRect& rrect) {
1218 }
else if (rrect.
IsOval()) {
1222 OpResult result = PaintResult(current_, flags);
1223 if (result != OpResult::kNoEffect &&
1224 AccumulateOpBounds(rrect.
GetBounds(), flags)) {
1225 Push<DrawRoundRectOp>(0, rrect);
1226 CheckLayerOpacityCompatibility();
1227 UpdateLayerResult(result);
1234 drawRoundRect(rrect);
1236void DisplayListBuilder::drawDiffRoundRect(
const DlRoundRect& outer,
1239 OpResult result = PaintResult(current_, flags);
1240 if (result != OpResult::kNoEffect &&
1241 AccumulateOpBounds(outer.
GetBounds(), flags)) {
1242 Push<DrawDiffRoundRectOp>(0, outer, inner);
1243 CheckLayerOpacityCompatibility();
1244 UpdateLayerResult(result);
1251 drawDiffRoundRect(outer, inner);
1256 }
else if (rse.
IsOval()) {
1260 OpResult result = PaintResult(current_, flags);
1261 if (result != OpResult::kNoEffect &&
1262 AccumulateOpBounds(rse.
GetBounds(), flags)) {
1266 Push<DrawRoundSuperellipseOp>(0, rse);
1268 DlPathBuilder builder;
1271 Push<DrawPathOp>(0, builder.TakePath());
1273 CheckLayerOpacityCompatibility();
1274 UpdateLayerResult(result);
1281 drawRoundSuperellipse(rse);
1283void DisplayListBuilder::drawPath(
const DlPath&
path) {
1285 OpResult result = PaintResult(current_, flags);
1286 if (result != OpResult::kNoEffect) {
1287 bool is_visible = AccumulateOpBounds(
path.GetBounds(), flags);
1289 Push<DrawPathOp>(0,
path);
1290 CheckLayerOpacityHairlineCompatibility();
1291 UpdateLayerResult(result);
1300void DisplayListBuilder::drawArc(
const DlRect& bounds,
1308 OpResult result = PaintResult(current_, flags);
1312 if (result != OpResult::kNoEffect && AccumulateOpBounds(bounds, flags)) {
1313 Push<DrawArcOp>(0, bounds, start, sweep, useCenter);
1315 CheckLayerOpacityHairlineCompatibility();
1317 CheckLayerOpacityCompatibility();
1319 UpdateLayerResult(result);
1327 SetAttributesFromPaint(
1329 drawArc(bounds,
start, sweep, useCenter);
1344void DisplayListBuilder::drawPoints(
DlPointMode mode,
1350 DisplayListAttributeFlags flags = FlagsForPointMode(mode);
1351 OpResult result = PaintResult(current_, flags);
1352 if (result == OpResult::kNoEffect) {
1357 int bytes = count *
sizeof(
DlPoint);
1358 AccumulationRect accumulator;
1359 for (
size_t i = 0;
i < count;
i++) {
1360 accumulator.accumulate(pts[
i]);
1362 if (!AccumulateOpBounds(accumulator.GetBounds(), flags)) {
1369 data_ptr = Push<DrawPointsOp>(bytes, count);
1372 data_ptr = Push<DrawLinesOp>(bytes, count);
1375 data_ptr = Push<DrawPolygonOp>(bytes, count);
1381 CopyV(data_ptr, pts, count);
1387 current_layer().layer_local_accumulator.record_overlapping_bounds();
1392 CheckLayerOpacityCompatibility();
1393 UpdateLayerResult(result);
1399 SetAttributesFromPaint(paint, FlagsForPointMode(
mode));
1400 drawPoints(
mode, count, pts);
1402void DisplayListBuilder::drawVertices(
1403 const std::shared_ptr<DlVertices>& vertices,
1406 OpResult result = PaintResult(current_, flags);
1407 if (result != OpResult::kNoEffect &&
1408 AccumulateOpBounds(vertices->GetBounds(), flags)) {
1409 Push<DrawVerticesOp>(0, vertices, mode);
1414 UpdateLayerOpacityCompatibility(
false);
1415 UpdateLayerResult(result);
1424 current_layer().layer_local_accumulator.record_overlapping_bounds();
1428 const std::shared_ptr<DlVertices>& vertices,
1432 drawVertices(vertices,
mode);
1435void DisplayListBuilder::drawImage(
const sk_sp<DlImage>
image,
1438 bool render_with_attributes) {
1442 OpResult result = PaintResult(current_, flags);
1443 if (result == OpResult::kNoEffect) {
1448 if (AccumulateOpBounds(bounds, flags)) {
1449 render_with_attributes
1450 ? Push<DrawImageWithAttrOp>(0,
image, point, sampling)
1451 : Push<DrawImageOp>(0,
image, point, sampling);
1452 CheckLayerOpacityCompatibility(render_with_attributes);
1453 UpdateLayerResult(result, render_with_attributes);
1454 is_ui_thread_safe_ = is_ui_thread_safe_ &&
image->isUIThreadSafe();
1461 if (paint !=
nullptr) {
1462 SetAttributesFromPaint(*paint,
1464 drawImage(
image, point, sampling,
true);
1466 drawImage(
image, point, sampling,
false);
1469void DisplayListBuilder::drawImageRect(
const sk_sp<DlImage>
image,
1473 bool render_with_attributes,
1478 OpResult result = PaintResult(current_, flags);
1479 if (result != OpResult::kNoEffect && AccumulateOpBounds(dst, flags)) {
1480 Push<DrawImageRectOp>(0,
image, src, dst, sampling, render_with_attributes,
1482 CheckLayerOpacityCompatibility(render_with_attributes);
1483 UpdateLayerResult(result, render_with_attributes);
1484 is_ui_thread_safe_ = is_ui_thread_safe_ &&
image->isUIThreadSafe();
1493 if (paint !=
nullptr) {
1494 SetAttributesFromPaint(*paint,
1496 drawImageRect(
image, src, dst, sampling,
true, constraint);
1498 drawImageRect(
image, src, dst, sampling,
false, constraint);
1501void DisplayListBuilder::drawImageNine(
const sk_sp<DlImage>
image,
1505 bool render_with_attributes) {
1509 OpResult result = PaintResult(current_, flags);
1510 if (result != OpResult::kNoEffect && AccumulateOpBounds(dst, flags)) {
1511 render_with_attributes
1512 ? Push<DrawImageNineWithAttrOp>(0,
image, center, dst, filter)
1513 : Push<DrawImageNineOp>(0,
image, center, dst, filter);
1514 CheckLayerOpacityCompatibility(render_with_attributes);
1515 UpdateLayerResult(result, render_with_attributes);
1516 is_ui_thread_safe_ = is_ui_thread_safe_ &&
image->isUIThreadSafe();
1524 if (paint !=
nullptr) {
1525 SetAttributesFromPaint(*paint,
1527 drawImageNine(
image, center, dst, filter,
true);
1529 drawImageNine(
image, center, dst, filter,
false);
1532void DisplayListBuilder::drawAtlas(
const sk_sp<DlImage> atlas,
1540 bool render_with_attributes) {
1544 OpResult result = PaintResult(current_, flags);
1545 if (result == OpResult::kNoEffect) {
1549 AccumulationRect accumulator;
1550 for (
int i = 0;
i < count;
i++) {
1552 xform[
i].
GetQuad(src.GetWidth(), src.GetHeight(), quad);
1553 for (
int j = 0; j < 4; j++) {
1554 accumulator.accumulate(quad[j]);
1557 if (accumulator.is_empty() ||
1558 !AccumulateOpBounds(accumulator.GetBounds(), flags)) {
1572 if (accumulator.overlap_detected()) {
1573 current_layer().layer_local_accumulator.record_overlapping_bounds();
1578 if (colors !=
nullptr) {
1579 bytes += count *
sizeof(
DlColor);
1580 if (cull_rect !=
nullptr) {
1582 Push<DrawAtlasCulledOp>(bytes, atlas, count, mode, sampling,
true,
1583 *cull_rect, render_with_attributes);
1585 data_ptr = Push<DrawAtlasOp>(bytes, atlas, count, mode, sampling,
true,
1586 render_with_attributes);
1588 CopyV(data_ptr, xform, count, tex, count, colors, count);
1590 if (cull_rect !=
nullptr) {
1592 Push<DrawAtlasCulledOp>(bytes, atlas, count, mode, sampling,
false,
1593 *cull_rect, render_with_attributes);
1595 data_ptr = Push<DrawAtlasOp>(bytes, atlas, count, mode, sampling,
false,
1596 render_with_attributes);
1598 CopyV(data_ptr, xform, count, tex, count);
1603 UpdateLayerOpacityCompatibility(
false);
1604 UpdateLayerResult(result, render_with_attributes);
1605 is_ui_thread_safe_ = is_ui_thread_safe_ && atlas->isUIThreadSafe();
1616 if (paint !=
nullptr) {
1617 SetAttributesFromPaint(*paint,
1619 drawAtlas(atlas, xform, tex, colors, count,
mode, sampling, cull_rect,
1622 drawAtlas(atlas, xform, tex, colors, count,
mode, sampling, cull_rect,
1629 if (!std::isfinite(opacity) || opacity <= SK_ScalarNearlyZero ||
1630 display_list->op_count() == 0 || display_list->GetBounds().IsEmpty() ||
1631 current_info().is_nop) {
1634 const DlRect bounds = display_list->GetBounds();
1636 sk_sp<const DlRTree> rtree;
1637 if (display_list->root_is_unbounded()) {
1638 accumulated = AccumulateUnbounded();
1639 }
else if (!rtree_data_.has_value() || !(rtree = display_list->rtree())) {
1642 std::list<DlRect> rects =
1644 accumulated =
false;
1645 for (
const DlRect& rect : rects) {
1657 DlPaint current_paint = current_;
1658 Push<DrawDisplayListOp>(0, display_list,
1659 opacity < SK_Scalar1 ? opacity : SK_Scalar1);
1669 depth_ += display_list->total_depth();
1671 is_ui_thread_safe_ = is_ui_thread_safe_ && display_list->isUIThreadSafe();
1675 SetAttributesFromPaint(current_paint,
1684 nested_op_count_ += display_list->op_count(
true) - 1;
1685 nested_bytes_ += display_list->bytes(
true);
1686 UpdateLayerOpacityCompatibility(display_list->can_apply_group_opacity());
1689 UpdateLayerResult(display_list->modifies_transparent_black()
1690 ? OpResult::kAffectsAll
1691 : OpResult::kPreservesTransparency,
1692 display_list->max_root_blend_mode());
1693 if (display_list->root_has_backdrop_filter()) {
1694 current_layer().contains_backdrop_filter =
true;
1698void DisplayListBuilder::drawText(
const std::shared_ptr<DlText>&
text,
1702 OpResult result = PaintResult(current_, flags);
1703 if (result == OpResult::kNoEffect) {
1707 bool unclipped = AccumulateOpBounds(bounds, flags);
1712#if defined(OS_FUCHSIA)
1716 Push<DrawTextOp>(0,
text,
x,
y);
1722 UpdateLayerOpacityCompatibility(
false);
1723 UpdateLayerResult(result);
1738 bool transparent_occluder,
1740 OpResult result = PaintResult(
DlPaint(color));
1741 if (result != OpResult::kNoEffect) {
1745 transparent_occluder
1746 ? Push<DrawShadowTransparentOccluderOp>(0,
path, color, elevation,
1748 : Push<DrawShadowOp>(0,
path, color, elevation, dpr);
1749 UpdateLayerOpacityCompatibility(
false);
1750 UpdateLayerResult(result, DlBlendMode::kSrcOver);
1755bool DisplayListBuilder::AdjustBoundsForPaint(
DlRect& bounds,
1764 DisplayListSpecialGeometryFlags special_flags =
1771 special_flags.may_have_acute_joins()) {
1775 special_flags.may_have_diagonal_caps()) {
1776 pad = std::max(pad, SK_ScalarSqrt2);
1779 pad *= std::max(current_.
getStrokeWidth() * 0.5f, min_stroke_width);
1780 bounds = bounds.
Expand(pad, pad);
1787 switch (filter->type()) {
1790 DlScalar mask_sigma_pad = filter->asBlur()->sigma() * 3.0;
1791 bounds = bounds.
Expand(mask_sigma_pad, mask_sigma_pad);
1806 if (!filter->map_local_bounds(bounds, dl_bounds)) {
1816bool DisplayListBuilder::AccumulateUnbounded(
const SaveInfo& save) {
1817 if (!save.has_valid_clip) {
1818 save.layer_info->is_unbounded =
true;
1820 DlRect global_clip = save.global_state.GetDeviceCullCoverage();
1821 DlRect layer_clip = save.global_state.GetLocalCullCoverage();
1822 if (global_clip.IsEmpty() || !save.layer_state.mapAndClipRect(&layer_clip)) {
1825 if (rtree_data_.has_value()) {
1826 FML_DCHECK(save.layer_info->global_space_accumulator.is_empty());
1827 rtree_data_->rects.push_back(global_clip);
1828 rtree_data_->indices.push_back(op_index_);
1830 save.layer_info->global_space_accumulator.accumulate(global_clip);
1832 save.layer_info->layer_local_accumulator.accumulate(layer_clip);
1836bool DisplayListBuilder::AccumulateOpBounds(
DlRect& bounds,
1837 DisplayListAttributeFlags flags) {
1838 if (AdjustBoundsForPaint(bounds, flags)) {
1839 return AccumulateBounds(bounds);
1841 return AccumulateUnbounded();
1845bool DisplayListBuilder::AccumulateBounds(
const DlRect& bounds,
1848 if (bounds.IsEmpty()) {
1853 if (!layer.global_state.mapAndClipRect(bounds, &global_bounds) ||
1854 !layer.layer_state.mapAndClipRect(bounds, &layer_bounds)) {
1857 if (rtree_data_.has_value()) {
1858 FML_DCHECK(layer.layer_info->global_space_accumulator.is_empty());
1860 rtree_data_->rects.push_back(global_bounds);
1861 rtree_data_->indices.push_back(
id);
1864 layer.layer_info->global_space_accumulator.accumulate(global_bounds);
1866 layer.layer_info->layer_local_accumulator.accumulate(layer_bounds);
1870bool DisplayListBuilder::SaveInfo::AccumulateBoundsLocal(
const DlRect& bounds) {
1871 if (bounds.IsEmpty()) {
1875 if (!layer_state.mapAndClipRect(bounds, &local_bounds)) {
1878 layer_info->layer_local_accumulator.accumulate(local_bounds);
1882bool DisplayListBuilder::paint_nops_on_transparency() {
1914 case DlBlendMode::kClear:
1915 case DlBlendMode::kSrc:
1916 case DlBlendMode::kSrcIn:
1917 case DlBlendMode::kDstIn:
1918 case DlBlendMode::kSrcOut:
1919 case DlBlendMode::kDstATop:
1920 case DlBlendMode::kModulate:
1926 case DlBlendMode::kDst:
1927 case DlBlendMode::kSrcOver:
1928 case DlBlendMode::kDstOver:
1929 case DlBlendMode::kDstOut:
1930 case DlBlendMode::kSrcATop:
1931 case DlBlendMode::kXor:
1932 case DlBlendMode::kPlus:
1933 case DlBlendMode::kScreen:
1934 case DlBlendMode::kOverlay:
1935 case DlBlendMode::kDarken:
1937 case DlBlendMode::kLighten:
1939 case DlBlendMode::kColorDodge:
1940 case DlBlendMode::kColorBurn:
1941 case DlBlendMode::kHardLight:
1942 case DlBlendMode::kSoftLight:
1943 case DlBlendMode::kDifference:
1945 case DlBlendMode::kExclusion:
1946 case DlBlendMode::kMultiply:
1947 case DlBlendMode::kHue:
1948 case DlBlendMode::kSaturation:
1949 case DlBlendMode::kColor:
1950 case DlBlendMode::kLuminosity:
1956DlColor DisplayListBuilder::GetEffectiveColor(
const DlPaint& paint,
1957 DisplayListAttributeFlags flags) {
1959 if (flags.applies_color()) {
1960 const DlColorSource* source = paint.getColorSourcePtr();
1966 color = paint.getColor();
1968 }
else if (flags.applies_alpha()) {
1979 if (flags.applies_image_filter()) {
1980 auto filter = paint.getImageFilterPtr();
1982 if (!color.isTransparent() || filter->modifies_transparent_black()) {
1987 if (flags.applies_color_filter()) {
1988 auto filter = paint.getColorFilterPtr();
1990 if (!color.isTransparent() || filter->modifies_transparent_black()) {
1998DisplayListBuilder::OpResult DisplayListBuilder::PaintResult(
1999 const DlPaint& paint,
2000 DisplayListAttributeFlags flags) {
2001 if (current_info().is_nop) {
2002 return OpResult::kNoEffect;
2004 if (flags.applies_blend()) {
2005 switch (paint.getBlendMode()) {
2007 case DlBlendMode::kDst:
2008 return OpResult::kNoEffect;
2011 case DlBlendMode::kClear:
2012 return OpResult::kPreservesTransparency;
2014 case DlBlendMode::kHue:
2015 case DlBlendMode::kSaturation:
2016 case DlBlendMode::kColor:
2017 case DlBlendMode::kLuminosity:
2018 case DlBlendMode::kColorBurn:
2020 ? OpResult::kNoEffect
2021 : OpResult::kAffectsAll;
2024 case DlBlendMode::kSrcIn:
2025 return OpResult::kPreservesTransparency;
2028 case DlBlendMode::kSrcATop:
2029 case DlBlendMode::kDstOut:
2031 ? OpResult::kNoEffect
2032 : OpResult::kPreservesTransparency;
2035 case DlBlendMode::kSrc:
2036 case DlBlendMode::kSrcOut:
2037 case DlBlendMode::kDstATop:
2039 ? OpResult::kPreservesTransparency
2040 : OpResult::kAffectsAll;
2044 case DlBlendMode::kDstIn:
2045 return GetEffectiveColor(paint, flags).
isOpaque()
2046 ? OpResult::kNoEffect
2047 : OpResult::kPreservesTransparency;
2051 case DlBlendMode::kSrcOver:
2052 case DlBlendMode::kDstOver:
2053 case DlBlendMode::kXor:
2054 case DlBlendMode::kPlus:
2055 case DlBlendMode::kScreen:
2056 case DlBlendMode::kMultiply:
2057 case DlBlendMode::kOverlay:
2058 case DlBlendMode::kDarken:
2059 case DlBlendMode::kLighten:
2060 case DlBlendMode::kColorDodge:
2061 case DlBlendMode::kHardLight:
2062 case DlBlendMode::kSoftLight:
2063 case DlBlendMode::kDifference:
2064 case DlBlendMode::kExclusion:
2066 ? OpResult::kNoEffect
2067 : OpResult::kAffectsAll;
2070 case DlBlendMode::kModulate:
2072 ? OpResult::kNoEffect
2073 : OpResult::kPreservesTransparency;
2076 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)