performPaint method
RenderLayoutBox real paint things after basiclly paint box model. Override which to paint layout or intrinsic things. Used by RenderReplaced, RenderFlowLayout, RenderFlexLayout.
Implementation
@override
void performPaint(PaintingContext context, Offset offset) {
// If using inline formatting context, delegate painting to it first.
if (establishIFC && _inlineFormattingContext != null) {
// Calculate content offset (adjust for padding and border)
final contentOffset = Offset(
offset.dx + renderStyle.paddingLeft.computedValue + renderStyle.effectiveBorderLeftWidth.computedValue,
offset.dy + renderStyle.paddingTop.computedValue + renderStyle.effectiveBorderTopWidth.computedValue,
);
// Paint the inline formatting context content
_inlineFormattingContext!.paint(context, contentOffset);
// Paint outside list marker if needed after IFC content
_paintListMarkerIfNeeded(context, offset, contentOffset);
// Paint positioned direct children in proper stacking order.
for (final RenderBox child in paintingOrder) {
if (child is RenderBoxModel && child.renderStyle.isSelfPositioned()) {
final RenderLayoutParentData pd = child.parentData as RenderLayoutParentData;
if (child.hasSize) context.paintChild(child, pd.offset + offset);
}
}
return;
}
// Regular flow layout painting: skip RenderTextBox unless it paints itself (non-IFC)
Offset _accumulateOffsetFromDescendant(RenderObject descendant, RenderObject ancestor) {
Offset sum = Offset.zero;
RenderObject? cur = descendant;
while (cur != null && cur != ancestor) {
final Object? pd = (cur is RenderBox) ? (cur.parentData) : null;
if (pd is ContainerBoxParentData) {
sum += (pd as ContainerBoxParentData).offset;
} else if (pd is RenderLayoutParentData) {
sum += (pd as RenderLayoutParentData).offset;
}
cur = cur.parent as RenderObject?;
}
return sum;
}
for (int i = 0; i < paintingOrder.length; i++) {
RenderBox child = paintingOrder[i];
bool shouldPaint = !isPositionPlaceholder(child);
// Skip text boxes that are handled by IFC, but paint text boxes that paint themselves
if (child is RenderTextBox) {
shouldPaint = shouldPaint && (child as RenderTextBox).paintsSelf;
}
if (!shouldPaint) continue;
final RenderLayoutParentData childParentData = child.parentData as RenderLayoutParentData;
if (!child.hasSize) continue;
bool restoreFlag = false;
bool previous = false;
// Only suppress descendants' positive stacking when painting the document root
// (where we promote descendant positives to this level).
final bool promoteHere = (renderStyle as CSSRenderStyle).isDocumentRootBox();
if (promoteHere && child is RenderBoxModel) {
final CSSRenderStyle rs = child.renderStyle;
final int? zi = rs.zIndex;
final bool isPositive = zi != null && zi > 0;
if (!isPositive) {
previous = rs.suppressPositiveStackingFromDescendants;
rs.suppressPositiveStackingFromDescendants = true;
if (child is RenderLayoutBox) {
child.markChildrenNeedsSort();
} else if (child is RenderWidget) {
child.markChildrenNeedsSort();
}
restoreFlag = true;
}
}
final bool direct = identical(child.parent, this);
final Offset localOffset = direct ? childParentData.offset : _accumulateOffsetFromDescendant(child, this);
context.paintChild(child, localOffset + offset);
if (restoreFlag && child is RenderBoxModel) {
(child.renderStyle as CSSRenderStyle).suppressPositiveStackingFromDescendants = previous;
if (child is RenderLayoutBox) {
child.markChildrenNeedsSort();
} else if (child is RenderWidget) {
child.markChildrenNeedsSort();
}
}
}
// Non-IFC flow: still attempt to paint outside marker if applicable
_paintListMarkerIfNeeded(context, offset, offset + Offset(
renderStyle.paddingLeft.computedValue + renderStyle.effectiveBorderLeftWidth.computedValue,
renderStyle.paddingTop.computedValue + renderStyle.effectiveBorderTopWidth.computedValue,
));
}