// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/// @docImport 'dart:ui';
///
/// @docImport 'package:flutter/widgets.dart';
///
/// @docImport 'box.dart';
/// @docImport 'paragraph.dart';
/// @docImport 'proxy_box.dart';
/// @docImport 'view.dart';
/// @docImport 'viewport.dart';
library;

import 'dart:ui' as ui show PictureRecorder;

import 'package:flutter/animation.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/painting.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/semantics.dart';

import 'binding.dart';
import 'debug.dart';
import 'layer.dart';

export 'package:flutter/foundation.dart'
    show
        DiagnosticPropertiesBuilder,
        DiagnosticsNode,
        DiagnosticsProperty,
        DoubleProperty,
        EnumProperty,
        ErrorDescription,
        ErrorHint,
        ErrorSummary,
        FlagProperty,
        FlutterError,
        InformationCollector,
        IntProperty,
        StringProperty;
export 'package:flutter/gestures.dart' show HitTestEntry, HitTestResult;
export 'package:flutter/painting.dart';

/// Base class for data associated with a [RenderObject] by its parent.
///
/// Some render objects wish to store data on their children, such as the
/// children's input parameters to the parent's layout algorithm or the
/// children's position relative to other children.
///
/// See also:
///
///  * [RenderObject.setupParentData], which [RenderObject] subclasses may
///    override to attach specific types of parent data to children.
class ParentData {
  /// Called when the RenderObject is removed from the tree.
  @protected
  @mustCallSuper
  void detach() {}

  @override
  String toString() => '<none>';
}

/// Signature for painting into a [PaintingContext].
///
/// The `offset` argument is the offset from the origin of the coordinate system
/// of the [PaintingContext.canvas] to the coordinate system of the callee.
///
/// Used by many of the methods of [PaintingContext].
typedef PaintingContextCallback = void Function(PaintingContext context, Offset offset);

/// Signature for transforming the given [Rect] to a different [Rect] with a
/// [Matrix4] transform.
typedef _TransformRect = Rect Function(Matrix4 transform, Rect rect);

/// A place to paint.
///
/// Rather than holding a canvas directly, [RenderObject]s paint using a painting
/// context. The painting context has a [Canvas], which receives the
/// individual draw operations, and also has functions for painting child
/// render objects.
///
/// When painting a child render object, the canvas held by the painting context
/// can change because the draw operations issued before and after painting the
/// child might be recorded in separate compositing layers. For this reason, do
/// not hold a reference to the canvas across operations that might paint
/// child render objects.
///
/// New [PaintingContext] objects are created automatically when using
/// [PaintingContext.repaintCompositedChild] and [pushLayer].
class PaintingContext extends ClipContext {
  /// Creates a painting context.
  ///
  /// Typically only called by [PaintingContext.repaintCompositedChild]
  /// and [pushLayer].
  @protected
  PaintingContext(this._containerLayer, this.estimatedBounds);

  final ContainerLayer _containerLayer;

  /// An estimate of the bounds within which the painting context's [canvas]
  /// will record painting commands. This can be useful for debugging.
  ///
  /// The canvas will allow painting outside these bounds.
  ///
  /// The [estimatedBounds] rectangle is in the [canvas] coordinate system.
  final Rect estimatedBounds;

  /// Repaint the given render object.
  ///
  /// The render object must be attached to a [PipelineOwner], must have a
  /// composited layer, and must be in need of painting. The render object's
  /// layer, if any, is re-used, along with any layers in the subtree that don't
  /// need to be repainted.
  ///
  /// See also:
  ///
  ///  * [RenderObject.isRepaintBoundary], which determines if a [RenderObject]
  ///    has a composited layer.
  static void repaintCompositedChild(RenderObject child, {bool debugAlsoPaintedParent = false}) {
    assert(child._needsPaint);
    _repaintCompositedChild(child, debugAlsoPaintedParent: debugAlsoPaintedParent);
  }

  static void _repaintCompositedChild(
    RenderObject child, {
    bool debugAlsoPaintedParent = false,
    PaintingContext? childContext,
  }) {
    assert(child.isRepaintBoundary);
    assert(() {
      // register the call for RepaintBoundary metrics
      child.debugRegisterRepaintBoundaryPaint(
        includedParent: debugAlsoPaintedParent,
        includedChild: true,
      );
      return true;
    }());
    var childLayer = child._layerHandle.layer as OffsetLayer?;
    if (childLayer == null) {
      assert(debugAlsoPaintedParent);
      assert(child._layerHandle.layer == null);

      // Not using the `layer` setter because the setter asserts that we not
      // replace the layer for repaint boundaries. That assertion does not
      // apply here because this is exactly the place designed to create a
      // layer for repaint boundaries.
      final OffsetLayer layer = child.updateCompositedLayer(oldLayer: null);
      child._layerHandle.layer = childLayer = layer;
    } else {
      assert(debugAlsoPaintedParent || childLayer.attached);
      Offset? debugOldOffset;
      assert(() {
        debugOldOffset = childLayer!.offset;
        return true;
      }());
      childLayer.removeAllChildren();
      final OffsetLayer updatedLayer = child.updateCompositedLayer(oldLayer: childLayer);
      assert(
        identical(updatedLayer, childLayer),
        '$child created a new layer instance $updatedLayer instead of reusing the '
        'existing layer $childLayer. See the documentation of RenderObject.updateCompositedLayer '
        'for more information on how to correctly implement this method.',
      );
      assert(debugOldOffset == updatedLayer.offset);
    }
    child._needsCompositedLayerUpdate = false;

    assert(identical(childLayer, child._layerHandle.layer));
    assert(child._layerHandle.layer is OffsetLayer);
    assert(() {
      childLayer!.debugCreator = child.debugCreator ?? child.runtimeType;
      return true;
    }());

    childContext ??= PaintingContext(childLayer, child.paintBounds);
    child._paintWithContext(childContext, Offset.zero);

    // Double-check that the paint method did not replace the layer (the first
    // check is done in the [layer] setter itself).
    assert(identical(childLayer, child._layerHandle.layer));
    childContext.stopRecordingIfNeeded();
  }

  /// Update the composited layer of [child] without repainting its children.
  ///
  /// The render object must be attached to a [PipelineOwner], must have a
  /// composited layer, and must be in need of a composited layer update but
  /// not in need of painting. The render object's layer is re-used, and none
  /// of its children are repaint or their layers updated.
  ///
  /// See also:
  ///
  ///  * [RenderObject.isRepaintBoundary], which determines if a [RenderObject]
  ///    has a composited layer.
  static void updateLayerProperties(RenderObject child) {
    assert(child.isRepaintBoundary && child._wasRepaintBoundary);
    assert(!child._needsPaint);
    assert(child._layerHandle.layer != null);

    final childLayer = child._layerHandle.layer! as OffsetLayer;
    Offset? debugOldOffset;
    assert(() {
      debugOldOffset = childLayer.offset;
      return true;
    }());
    final OffsetLayer updatedLayer = child.updateCompositedLayer(oldLayer: childLayer);
    assert(
      identical(updatedLayer, childLayer),
      '$child created a new layer instance $updatedLayer instead of reusing the '
      'existing layer $childLayer. See the documentation of RenderObject.updateCompositedLayer '
      'for more information on how to correctly implement this method.',
    );
    assert(debugOldOffset == updatedLayer.offset);
    child._needsCompositedLayerUpdate = false;
  }

  /// In debug mode, repaint the given render object using a custom painting
  /// context that can record the results of the painting operation in addition
  /// to performing the regular paint of the child.
  ///
  /// See also:
  ///
  ///  * [repaintCompositedChild], for repainting a composited child without
  ///    instrumentation.
  static void debugInstrumentRepaintCompositedChild(
    RenderObject child, {
    bool debugAlsoPaintedParent = false,
    required PaintingContext customContext,
  }) {
    assert(() {
      _repaintCompositedChild(
        child,
        debugAlsoPaintedParent: debugAlsoPaintedParent,
        childContext: customContext,
      );
      return true;
    }());
  }

  /// Paint a child [RenderObject].
  ///
  /// If the child has its own composited layer, the child will be composited
  /// into the layer subtree associated with this painting context. Otherwise,
  /// the child will be painted into the current PictureLayer for this context.
  void paintChild(RenderObject child, Offset offset) {
    assert(() {
      debugOnProfilePaint?.call(child);
      return true;
    }());

    if (child.isRepaintBoundary) {
      stopRecordingIfNeeded();
      _compositeChild(child, offset);
      // If a render object was a repaint boundary but no longer is one, this
      // is where the framework managed layer is automatically disposed.
    } else if (child._wasRepaintBoundary) {
      assert(child._layerHandle.layer is OffsetLayer);
      child._layerHandle.layer = null;
      child._paintWithContext(this, offset);
    } else {
      child._paintWithContext(this, offset);
    }
  }

  void _compositeChild(RenderObject child, Offset offset) {
    assert(!_isRecording);
    assert(child.isRepaintBoundary);
    assert(_canvas == null || _canvas!.getSaveCount() == 1);

    // Create a layer for our child, and paint the child into it.
    if (child._needsPaint || !child._wasRepaintBoundary) {
      repaintCompositedChild(child, debugAlsoPaintedParent: true);
    } else {
      if (child._needsCompositedLayerUpdate) {
        updateLayerProperties(child);
      }
      assert(() {
        // register the call for RepaintBoundary metrics
        child.debugRegisterRepaintBoundaryPaint();
        child._layerHandle.layer!.debugCreator = child.debugCreator ?? child;
        return true;
      }());
    }
    assert(child._layerHandle.layer is OffsetLayer);
    final childOffsetLayer = child._layerHandle.layer! as OffsetLayer;
    childOffsetLayer.offset = offset;
    appendLayer(childOffsetLayer);
  }

  /// Adds a layer to the recording requiring that the recording is already
  /// stopped.
  ///
  /// Do not call this function directly: call [addLayer] or [pushLayer]
  /// instead. This function is called internally when all layers not
  /// generated from the [canvas] are added.
  ///
  /// Subclasses that need to customize how layers are added should override
  /// this method.
  @protected
  void appendLayer(Layer layer) {
    assert(!_isRecording);
    layer.remove();
    _containerLayer.append(layer);
  }

  bool get _isRecording {
    final hasCanvas = _canvas != null;
    assert(() {
      if (hasCanvas) {
        assert(_currentLayer != null);
        assert(_recorder != null);
        assert(_canvas != null);
      } else {
        assert(_currentLayer == null);
        assert(_recorder == null);
        assert(_canvas == null);
      }
      return true;
    }());
    return hasCanvas;
  }

  // Recording state
  PictureLayer? _currentLayer;
  ui.PictureRecorder? _recorder;
  Canvas? _canvas;

  /// The recorder that is being used by this [PaintingContext]
  /// to record interactions with the [Canvas].
  ///
  /// It's fragile to hold a reference to the recorder
  /// returned by this getter as it can change at any time.
  ui.PictureRecorder get recorder {
    if (_recorder == null) {
      _startRecording();
    }
    assert(_currentLayer != null);
    return _recorder!;
  }

  /// The canvas on which to paint.
  ///
  /// The current canvas can change whenever you paint a child using this
  /// context, which means it's fragile to hold a reference to the canvas
  /// returned by this getter.
  @override
  Canvas get canvas {
    if (_canvas == null) {
      _startRecording();
    }
    assert(_currentLayer != null);
    return _canvas!;
  }

  void _startRecording() {
    assert(!_isRecording);
    _currentLayer = PictureLayer(estimatedBounds);
    _recorder = RendererBinding.instance.createPictureRecorder();
    _canvas = RendererBinding.instance.createCanvas(_recorder!);
    _containerLayer.append(_currentLayer!);
  }

  /// Adds a [CompositionCallback] for the current [ContainerLayer] used by this
  /// context.
  ///
  /// Composition callbacks are called whenever the layer tree containing the
  /// current layer of this painting context gets composited, or when it gets
  /// detached and will not be rendered again. This happens regardless of
  /// whether the layer is added via retained rendering or not.
  ///
  /// {@macro flutter.rendering.Layer.compositionCallbacks}
  ///
  /// See also:
  ///   *  [Layer.addCompositionCallback].
  VoidCallback addCompositionCallback(CompositionCallback callback) {
    return _containerLayer.addCompositionCallback(callback);
  }

  /// Stop recording to a canvas if recording has started.
  ///
  /// Do not call this function directly: functions in this class will call
  /// this method as needed. This function is called internally to ensure that
  /// recording is stopped before adding layers or finalizing the results of a
  /// paint.
  ///
  /// Subclasses that need to customize how recording to a canvas is performed
  /// should override this method to save the results of the custom canvas
  /// recordings.
  @protected
  @mustCallSuper
  void stopRecordingIfNeeded() {
    if (!_isRecording) {
      return;
    }
    assert(() {
      if (debugRepaintRainbowEnabled) {
        final paint = Paint()
          ..style = PaintingStyle.stroke
          ..strokeWidth = 6.0
          ..color = debugCurrentRepaintColor.toColor();
        canvas.drawRect(estimatedBounds.deflate(3.0), paint);
      }
      if (debugPaintLayerBordersEnabled) {
        final paint = Paint()
          ..style = PaintingStyle.stroke
          ..strokeWidth = 1.0
          ..color = const Color(0xFFFF9800);
        canvas.drawRect(estimatedBounds, paint);
      }
      return true;
    }());
    _currentLayer!.picture = _recorder!.endRecording();
    _currentLayer = null;
    _recorder = null;
    _canvas = null;
  }

  /// Hints that the painting in the current layer is complex and would benefit
  /// from caching.
  ///
  /// If this hint is not set, the compositor will apply its own heuristics to
  /// decide whether the current layer is complex enough to benefit from
  /// caching.
  ///
  /// Calling this ensures a [Canvas] is available. Only draw calls on the
  /// current canvas will be hinted; the hint is not propagated to new canvases
  /// created after a new layer is added to the painting context (e.g. with
  /// [addLayer] or [pushLayer]).
  void setIsComplexHint() {
    if (_currentLayer == null) {
      _startRecording();
    }
    _currentLayer!.isComplexHint = true;
  }

  /// Hints that the painting in the current layer is likely to change next frame.
  ///
  /// This hint tells the compositor not to cache the current layer because the
  /// cache will not be used in the future. If this hint is not set, the
  /// compositor will apply its own heuristics to decide whether the current
  /// layer is likely to be reused in the future.
  ///
  /// Calling this ensures a [Canvas] is available. Only draw calls on the
  /// current canvas will be hinted; the hint is not propagated to new canvases
  /// created after a new layer is added to the painting context (e.g. with
  /// [addLayer] or [pushLayer]).
  void setWillChangeHint() {
    if (_currentLayer == null) {
      _startRecording();
    }
    _currentLayer!.willChangeHint = true;
  }

  /// Adds a composited leaf layer to the recording.
  ///
  /// After calling this function, the [canvas] property will change to refer to
  /// a new [Canvas] that draws on top of the given layer.
  ///
  /// A [RenderObject] that uses this function is very likely to require its
  /// [RenderObject.alwaysNeedsCompositing] property to return true. That informs
  /// ancestor render objects that this render object will include a composited
  /// layer, which, for example, causes them to use composited clips.
  ///
  /// See also:
  ///
  ///  * [pushLayer], for adding a layer and painting further contents within
  ///    it.
  void addLayer(Layer layer) {
    stopRecordingIfNeeded();
    appendLayer(layer);
  }

  /// Appends the given layer to the recording, and calls the `painter` callback
  /// with that layer, providing the `childPaintBounds` as the estimated paint
  /// bounds of the child. The `childPaintBounds` can be used for debugging but
  /// have no effect on painting.
  ///
  /// The given layer must be an unattached orphan. (Providing a newly created
  /// object, rather than reusing an existing layer, satisfies that
  /// requirement.)
  ///
  /// {@template flutter.rendering.PaintingContext.pushLayer.offset}
  /// The `offset` is the offset to pass to the `painter`. In particular, it is
  /// not an offset applied to the layer itself. Layers conceptually by default
  /// have no position or size, though they can transform their contents. For
  /// example, an [OffsetLayer] applies an offset to its children.
  /// {@endtemplate}
  ///
  /// If the `childPaintBounds` are not specified then the current layer's paint
  /// bounds are used. This is appropriate if the child layer does not apply any
  /// transformation or clipping to its contents. The `childPaintBounds`, if
  /// specified, must be in the coordinate system of the new layer (i.e. as seen
  /// by its children after it applies whatever transform to its contents), and
  /// should not go outside the current layer's paint bounds.
  ///
  /// See also:
  ///
  ///  * [addLayer], for pushing a layer without painting further contents
  ///    within it.
  void pushLayer(
    ContainerLayer childLayer,
    PaintingContextCallback painter,
    Offset offset, {
    Rect? childPaintBounds,
  }) {
    // If a layer is being reused, it may already contain children. We remove
    // them so that `painter` can add children that are relevant for this frame.
    if (childLayer.hasChildren) {
      childLayer.removeAllChildren();
    }
    stopRecordingIfNeeded();
    appendLayer(childLayer);
    final PaintingContext childContext = createChildContext(
      childLayer,
      childPaintBounds ?? estimatedBounds,
    );

    painter(childContext, offset);
    childContext.stopRecordingIfNeeded();
  }

  /// Creates a painting context configured to paint into [childLayer].
  ///
  /// The `bounds` are estimated paint bounds for debugging purposes.
  @protected
  PaintingContext createChildContext(ContainerLayer childLayer, Rect bounds) {
    return PaintingContext(childLayer, bounds);
  }

  /// Clip further painting using a rectangle.
  ///
  /// {@template flutter.rendering.PaintingContext.pushClipRect.needsCompositing}
  /// The `needsCompositing` argument specifies whether the child needs
  /// compositing. Typically this matches the value of
  /// [RenderObject.needsCompositing] for the caller. If false, this method
  /// returns null, indicating that a layer is no longer necessary. If a render
  /// object calling this method stores the `oldLayer` in its
  /// [RenderObject.layer] field, it should set that field to null.
  ///
  /// When `needsCompositing` is false, this method will use a more efficient
  /// way to apply the layer effect than actually creating a layer.
  /// {@endtemplate}
  ///
  /// {@template flutter.rendering.PaintingContext.pushClipRect.offset}
  /// The `offset` argument is the offset from the origin of the canvas'
  /// coordinate system to the origin of the caller's coordinate system.
  /// {@endtemplate}
  ///
  /// The `clipRect` is the rectangle (in the caller's coordinate system) to use
  /// to clip the painting done by [painter]. It should not include the
  /// `offset`.
  ///
  /// The `painter` callback will be called while the `clipRect` is applied. It
  /// is called synchronously during the call to [pushClipRect].
  ///
  /// The `clipBehavior` argument controls how the rectangle is clipped.
  ///
  /// {@template flutter.rendering.PaintingContext.pushClipRect.oldLayer}
  /// For the `oldLayer` argument, specify the layer created in the previous
  /// frame. This gives the engine more information for performance
  /// optimizations. Typically this is the value of [RenderObject.layer] that a
  /// render object creates once, then reuses for all subsequent frames until a
  /// layer is no longer needed (e.g. the render object no longer needs
  /// compositing) or until the render object changes the type of the layer
  /// (e.g. from opacity layer to a clip rect layer).
  /// {@endtemplate}
  ClipRectLayer? pushClipRect(
    bool needsCompositing,
    Offset offset,
    Rect clipRect,
    PaintingContextCallback painter, {
    Clip clipBehavior = Clip.hardEdge,
    ClipRectLayer? oldLayer,
  }) {
    if (clipBehavior == Clip.none) {
      painter(this, offset);
      return null;
    }
    final Rect offsetClipRect = clipRect.shift(offset);
    if (needsCompositing) {
      final ClipRectLayer layer = oldLayer ?? ClipRectLayer();
      layer
        ..clipRect = offsetClipRect
        ..clipBehavior = clipBehavior;
      pushLayer(layer, painter, offset, childPaintBounds: offsetClipRect);
      return layer;
    } else {
      clipRectAndPaint(offsetClipRect, clipBehavior, offsetClipRect, () => painter(this, offset));
      return null;
    }
  }

  /// Clip further painting using a rounded rectangle.
  ///
  /// {@macro flutter.rendering.PaintingContext.pushClipRect.needsCompositing}
  ///
  /// {@macro flutter.rendering.PaintingContext.pushClipRect.offset}
  ///
  /// The `bounds` argument is used to specify the region of the canvas (in the
  /// caller's coordinate system) into which `painter` will paint.
  ///
  /// The `clipRRect` argument specifies the rounded-rectangle (in the caller's
  /// coordinate system) to use to clip the painting done by `painter`. It
  /// should not include the `offset`.
  ///
  /// The `painter` callback will be called while the `clipRRect` is applied. It
  /// is called synchronously during the call to [pushClipRRect].
  ///
  /// The `clipBehavior` argument controls how the rounded rectangle is clipped.
  ///
  /// {@macro flutter.rendering.PaintingContext.pushClipRect.oldLayer}
  ClipRRectLayer? pushClipRRect(
    bool needsCompositing,
    Offset offset,
    Rect bounds,
    RRect clipRRect,
    PaintingContextCallback painter, {
    Clip clipBehavior = Clip.antiAlias,
    ClipRRectLayer? oldLayer,
  }) {
    if (clipBehavior == Clip.none) {
      painter(this, offset);
      return null;
    }
    final Rect offsetBounds = bounds.shift(offset);
    final RRect offsetClipRRect = clipRRect.shift(offset);
    if (needsCompositing) {
      final ClipRRectLayer layer = oldLayer ?? ClipRRectLayer();
      layer
        ..clipRRect = offsetClipRRect
        ..clipBehavior = clipBehavior;
      pushLayer(layer, painter, offset, childPaintBounds: offsetBounds);
      return layer;
    } else {
      clipRRectAndPaint(offsetClipRRect, clipBehavior, offsetBounds, () => painter(this, offset));
      return null;
    }
  }

  /// Clip further painting using a rounded superellipse.
  ///
  /// {@macro flutter.rendering.PaintingContext.pushClipRect.needsCompositing}
  ///
  /// {@macro flutter.rendering.PaintingContext.pushClipRect.offset}
  ///
  /// The `bounds` argument is used to specify the region of the canvas (in the
  /// caller's coordinate system) into which `painter` will paint.
  ///
  /// The `clipRSuperellipse` argument specifies the rounded-superellipse (in the caller's
  /// coordinate system) to use to clip the painting done by `painter`. It
  /// should not include the `offset`.
  ///
  /// The `painter` callback will be called while the `clipRSuperellipse` is applied. It
  /// is called synchronously during the call to [pushClipRSuperellipse].
  ///
  /// The `clipBehavior` argument controls how the rounded rectangle is clipped.
  ///
  /// Hit tests are performed based on the bounding box of the [RSuperellipse].
  ///
  /// {@macro flutter.rendering.PaintingContext.pushClipRect.oldLayer}
  ClipRSuperellipseLayer? pushClipRSuperellipse(
    bool needsCompositing,
    Offset offset,
    Rect bounds,
    RSuperellipse clipRSuperellipse,
    PaintingContextCallback painter, {
    Clip clipBehavior = Clip.antiAlias,
    ClipRSuperellipseLayer? oldLayer,
  }) {
    if (clipBehavior == Clip.none) {
      painter(this, offset);
      return null;
    }
    final Rect offsetBounds = bounds.shift(offset);
    final RSuperellipse offsetShape = clipRSuperellipse.shift(offset);
    if (needsCompositing) {
      final ClipRSuperellipseLayer layer = oldLayer ?? ClipRSuperellipseLayer();
      layer
        ..clipRSuperellipse = offsetShape
        ..clipBehavior = clipBehavior;
      pushLayer(layer, painter, offset, childPaintBounds: offsetBounds);
      return layer;
    } else {
      clipRSuperellipseAndPaint(
        offsetShape,
        clipBehavior,
        offsetBounds,
        () => painter(this, offset),
      );
      return null;
    }
  }

  /// Clip further painting using a path.
  ///
  /// {@macro flutter.rendering.PaintingContext.pushClipRect.needsCompositing}
  ///
  /// {@macro flutter.rendering.PaintingContext.pushClipRect.offset}
  ///
  /// The `bounds` argument is used to specify the region of the canvas (in the
  /// caller's coordinate system) into which `painter` will paint.
  ///
  /// The `clipPath` argument specifies the [Path] (in the caller's coordinate
  /// system) to use to clip the painting done by `painter`. It should not
  /// include the `offset`.
  ///
  /// The `painter` callback will be called while the `clipPath` is applied. It
  /// is called synchronously during the call to [pushClipPath].
  ///
  /// The `clipBehavior` argument controls how the path is clipped.
  ///
  /// {@macro flutter.rendering.PaintingContext.pushClipRect.oldLayer}
  ClipPathLayer? pushClipPath(
    bool needsCompositing,
    Offset offset,
    Rect bounds,
    Path clipPath,
    PaintingContextCallback painter, {
    Clip clipBehavior = Clip.antiAlias,
    ClipPathLayer? oldLayer,
  }) {
    if (clipBehavior == Clip.none) {
      painter(this, offset);
      return null;
    }
    final Rect offsetBounds = bounds.shift(offset);
    final Path offsetClipPath = clipPath.shift(offset);
    if (needsCompositing) {
      final ClipPathLayer layer = oldLayer ?? ClipPathLayer();
      layer
        ..clipPath = offsetClipPath
        ..clipBehavior = clipBehavior;
      pushLayer(layer, painter, offset, childPaintBounds: offsetBounds);
      return layer;
    } else {
      clipPathAndPaint(offsetClipPath, clipBehavior, offsetBounds, () => painter(this, offset));
      return null;
    }
  }

  /// Blend further painting with a color filter.
  ///
  /// {@macro flutter.rendering.PaintingContext.pushLayer.offset}
  ///
  /// The `colorFilter` argument is the [ColorFilter] value to use when blending
  /// the painting done by `painter`.
  ///
  /// The `painter` callback will be called while the `colorFilter` is applied.
  /// It is called synchronously during the call to [pushColorFilter].
  ///
  /// {@macro flutter.rendering.PaintingContext.pushClipRect.oldLayer}
  ///
  /// A [RenderObject] that uses this function is very likely to require its
  /// [RenderObject.alwaysNeedsCompositing] property to return true. That informs
  /// ancestor render objects that this render object will include a composited
  /// layer, which, for example, causes them to use composited clips.
  ColorFilterLayer pushColorFilter(
    Offset offset,
    ColorFilter colorFilter,
    PaintingContextCallback painter, {
    ColorFilterLayer? oldLayer,
  }) {
    final ColorFilterLayer layer = oldLayer ?? ColorFilterLayer();
    layer.colorFilter = colorFilter;
    pushLayer(layer, painter, offset);
    return layer;
  }

  /// Transform further painting using a matrix.
  ///
  /// {@macro flutter.rendering.PaintingContext.pushClipRect.needsCompositing}
  ///
  /// The `offset` argument is the offset to pass to `painter` and the offset to
  /// the origin used by `transform`.
  ///
  /// The `transform` argument is the [Matrix4] with which to transform the
  /// coordinate system while calling `painter`. It should not include `offset`.
  /// It is applied effectively after applying `offset`.
  ///
  /// The `painter` callback will be called while the `transform` is applied. It
  /// is called synchronously during the call to [pushTransform].
  ///
  /// {@macro flutter.rendering.PaintingContext.pushClipRect.oldLayer}
  TransformLayer? pushTransform(
    bool needsCompositing,
    Offset offset,
    Matrix4 transform,
    PaintingContextCallback painter, {
    TransformLayer? oldLayer,
  }) {
    final effectiveTransform = Matrix4.translationValues(offset.dx, offset.dy, 0.0)
      ..multiply(transform)
      ..translateByDouble(-offset.dx, -offset.dy, 0, 1);
    if (needsCompositing) {
      final TransformLayer layer = oldLayer ?? TransformLayer();
      layer.transform = effectiveTransform;
      pushLayer(
        layer,
        painter,
        offset,
        childPaintBounds: MatrixUtils.inverseTransformRect(effectiveTransform, estimatedBounds),
      );
      return layer;
    } else {
      canvas
        ..save()
        ..transform(effectiveTransform.storage);
      painter(this, offset);
      canvas.restore();
      return null;
    }
  }

  /// Blend further painting with an alpha value.
  ///
  /// The `offset` argument indicates an offset to apply to all the children
  /// (the rendering created by `painter`).
  ///
  /// The `alpha` argument is the alpha value to use when blending the painting
  /// done by `painter`. An alpha value of 0 means the painting is fully
  /// transparent and an alpha value of 255 means the painting is fully opaque.
  ///
  /// The `painter` callback will be called while the `alpha` is applied. It
  /// is called synchronously during the call to [pushOpacity].
  ///
  /// {@macro flutter.rendering.PaintingContext.pushClipRect.oldLayer}
  ///
  /// A [RenderObject] that uses this function is very likely to require its
  /// [RenderObject.alwaysNeedsCompositing] property to return true. That informs
  /// ancestor render objects that this render object will include a composited
  /// layer, which, for example, causes them to use composited clips.
  OpacityLayer pushOpacity(
    Offset offset,
    int alpha,
    PaintingContextCallback painter, {
    OpacityLayer? oldLayer,
  }) {
    final OpacityLayer layer = oldLayer ?? OpacityLayer();
    layer
      ..alpha = alpha
      ..offset = offset;
    pushLayer(layer, painter, Offset.zero);
    return layer;
  }

  @override
  String toString() =>
      '${objectRuntimeType(this, 'PaintingContext')}#$hashCode(layer: $_containerLayer, canvas bounds: $estimatedBounds)';
}

/// An abstract set of layout constraints.
///
/// Concrete layout models (such as box) will create concrete subclasses to
/// communicate layout constraints between parents and children.
///
/// ## Writing a Constraints subclass
///
/// When creating a new [RenderObject] subclass with a new layout protocol, one
/// will usually need to create a new [Constraints] subclass to express the
/// input to the layout algorithms.
///
/// A [Constraints] subclass should be immutable (all fields final). There are
/// several members to implement, in addition to whatever fields, constructors,
/// and helper methods one may find useful for a particular layout protocol:
///
/// * The [isTight] getter, which should return true if the object represents a
///   case where the [RenderObject] class has no choice for how to lay itself
///   out. For example, [BoxConstraints] returns true for [isTight] when both
///   the minimum and maximum widths and the minimum and maximum heights are
///   equal.
///
/// * The [isNormalized] getter, which should return true if the object
///   represents its data in its canonical form. Sometimes, it is possible for
///   fields to be redundant with each other, such that several different
///   representations have the same implications. For example, a
///   [BoxConstraints] instance with its minimum width greater than its maximum
///   width is equivalent to one where the maximum width is set to that minimum
///   width (`2<w<1` is equivalent to `2<w<2`, since minimum constraints have
///   priority). This getter is used by the default implementation of
///   [debugAssertIsValid].
///
/// * The [debugAssertIsValid] method, which should assert if there's anything
///   wrong with the constraints object. (We use this approach rather than
///   asserting in constructors so that our constructors can be `const` and so
///   that it is possible to create invalid constraints temporarily while
///   building valid ones.) See the implementation of
///   [BoxConstraints.debugAssertIsValid] for an example of the detailed checks
///   that can be made.
///
/// * The [==] operator and the [hashCode] getter, so that constraints can be
///   compared for equality. If a render object is given constraints that are
///   equal, then the rendering library will avoid laying the object out again
///   if it is not dirty.
///
/// * The [toString] method, which should describe the constraints so that they
///   appear in a usefully readable form in the output of [debugDumpRenderTree].
@immutable
abstract class Constraints {
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
  const Constraints();

  /// Whether there is exactly one size possible given these constraints.
  bool get isTight;

  /// Whether the constraint is expressed in a consistent manner.
  bool get isNormalized;

  /// Asserts that the constraints are valid.
  ///
  /// This might involve checks more detailed than [isNormalized].
  ///
  /// For example, the [BoxConstraints] subclass verifies that the constraints
  /// are not [double.nan].
  ///
  /// If the `isAppliedConstraint` argument is true, then even stricter rules
  /// are enforced. This argument is set to true when checking constraints that
  /// are about to be applied to a [RenderObject] during layout, as opposed to
  /// constraints that may be further affected by other constraints. For
  /// example, the asserts for verifying the validity of
  /// [RenderConstrainedBox.additionalConstraints] do not set this argument, but
  /// the asserts for verifying the argument passed to the [RenderObject.layout]
  /// method do.
  ///
  /// The `informationCollector` argument takes an optional callback which is
  /// called when an exception is to be thrown. The collected information is
  /// then included in the message after the error line.
  ///
  /// Returns the same as [isNormalized] if asserts are disabled.
  bool debugAssertIsValid({
    bool isAppliedConstraint = false,
    InformationCollector? informationCollector,
  }) {
    assert(isNormalized);
    return isNormalized;
  }
}

/// Signature for a function that is called for each [RenderObject].
///
/// Used by [RenderObject.visitChildren] and [RenderObject.visitChildrenForSemantics].
typedef RenderObjectVisitor = void Function(RenderObject child);

/// Signature for a function that is called during layout.
///
/// Used by [RenderObject.invokeLayoutCallback].
typedef LayoutCallback<T extends Constraints> = void Function(T constraints);

class _LocalSemanticsHandle implements SemanticsHandle {
  _LocalSemanticsHandle._(PipelineOwner owner, this.listener) : _owner = owner {
    assert(debugMaybeDispatchCreated('rendering', '_LocalSemanticsHandle', this));
    if (listener != null) {
      _owner.semanticsOwner!.addListener(listener!);
    }
  }

  final PipelineOwner _owner;

  /// The callback that will be notified when the semantics tree updates.
  final VoidCallback? listener;

  @override
  void dispose() {
    assert(debugMaybeDispatchDisposed(this));
    if (listener != null) {
      _owner.semanticsOwner!.removeListener(listener!);
    }
    _owner._didDisposeSemanticsHandle();
  }
}

/// The pipeline owner manages the rendering pipeline.
///
/// The pipeline owner provides an interface for driving the rendering pipeline
/// and stores the state about which render objects have requested to be visited
/// in each stage of the pipeline. To flush the pipeline, call the following
/// functions in order:
///
/// 1. [flushLayout] updates any render objects that need to compute their
///    layout. During this phase, the size and position of each render
///    object is calculated. Render objects might dirty their painting or
///    compositing state during this phase.
/// 2. [flushCompositingBits] updates any render objects that have dirty
///    compositing bits. During this phase, each render object learns whether
///    any of its children require compositing. This information is used during
///    the painting phase when selecting how to implement visual effects such as
///    clipping. If a render object has a composited child, it needs to use a
///    [Layer] to create the clip in order for the clip to apply to the
///    composited child (which will be painted into its own [Layer]).
/// 3. [flushPaint] visits any render objects that need to paint. During this
///    phase, render objects get a chance to record painting commands into
///    [PictureLayer]s and construct other composited [Layer]s.
/// 4. Finally, if semantics are enabled, [flushSemantics] will compile the
///    semantics for the render objects. This semantic information is used by
///    assistive technology to improve the accessibility of the render tree.
///
/// The [RendererBinding] holds the pipeline owner for the render objects that
/// are visible on screen. You can create other pipeline owners to manage
/// off-screen objects, which can flush their pipelines independently of the
/// on-screen render objects.
///
/// [PipelineOwner]s can be organized in a tree to manage multiple render trees,
/// where each [PipelineOwner] is responsible for one of the render trees. To
/// build or modify the tree, call [adoptChild] or [dropChild]. During each of
/// the different flush phases described above, a [PipelineOwner] will first
/// perform the phase on the nodes it manages in its own render tree before
/// calling the same flush method on its children. No assumption must be made
/// about the order in which child [PipelineOwner]s are flushed.
///
/// A [PipelineOwner] may also be [attach]ed to a [PipelineManifold], which
/// gives it access to platform functionality usually exposed by the bindings
/// without tying it to a specific binding implementation. All [PipelineOwner]s
/// in a given tree must be attached to the same [PipelineManifold]. This
/// happens automatically during [adoptChild].
base class PipelineOwner with DiagnosticableTreeMixin {
  /// Creates a pipeline owner.
  ///
  /// Typically created by the binding (e.g., [RendererBinding]), but can be
  /// created separately from the binding to drive off-screen render objects
  /// through the rendering pipeline.
  PipelineOwner({
    this.onNeedVisualUpdate,
    this.onSemanticsOwnerCreated,
    this.onSemanticsUpdate,
    this.onSemanticsOwnerDisposed,
  }) {
    assert(debugMaybeDispatchCreated('rendering', 'PipelineOwner', this));
  }

  /// Called when a render object associated with this pipeline owner wishes to
  /// update its visual appearance.
  ///
  /// Typical implementations of this function will schedule a task to flush the
  /// various stages of the pipeline. This function might be called multiple
  /// times in quick succession. Implementations should take care to discard
  /// duplicate calls quickly.
  ///
  /// When the [PipelineOwner] is attached to a [PipelineManifold] and
  /// [onNeedVisualUpdate] is provided, the [onNeedVisualUpdate] callback is
  /// invoked instead of calling [PipelineManifold.requestVisualUpdate].
  final VoidCallback? onNeedVisualUpdate;

  /// Called whenever this pipeline owner creates a semantics object.
  ///
  /// Typical implementations will schedule the creation of the initial
  /// semantics tree.
  final VoidCallback? onSemanticsOwnerCreated;

  /// Called whenever this pipeline owner's semantics owner emits a [SemanticsUpdate].
  ///
  /// Typical implementations will delegate the [SemanticsUpdate] to a [FlutterView]
  /// that can handle the [SemanticsUpdate].
  final SemanticsUpdateCallback? onSemanticsUpdate;

  /// Called whenever this pipeline owner disposes its semantics owner.
  ///
  /// Typical implementations will tear down the semantics tree.
  final VoidCallback? onSemanticsOwnerDisposed;

  /// Calls [onNeedVisualUpdate] if [onNeedVisualUpdate] is not null.
  ///
  /// Used to notify the pipeline owner that an associated render object wishes
  /// to update its visual appearance.
  void requestVisualUpdate() {
    if (onNeedVisualUpdate != null) {
      onNeedVisualUpdate!();
    } else {
      _manifold?.requestVisualUpdate();
    }
  }

  /// The unique object managed by this pipeline that has no parent.
  RenderObject? get rootNode => _rootNode;
  RenderObject? _rootNode;
  set rootNode(RenderObject? value) {
    if (_rootNode == value) {
      return;
    }
    _rootNode?.detach();
    _rootNode = value;
    _rootNode?.attach(this);
  }

  // Whether the current [flushLayout] call should pause to incorporate the
  // [RenderObject]s in `_nodesNeedingLayout` into the current dirty list,
  // before continuing to process dirty relayout boundaries.
  //
  // This flag is set to true when a [RenderObject.invokeLayoutCallback]
  // returns, to avoid laying out dirty relayout boundaries in an incorrect
  // order and causing them to be laid out more than once per frame. See
  // layout_builder_mutations_test.dart for an example.
  //
  // The new dirty nodes are not immediately merged after a
  // [RenderObject.invokeLayoutCallback] call because we may encounter multiple
  // such calls while processing a single relayout boundary in [flushLayout].
  // Batching new dirty nodes can reduce the number of merges [flushLayout]
  // has to perform.
  bool _shouldMergeDirtyNodes = false;
  List<RenderObject> _nodesNeedingLayout = <RenderObject>[];

  /// The [RenderObject]s representing relayout boundaries which need to be laid out
  /// in the next [flushLayout] pass.
  ///
  /// Relayout boundaries are added when they are marked for layout.
  /// Subclasses of [PipelineOwner] may use them to invalidate caches or
  /// otherwise make performance optimizations. Since nodes may be marked for
  /// layout at any time, they are best checked during [flushLayout].
  ///
  /// Relayout boundaries owned by child [PipelineOwner]s are not included here.
  ///
  /// Boundaries appear in an arbitrary order, and may appear multiple times.
  @protected
  @nonVirtual
  Iterable<RenderObject> get nodesNeedingLayout => _nodesNeedingLayout;

  /// Whether this pipeline is currently in the layout phase.
  ///
  /// Specifically, whether [flushLayout] is currently running.
  ///
  /// Only valid when asserts are enabled; in release builds, this
  /// always returns false.
  bool get debugDoingLayout => _debugDoingLayout;
  bool _debugDoingLayout = false;
  bool _debugDoingChildLayout = false;

  /// Update the layout information for all dirty render objects.
  ///
  /// This function is one of the core stages of the rendering pipeline. Layout
  /// information is cleaned prior to painting so that render objects will
  /// appear on screen in their up-to-date locations.
  ///
  /// See [RendererBinding] for an example of how this function is used.
  void flushLayout() {
    if (!kReleaseMode) {
      Map<String, String>? debugTimelineArguments;
      assert(() {
        if (debugEnhanceLayoutTimelineArguments) {
          debugTimelineArguments = <String, String>{
            'dirty count': '${_nodesNeedingLayout.length}',
            'dirty list': '$_nodesNeedingLayout',
          };
        }
        return true;
      }());
      FlutterTimeline.startSync(
        'LAYOUT$_debugRootSuffixForTimelineEventNames',
        arguments: debugTimelineArguments,
      );
    }
    assert(() {
      _debugDoingLayout = true;
      return true;
    }());
    try {
      while (_nodesNeedingLayout.isNotEmpty) {
        assert(!_shouldMergeDirtyNodes);
        final List<RenderObject> dirtyNodes = _nodesNeedingLayout;
        _nodesNeedingLayout = <RenderObject>[];
        dirtyNodes.sort((RenderObject a, RenderObject b) => a.depth - b.depth);
        for (var i = 0; i < dirtyNodes.length; i++) {
          if (_shouldMergeDirtyNodes) {
            _shouldMergeDirtyNodes = false;
            if (_nodesNeedingLayout.isNotEmpty) {
              _nodesNeedingLayout.addAll(dirtyNodes.getRange(i, dirtyNodes.length));
              break;
            }
          }
          final RenderObject node = dirtyNodes[i];
          if (node._needsLayout && node.owner == this) {
            node._layoutWithoutResize();
          }
        }
        // No need to merge dirty nodes generated from processing the last
        // relayout boundary back.
        _shouldMergeDirtyNodes = false;
      }

      assert(() {
        _debugDoingChildLayout = true;
        return true;
      }());
      for (final PipelineOwner child in _children) {
        child.flushLayout();
      }
      assert(
        _nodesNeedingLayout.isEmpty,
        'Child PipelineOwners must not dirty nodes in their parent.',
      );
    } finally {
      _shouldMergeDirtyNodes = false;
      assert(() {
        _debugDoingLayout = false;
        _debugDoingChildLayout = false;
        return true;
      }());
      if (!kReleaseMode) {
        FlutterTimeline.finishSync();
      }
    }
  }

  // This flag is used to allow the kinds of mutations performed by GlobalKey
  // reparenting while a LayoutBuilder is being rebuilt and in so doing tries to
  // move a node from another LayoutBuilder subtree that hasn't been updated
  // yet. To set this, call [_enableMutationsToDirtySubtrees], which is called
  // by [RenderObject.invokeLayoutCallback].
  bool _debugAllowMutationsToDirtySubtrees = false;

  // See [RenderObject.invokeLayoutCallback].
  void _enableMutationsToDirtySubtrees(VoidCallback callback) {
    assert(_debugDoingLayout);
    bool? oldState;
    assert(() {
      oldState = _debugAllowMutationsToDirtySubtrees;
      _debugAllowMutationsToDirtySubtrees = true;
      return true;
    }());
    try {
      callback();
    } finally {
      _shouldMergeDirtyNodes = true;
      assert(() {
        _debugAllowMutationsToDirtySubtrees = oldState!;
        return true;
      }());
    }
  }

  final List<RenderObject> _nodesNeedingCompositingBitsUpdate = <RenderObject>[];

  /// Updates the [RenderObject.needsCompositing] bits.
  ///
  /// Called as part of the rendering pipeline after [flushLayout] and before
  /// [flushPaint].
  void flushCompositingBits() {
    if (!kReleaseMode) {
      FlutterTimeline.startSync('UPDATING COMPOSITING BITS$_debugRootSuffixForTimelineEventNames');
    }
    _nodesNeedingCompositingBitsUpdate.sort((RenderObject a, RenderObject b) => a.depth - b.depth);
    for (final RenderObject node in _nodesNeedingCompositingBitsUpdate) {
      if (node._needsCompositingBitsUpdate && node.owner == this) {
        node._updateCompositingBits();
      }
    }
    _nodesNeedingCompositingBitsUpdate.clear();
    for (final PipelineOwner child in _children) {
      child.flushCompositingBits();
    }
    assert(
      _nodesNeedingCompositingBitsUpdate.isEmpty,
      'Child PipelineOwners must not dirty nodes in their parent.',
    );
    if (!kReleaseMode) {
      FlutterTimeline.finishSync();
    }
  }

  List<RenderObject> _nodesNeedingPaint = <RenderObject>[];

  /// The [RenderObject]s which need to be painted in the next [flushPaint] pass.
  ///
  /// [RenderObject]s marked with [RenderObject.isRepaintBoundary] are added
  /// when they are marked needing paint. Subclasses of [PipelineOwner] may use them
  /// to invalidate caches or otherwise make performance optimizations.
  /// Since nodes may be marked for layout at any time, they are best checked during
  /// [flushPaint].
  ///
  /// Marked children of child [PipelineOwner]s are not included here.
  @protected
  @nonVirtual
  Iterable<RenderObject> get nodesNeedingPaint => _nodesNeedingPaint;

  /// Whether this pipeline is currently in the paint phase.
  ///
  /// Specifically, whether [flushPaint] is currently running.
  ///
  /// Only valid when asserts are enabled. In release builds,
  /// this always returns false.
  bool get debugDoingPaint => _debugDoingPaint;
  bool _debugDoingPaint = false;

  /// Update the display lists for all render objects.
  ///
  /// This function is one of the core stages of the rendering pipeline.
  /// Painting occurs after layout and before the scene is recomposited so that
  /// scene is composited with up-to-date display lists for every render object.
  ///
  /// See [RendererBinding] for an example of how this function is used.
  void flushPaint() {
    if (!kReleaseMode) {
      Map<String, String>? debugTimelineArguments;
      assert(() {
        if (debugEnhancePaintTimelineArguments) {
          debugTimelineArguments = <String, String>{
            'dirty count': '${_nodesNeedingPaint.length}',
            'dirty list': '$_nodesNeedingPaint',
          };
        }
        return true;
      }());
      FlutterTimeline.startSync(
        'PAINT$_debugRootSuffixForTimelineEventNames',
        arguments: debugTimelineArguments,
      );
    }
    try {
      assert(() {
        _debugDoingPaint = true;
        return true;
      }());
      final List<RenderObject> dirtyNodes = _nodesNeedingPaint;
      _nodesNeedingPaint = <RenderObject>[];

      // Sort the dirty nodes in reverse order (deepest first).
      for (final node in dirtyNodes..sort((RenderObject a, RenderObject b) => b.depth - a.depth)) {
        assert(node._layerHandle.layer != null);
        if ((node._needsPaint || node._needsCompositedLayerUpdate) && node.owner == this) {
          if (node._layerHandle.layer!.attached) {
            assert(node.isRepaintBoundary);
            if (node._needsPaint) {
              PaintingContext.repaintCompositedChild(node);
            } else {
              PaintingContext.updateLayerProperties(node);
            }
          } else {
            node._skippedPaintingOnLayer();
          }
        }
      }
      for (final PipelineOwner child in _children) {
        child.flushPaint();
      }
      assert(
        _nodesNeedingPaint.isEmpty,
        'Child PipelineOwners must not dirty nodes in their parent.',
      );
    } finally {
      assert(() {
        _debugDoingPaint = false;
        return true;
      }());
      if (!kReleaseMode) {
        FlutterTimeline.finishSync();
      }
    }
  }

  /// The object that is managing semantics for this pipeline owner, if any.
  ///
  /// An owner is created by [ensureSemantics] or when the [PipelineManifold] to
  /// which this owner is connected has [PipelineManifold.semanticsEnabled] set
  /// to true. The owner is valid for as long as
  /// [PipelineManifold.semanticsEnabled] remains true or while there are
  /// outstanding [SemanticsHandle]s from calls to [ensureSemantics]. The
  /// [semanticsOwner] field will revert to null once both conditions are no
  /// longer met.
  ///
  /// When [semanticsOwner] is null, the [PipelineOwner] skips all steps
  /// relating to semantics.
  SemanticsOwner? get semanticsOwner => _semanticsOwner;
  SemanticsOwner? _semanticsOwner;

  /// Deprecated.
  ///
  /// Use [SemanticsBinding.debugOutstandingSemanticsHandles] instead. This
  /// API is broken because an outstanding semantics handle on a given pipeline
  /// owner doesn't mean that semantics are actually produced.
  @Deprecated(
    'Use SemanticsBinding.debugOutstandingSemanticsHandles instead. '
    'This API is broken (see ensureSemantics). '
    'This feature was deprecated after v3.22.0-23.0.pre.',
  )
  int get debugOutstandingSemanticsHandles => _outstandingSemanticsHandles;
  int _outstandingSemanticsHandles = 0;

  /// Deprecated.
  ///
  /// Call [SemanticsBinding.ensureSemantics] instead and optionally add a
  /// listener to [PipelineOwner.semanticsOwner]. This API is broken as calling
  /// it does not guarantee that semantics are produced.
  @Deprecated(
    'Call SemanticsBinding.ensureSemantics instead and optionally add a listener to PipelineOwner.semanticsOwner. '
    'This API is broken; it does not guarantee that semantics are actually produced. '
    'This feature was deprecated after v3.22.0-23.0.pre.',
  )
  SemanticsHandle ensureSemantics({VoidCallback? listener}) {
    _outstandingSemanticsHandles += 1;
    _updateSemanticsOwner();
    return _LocalSemanticsHandle._(this, listener);
  }

  void _updateSemanticsOwner() {
    if ((_manifold?.semanticsEnabled ?? false) || _outstandingSemanticsHandles > 0) {
      if (_semanticsOwner == null) {
        assert(
          onSemanticsUpdate != null,
          'Attempted to enable semantics without configuring an onSemanticsUpdate callback.',
        );
        _semanticsOwner = SemanticsOwner(onSemanticsUpdate: onSemanticsUpdate!);
        onSemanticsOwnerCreated?.call();
      }
    } else if (_semanticsOwner != null) {
      _semanticsOwner?.dispose();
      _semanticsOwner = null;
      onSemanticsOwnerDisposed?.call();
    }
  }

  void _didDisposeSemanticsHandle() {
    assert(_semanticsOwner != null);
    _outstandingSemanticsHandles -= 1;
    _updateSemanticsOwner();
  }

  bool _debugDoingSemantics = false;
  final Set<RenderObject> _nodesNeedingSemantics = <RenderObject>{};

  /// Update the semantics for render objects marked as needing a semantics
  /// update.
  ///
  /// Initially, only the root node, as scheduled by
  /// [RenderObject.scheduleInitialSemantics], needs a semantics update.
  ///
  /// This function is one of the core stages of the rendering pipeline. The
  /// semantics are compiled after painting and only after
  /// [RenderObject.scheduleInitialSemantics] has been called.
  ///
  /// See [RendererBinding] for an example of how this function is used.
  // See [_RenderObjectSemantics]'s documentation for detailed explanations on
  // what this method does.
  void flushSemantics() {
    if (_semanticsOwner == null) {
      return;
    }
    if (!kReleaseMode) {
      FlutterTimeline.startSync('SEMANTICS$_debugRootSuffixForTimelineEventNames');
    }
    assert(_semanticsOwner != null);
    assert(() {
      _debugDoingSemantics = true;
      return true;
    }());
    try {
      // This has to be top-to-down order since the geometries of a child and its
      // subtree depends on ancestors' transforms and clips. If it updates child
      // first, it may use dirty geometry in parent's semantics node to
      // calculate the geometries in the subtree.
      final List<RenderObject> nodesToProcess =
          _nodesNeedingSemantics
              .where((RenderObject object) => !object._needsLayout && object.owner == this)
              .toList()
            ..sort((RenderObject a, RenderObject b) => a.depth - b.depth);
      _nodesNeedingSemantics.clear();
      if (!kReleaseMode) {
        FlutterTimeline.startSync('Semantics.updateChildren');
      }
      for (final node in nodesToProcess) {
        if (node._semantics.parentDataDirty) {
          // This node is either blocked by a sibling
          // (via SemanticsConfiguration.isBlockingSemanticsOfPreviouslyPaintedNodes)
          // or is hidden by parent through visitChildrenForSemantics. Otherwise,
          // the parent node would have updated this node's parent data and it
          // would not be dirty.
          //
          // Updating the parent data now may create a gap of render object with
          // dirty parent data when this branch later rejoin the rendering tree.
          continue;
        }
        node._semantics.updateChildren();
      }
      if (!kReleaseMode) {
        FlutterTimeline.finishSync();
      }

      final RenderObject? rootNode = this.rootNode;
      assert(() {
        assert(nodesToProcess.isEmpty || rootNode != null);
        if (rootNode != null) {
          _RenderObjectSemantics.debugCheckForParentData(rootNode);
        }
        return true;
      }());

      if (!kReleaseMode) {
        FlutterTimeline.startSync('Semantics.ensureGeometry');
      }
      for (final node in nodesToProcess) {
        if (node._semantics.parentDataDirty) {
          // same as above.
          continue;
        }
        node._semantics.ensureGeometry();
      }
      if (!kReleaseMode) {
        FlutterTimeline.finishSync();
      }

      if (!kReleaseMode) {
        FlutterTimeline.startSync('Semantics.ensureSemanticsNode');
      }
      for (final RenderObject node in nodesToProcess.reversed) {
        if (node._semantics.parentDataDirty) {
          // same as above.
          continue;
        }
        node._semantics.ensureSemanticsNode();
      }
      if (!kReleaseMode) {
        FlutterTimeline.finishSync();
      }

      _semanticsOwner!.sendSemanticsUpdate();
      for (final PipelineOwner child in _children) {
        child.flushSemantics();
      }
      assert(
        _nodesNeedingSemantics.isEmpty,
        'Child PipelineOwners must not dirty nodes in their parent.',
      );
    } finally {
      assert(() {
        _debugDoingSemantics = false;
        return true;
      }());
      if (!kReleaseMode) {
        FlutterTimeline.finishSync();
      }
    }
  }

  @override
  List<DiagnosticsNode> debugDescribeChildren() {
    return <DiagnosticsNode>[
      for (final PipelineOwner child in _children) child.toDiagnosticsNode(),
    ];
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<RenderObject>('rootNode', rootNode, defaultValue: null));
  }

  // TREE MANAGEMENT

  final Set<PipelineOwner> _children = <PipelineOwner>{};
  PipelineManifold? _manifold;

  PipelineOwner? _debugParent;
  bool _debugSetParent(PipelineOwner child, PipelineOwner? parent) {
    child._debugParent = parent;
    return true;
  }

  String get _debugRootSuffixForTimelineEventNames => _debugParent == null ? ' (root)' : '';

  /// Mark this [PipelineOwner] as attached to the given [PipelineManifold].
  ///
  /// Typically, this is only called directly on the root [PipelineOwner].
  /// Children are automatically attached to their parent's [PipelineManifold]
  /// when [adoptChild] is called.
  void attach(PipelineManifold manifold) {
    assert(_manifold == null);
    _manifold = manifold;
    _manifold!.addListener(_updateSemanticsOwner);
    _updateSemanticsOwner();

    for (final PipelineOwner child in _children) {
      child.attach(manifold);
    }
  }

  /// Mark this [PipelineOwner] as detached.
  ///
  /// Typically, this is only called directly on the root [PipelineOwner].
  /// Children are automatically detached from their parent's [PipelineManifold]
  /// when [dropChild] is called.
  void detach() {
    assert(_manifold != null);
    _manifold!.removeListener(_updateSemanticsOwner);
    _manifold = null;
    // Not updating the semantics owner here to not disrupt any of its clients
    // in case we get re-attached. If necessary, semantics owner will be updated
    // in "attach", or disposed in "dispose", if not reattached.

    for (final PipelineOwner child in _children) {
      child.detach();
    }
  }

  // In theory, child list modifications are also disallowed between
  // _debugDoingChildrenLayout and _debugDoingPaint as well as between
  // _debugDoingPaint and _debugDoingSemantics. However, since the associated
  // flush methods are usually called back to back, this gets us close enough.
  bool get _debugAllowChildListModifications =>
      !_debugDoingChildLayout && !_debugDoingPaint && !_debugDoingSemantics;

  /// Adds `child` to this [PipelineOwner].
  ///
  /// During the phases of frame production (see [RendererBinding.drawFrame]),
  /// the parent [PipelineOwner] will complete a phase for the nodes it owns
  /// directly before invoking the flush method corresponding to the current
  /// phase on its child [PipelineOwner]s. For example, during layout, the
  /// parent [PipelineOwner] will first lay out its own nodes before calling
  /// [flushLayout] on its children. During paint, it will first paint its own
  /// nodes before calling [flushPaint] on its children. This order also applies
  /// for all the other phases.
  ///
  /// No assumptions must be made about the order in which child
  /// [PipelineOwner]s are flushed.
  ///
  /// No new children may be added after the [PipelineOwner] has started calling
  /// [flushLayout] on any of its children until the end of the current frame.
  ///
  /// To remove a child, call [dropChild].
  void adoptChild(PipelineOwner child) {
    assert(child._debugParent == null);
    assert(!_children.contains(child));
    assert(_debugAllowChildListModifications, 'Cannot modify child list after layout.');
    _children.add(child);
    if (!kReleaseMode) {
      _debugSetParent(child, this);
    }
    if (_manifold != null) {
      child.attach(_manifold!);
    }
  }

  /// Removes a child [PipelineOwner] previously added via [adoptChild].
  ///
  /// This node will cease to call the flush methods on the `child` during frame
  /// production.
  ///
  /// No children may be removed after the [PipelineOwner] has started calling
  /// [flushLayout] on any of its children until the end of the current frame.
  void dropChild(PipelineOwner child) {
    assert(child._debugParent == this);
    assert(_children.contains(child));
    assert(_debugAllowChildListModifications, 'Cannot modify child list after layout.');
    _children.remove(child);
    if (!kReleaseMode) {
      _debugSetParent(child, null);
    }
    if (_manifold != null) {
      child.detach();
    }
  }

  /// Calls `visitor` for each immediate child of this [PipelineOwner].
  ///
  /// See also:
  ///
  ///  * [adoptChild] to add a child.
  ///  * [dropChild] to remove a child.
  void visitChildren(PipelineOwnerVisitor visitor) {
    _children.forEach(visitor);
  }

  /// Release any resources held by this pipeline owner.
  ///
  /// Prior to calling this method the pipeline owner must be removed from the
  /// pipeline owner tree, i.e. it must have neither a parent nor any children
  /// (see [dropChild]). It also must be [detach]ed from any [PipelineManifold].
  ///
  /// The object is no longer usable after calling dispose.
  void dispose() {
    assert(_children.isEmpty);
    assert(rootNode == null);
    assert(_manifold == null);
    assert(_debugParent == null);
    assert(debugMaybeDispatchDisposed(this));
    _semanticsOwner?.dispose();
    _semanticsOwner = null;
    _nodesNeedingLayout.clear();
    _nodesNeedingCompositingBitsUpdate.clear();
    _nodesNeedingPaint.clear();
    _nodesNeedingSemantics.clear();
  }
}

/// Signature for the callback to [PipelineOwner.visitChildren].
///
/// The argument is the child being visited.
typedef PipelineOwnerVisitor = void Function(PipelineOwner child);

/// Manages a tree of [PipelineOwner]s.
///
/// All [PipelineOwner]s within a tree are attached to the same
/// [PipelineManifold], which gives them access to shared functionality such
/// as requesting a visual update (by calling [requestVisualUpdate]). As such,
/// the [PipelineManifold] gives the [PipelineOwner]s access to functionality
/// usually provided by the bindings without tying the [PipelineOwner]s to a
/// particular binding implementation.
///
/// The root of the [PipelineOwner] tree is attached to a [PipelineManifold] by
/// passing the manifold to [PipelineOwner.attach]. Children are attached to the
/// same [PipelineManifold] as their parent when they are adopted via
/// [PipelineOwner.adoptChild].
///
/// [PipelineOwner]s can register listeners with the [PipelineManifold] to be
/// informed when certain values provided by the [PipelineManifold] change.
abstract class PipelineManifold implements Listenable {
  /// Whether [PipelineOwner]s connected to this [PipelineManifold] should
  /// collect semantics information and produce a semantics tree.
  ///
  /// The [PipelineManifold] notifies its listeners (managed with [addListener]
  /// and [removeListener]) when this property changes its value.
  ///
  /// See also:
  ///
  ///  * [SemanticsBinding.semanticsEnabled], which [PipelineManifold]
  ///    implementations typically use to back this property.
  bool get semanticsEnabled;

  /// Called by a [PipelineOwner] connected to this [PipelineManifold] when a
  /// [RenderObject] associated with that pipeline owner wishes to update its
  /// visual appearance.
  ///
  /// Typical implementations of this function will schedule a task to flush the
  /// various stages of the pipeline. This function might be called multiple
  /// times in quick succession. Implementations should take care to discard
  /// duplicate calls quickly.
  ///
  /// A [PipelineOwner] connected to this [PipelineManifold] will call
  /// [PipelineOwner.onNeedVisualUpdate] instead of this method if it has been
  /// configured with a non-null [PipelineOwner.onNeedVisualUpdate] callback.
  ///
  /// See also:
  ///
  ///  * [SchedulerBinding.ensureVisualUpdate], which [PipelineManifold]
  ///    implementations typically call to implement this method.
  void requestVisualUpdate();
}

/// An object in the render tree.
///
/// The [RenderObject] class hierarchy is the core of the rendering
/// library's reason for being.
///
/// {@youtube 560 315 https://www.youtube.com/watch?v=zmbmrw07qBc}
///
/// [RenderObject]s have a [parent], and have a slot called [parentData] in
/// which the parent [RenderObject] can store child-specific data, for example,
/// the child position. The [RenderObject] class also implements the basic
/// layout and paint protocols.
///
/// The [RenderObject] class, however, does not define a child model (e.g.
/// whether a node has zero, one, or more children). It also doesn't define a
/// coordinate system (e.g. whether children are positioned in Cartesian
/// coordinates, in polar coordinates, etc) or a specific layout protocol (e.g.
/// whether the layout is width-in-height-out, or constraint-in-size-out, or
/// whether the parent sets the size and position of the child before or after
/// the child lays out, etc; or indeed whether the children are allowed to read
/// their parent's [parentData] slot).
///
/// The [RenderBox] subclass introduces the opinion that the layout
/// system uses Cartesian coordinates.
///
/// ## Lifecycle
///
/// A [RenderObject] must [dispose] when it is no longer needed. The creator
/// of the object is responsible for disposing of it. Typically, the creator is
/// a [RenderObjectElement], and that element will dispose the object it creates
/// when it is unmounted.
///
/// [RenderObject]s are responsible for cleaning up any expensive resources
/// they hold when [dispose] is called, such as [Picture] or [Image] objects.
/// This includes any [Layer]s that the render object has directly created. The
/// base implementation of dispose will nullify the [layer] property. Subclasses
/// must also nullify any other layer(s) it directly creates.
///
/// ## Writing a RenderObject subclass
///
/// In most cases, subclassing [RenderObject] itself is overkill, and
/// [RenderBox] would be a better starting point. However, if a render object
/// doesn't want to use a Cartesian coordinate system, then it should indeed
/// inherit from [RenderObject] directly. This allows it to define its own
/// layout protocol by using a new subclass of [Constraints] rather than using
/// [BoxConstraints], and by potentially using an entirely new set of objects
/// and values to represent the result of the output rather than just a [Size].
/// This increased flexibility comes at the cost of not being able to rely on
/// the features of [RenderBox]. For example, [RenderBox] implements an
/// intrinsic sizing protocol that allows you to measure a child without fully
/// laying it out, in such a way that if that child changes size, the parent
/// will be laid out again (to take into account the new dimensions of the
/// child). This is a subtle and bug-prone feature to get right.
///
/// Most aspects of writing a [RenderBox] apply to writing a [RenderObject] as
/// well, and therefore the discussion at [RenderBox] is recommended background
/// reading. The main differences are around layout and hit testing, since those
/// are the aspects that [RenderBox] primarily specializes.
///
/// ### Layout
///
/// A layout protocol begins with a subclass of [Constraints]. See the
/// discussion at [Constraints] for more information on how to write a
/// [Constraints] subclass.
///
/// The [performLayout] method should take the [constraints], and apply them.
/// The output of the layout algorithm is fields set on the object that describe
/// the geometry of the object for the purposes of the parent's layout. For
/// example, with [RenderBox] the output is the [RenderBox.size] field. This
/// output should only be read by the parent if the parent specified
/// `parentUsesSize` as true when calling [layout] on the child.
///
/// Anytime anything changes on a render object that would affect the layout of
/// that object, it should call [markNeedsLayout].
///
/// ### Hit Testing
///
/// Hit testing is even more open-ended than layout. There is no method to
/// override, you are expected to provide one.
///
/// The general behavior of your hit-testing method should be similar to the
/// behavior described for [RenderBox]. The main difference is that the input
/// need not be an [Offset]. You are also allowed to use a different subclass of
/// [HitTestEntry] when adding entries to the [HitTestResult]. When the
/// [handleEvent] method is called, the same object that was added to the
/// [HitTestResult] will be passed in, so it can be used to track information
/// like the precise coordinate of the hit, in whatever coordinate system is
/// used by the new layout protocol.
///
/// ### Adapting from one protocol to another
///
/// In general, the root of a Flutter render object tree is a [RenderView]. This
/// object has a single child, which must be a [RenderBox]. Thus, if you want to
/// have a custom [RenderObject] subclass in the render tree, you have two
/// choices: you either need to replace the [RenderView] itself, or you need to
/// have a [RenderBox] that has your class as its child. (The latter is the much
/// more common case.)
///
/// This [RenderBox] subclass converts from the box protocol to the protocol of
/// your class.
///
/// In particular, this means that for hit testing it overrides
/// [RenderBox.hitTest], and calls whatever method you have in your class for
/// hit testing.
///
/// Similarly, it overrides [performLayout] to create a [Constraints] object
/// appropriate for your class and passes that to the child's [layout] method.
///
/// ### Layout interactions between render objects
///
/// In general, the layout of a render object should only depend on the output of
/// its child's layout, and then only if `parentUsesSize` is set to true in the
/// [layout] call. Furthermore, if it is set to true, the parent must call the
/// child's [layout] if the child is to be rendered, because otherwise the
/// parent will not be notified when the child changes its layout outputs.
///
/// It is possible to set up render object protocols that transfer additional
/// information. For example, in the [RenderBox] protocol you can query your
/// children's intrinsic dimensions and baseline geometry. However, if this is
/// done then it is imperative that the child call [markNeedsLayout] on the
/// parent any time that additional information changes, if the parent used it
/// in the last layout phase. For an example of how to implement this, see the
/// [RenderBox.markNeedsLayout] method. It overrides
/// [RenderObject.markNeedsLayout] so that if a parent has queried the intrinsic
/// or baseline information, it gets marked dirty whenever the child's geometry
/// changes.
abstract class RenderObject with DiagnosticableTreeMixin implements HitTestTarget {
  /// Initializes internal fields for subclasses.
  RenderObject() {
    assert(debugMaybeDispatchCreated('rendering', 'RenderObject', this));
    _needsCompositing = isRepaintBoundary || alwaysNeedsCompositing;
    _wasRepaintBoundary = isRepaintBoundary;
  }

  /// Cause the entire subtree rooted at the given [RenderObject] to be marked
  /// dirty for layout, paint, etc, so that the effects of a hot reload can be
  /// seen, or so that the effect of changing a global debug flag (such as
  /// [debugPaintSizeEnabled]) can be applied.
  ///
  /// This is called by the [RendererBinding] in response to the
  /// `ext.flutter.reassemble` hook, which is used by development tools when the
  /// application code has changed, to cause the widget tree to pick up any
  /// changed implementations.
  ///
  /// This is expensive and should not be called except during development.
  ///
  /// See also:
  ///
  ///  * [BindingBase.reassembleApplication]
  void reassemble() {
    markNeedsLayout();
    markNeedsCompositingBitsUpdate();
    markNeedsPaint();
    markNeedsSemanticsUpdate();
    visitChildren((RenderObject child) {
      child.reassemble();
    });
  }

  /// Whether this has been disposed.
  ///
  /// If asserts are disabled, this property is always null.
  bool? get debugDisposed {
    bool? disposed;
    assert(() {
      disposed = _debugDisposed;
      return true;
    }());
    return disposed;
  }

  bool _debugDisposed = false;

  /// Release any resources held by this render object.
  ///
  /// The object that creates a RenderObject is in charge of disposing it.
  /// If this render object has created any children directly, it must dispose
  /// of those children in this method as well. It must not dispose of any
  /// children that were created by some other object, such as
  /// a [RenderObjectElement]. Those children will be disposed when that
  /// element unmounts, which may be delayed if the element is moved to another
  /// part of the tree.
  ///
  /// Implementations of this method must end with a call to the inherited
  /// method, as in `super.dispose()`.
  ///
  /// The object is no longer usable after calling dispose.
  @mustCallSuper
  void dispose() {
    assert(!_debugDisposed);
    assert(debugMaybeDispatchDisposed(this));
    _layerHandle.layer = null;
    assert(() {
      // TODO(dnfield): Enable this assert once clients have had a chance to
      // migrate.
      // visitChildren((RenderObject child) {
      //   assert(
      //     child.debugDisposed!,
      //     '${child.runtimeType} (child of $runtimeType) must be disposed before calling super.dispose().',
      //   );
      // });
      _debugDisposed = true;
      return true;
    }());
  }

  // LAYOUT

  /// Data for use by the parent render object.
  ///
  /// The parent data is used by the render object that lays out this object
  /// (typically this object's parent in the render tree) to store information
  /// relevant to itself and to any other nodes who happen to know exactly what
  /// the data means. The parent data is opaque to the child.
  ///
  ///  * The parent data field must not be directly set, except by calling
  ///    [setupParentData] on the parent node.
  ///  * The parent data can be set before the child is added to the parent, by
  ///    calling [setupParentData] on the future parent node.
  ///  * The conventions for using the parent data depend on the layout protocol
  ///    used between the parent and child. For example, in box layout, the
  ///    parent data is completely opaque but in sector layout the child is
  ///    permitted to read some fields of the parent data.
  ParentData? parentData;

  /// Override to setup parent data correctly for your children.
  ///
  /// You can call this function to set up the parent data for child before the
  /// child is added to the parent's child list.
  void setupParentData(covariant RenderObject child) {
    assert(_debugCanPerformMutations);
    if (child.parentData is! ParentData) {
      child.parentData = ParentData();
    }
  }

  /// The depth of this render object in the render tree.
  ///
  /// The depth of nodes in a tree monotonically increases as you traverse down
  /// the tree: a node always has a [depth] greater than its ancestors.
  /// There's no guarantee regarding depth between siblings.
  ///
  /// The [depth] of a child can be more than one greater than the [depth] of
  /// the parent, because the [depth] values are never decreased: all that
  /// matters is that it's greater than the parent. Consider a tree with a root
  /// node A, a child B, and a grandchild C. Initially, A will have [depth] 0,
  /// B [depth] 1, and C [depth] 2. If C is moved to be a child of A,
  /// sibling of B, then the numbers won't change. C's [depth] will still be 2.
  ///
  /// The depth of a node is used to ensure that nodes are processed in
  /// depth order.  The [depth] is automatically maintained by the [adoptChild]
  /// and [dropChild] methods.
  int get depth => _depth;
  int _depth = 0;

  /// Adjust the [depth] of the given [child] to be greater than this node's own
  /// [depth].
  ///
  /// Only call this method from overrides of [redepthChildren].
  @protected
  void redepthChild(RenderObject child) {
    assert(child.owner == owner);
    if (child._depth <= _depth) {
      child._depth = _depth + 1;
      child.redepthChildren();
    }
  }

  /// Adjust the [depth] of this node's children, if any.
  ///
  /// Override this method in subclasses with child nodes to call [redepthChild]
  /// for each child. Do not call this method directly.
  @protected
  void redepthChildren() {}

  /// The parent of this render object in the render tree.
  ///
  /// The [parent] of the root node in the render tree is null.
  RenderObject? get parent => _parent;
  RenderObject? _parent;

  /// Called by subclasses when they decide a render object is a child.
  ///
  /// Only for use by subclasses when changing their child lists. Calling this
  /// in other cases will lead to an inconsistent tree and probably cause crashes.
  @mustCallSuper
  @protected
  void adoptChild(RenderObject child) {
    assert(child._parent == null);
    assert(() {
      var node = this;
      while (node.parent != null) {
        node = node.parent!;
      }
      assert(node != child); // indicates we are about to create a cycle
      return true;
    }());

    setupParentData(child);
    markNeedsLayout();
    markNeedsCompositingBitsUpdate();
    markNeedsSemanticsUpdate();
    child._parent = this;
    if (attached) {
      child.attach(_owner!);
    }
    redepthChild(child);
  }

  /// Called by subclasses when they decide a render object is no longer a child.
  ///
  /// Only for use by subclasses when changing their child lists. Calling this
  /// in other cases will lead to an inconsistent tree and probably cause crashes.
  @mustCallSuper
  @protected
  void dropChild(RenderObject child) {
    assert(child._parent == this);
    assert(child.attached == attached);
    assert(child.parentData != null);
    if (!(child._isRelayoutBoundary ?? true)) {
      child._isRelayoutBoundary = null;
    }
    child.parentData!.detach();
    child.parentData = null;
    child._parent = null;
    if (attached) {
      child.detach();
    }
    markNeedsLayout();
    markNeedsCompositingBitsUpdate();
    markNeedsSemanticsUpdate();
  }

  /// Calls visitor for each immediate child of this render object.
  ///
  /// Override in subclasses with children and call the visitor for each child.
  void visitChildren(RenderObjectVisitor visitor) {}

  /// The object responsible for creating this render object.
  ///
  /// Used in debug messages.
  ///
  /// See also:
  ///
  ///  * [DebugCreator], which the [widgets] library uses as values for this field.
  Object? debugCreator;

  void _reportException(String method, Object exception, StackTrace stack) {
    FlutterError.reportError(
      FlutterErrorDetails(
        exception: exception,
        stack: stack,
        library: 'rendering library',
        context: ErrorDescription('during $method()'),
        informationCollector: () => <DiagnosticsNode>[
          // debugCreator should always be null outside of debugMode, but we want
          // the tree shaker to notice this.
          if (kDebugMode && debugCreator != null) DiagnosticsDebugCreator(debugCreator!),
          describeForError(
            'The following RenderObject was being processed when the exception was fired',
          ),
          // TODO(jacobr): this error message has a code smell. Consider whether
          // displaying the truncated children is really useful for command line
          // users. Inspector users can see the full tree by clicking on the
          // render object so this may not be that useful.
          describeForError('RenderObject', style: DiagnosticsTreeStyle.truncateChildren),
        ],
      ),
    );
  }

  /// Whether [performResize] for this render object is currently running.
  ///
  /// Only valid when asserts are enabled. In release builds, always returns
  /// false.
  bool get debugDoingThisResize => _debugDoingThisResize;
  bool _debugDoingThisResize = false;

  /// Whether [performLayout] for this render object is currently running.
  ///
  /// Only valid when asserts are enabled. In release builds, always returns
  /// false.
  bool get debugDoingThisLayout => _debugDoingThisLayout;
  bool _debugDoingThisLayout = false;

  /// The render object that is actively computing layout.
  ///
  /// Only valid when asserts are enabled. In release builds, always returns
  /// null.
  static RenderObject? get debugActiveLayout => _debugActiveLayout;
  static RenderObject? _debugActiveLayout;

  /// Set [debugActiveLayout] to null when [inner] callback is called.
  /// This is useful when you have to temporarily clear that variable to
  /// disable some false-positive checks, such as when computing toStringDeep
  /// or using custom trees.
  @pragma('dart2js:tryInline')
  @pragma('vm:prefer-inline')
  @pragma('wasm:prefer-inline')
  static T _withDebugActiveLayoutCleared<T>(T Function() inner) {
    RenderObject? debugPreviousActiveLayout;
    assert(() {
      debugPreviousActiveLayout = _debugActiveLayout;
      _debugActiveLayout = null;
      return true;
    }());
    final T result = inner();
    assert(() {
      _debugActiveLayout = debugPreviousActiveLayout;
      return true;
    }());
    return result;
  }

  /// Whether the parent render object is permitted to use this render object's
  /// size.
  ///
  /// Determined by the `parentUsesSize` parameter to [layout].
  ///
  /// Only valid when asserts are enabled. In release builds, throws.
  bool get debugCanParentUseSize => _debugCanParentUseSize!;
  bool? _debugCanParentUseSize;

  bool _debugMutationsLocked = false;

  /// Whether tree mutations are currently permitted.
  ///
  /// This is only useful during layout. One should also not mutate the tree at
  /// other times (e.g. during paint or while assembling the semantic tree) but
  /// this function does not currently enforce those conventions.
  ///
  /// Only valid when asserts are enabled. This will throw in release builds.
  bool get _debugCanPerformMutations {
    late bool result;
    assert(() {
      if (_debugDisposed) {
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('A disposed RenderObject was mutated.'),
          DiagnosticsProperty<RenderObject>(
            'The disposed RenderObject was',
            this,
            style: DiagnosticsTreeStyle.errorProperty,
          ),
        ]);
      }

      final PipelineOwner? owner = this.owner;
      // Detached nodes are allowed to mutate and the "can perform mutations"
      // check will be performed when they re-attach. This assert is only useful
      // during layout.
      if (owner == null || !owner.debugDoingLayout) {
        result = true;
        return true;
      }

      RenderObject? activeLayoutRoot = this;
      while (activeLayoutRoot != null) {
        final bool mutationsToDirtySubtreesAllowed =
            activeLayoutRoot.owner?._debugAllowMutationsToDirtySubtrees ?? false;
        final bool doingLayoutWithCallback = activeLayoutRoot._doingThisLayoutWithCallback;
        // Mutations on this subtree is allowed when:
        // - the "activeLayoutRoot" subtree is being mutated in a layout callback.
        // - a different part of the render tree is doing a layout callback,
        //   and this subtree is being reparented to that subtree, as a result
        //   of global key reparenting.
        if (doingLayoutWithCallback ||
            mutationsToDirtySubtreesAllowed && activeLayoutRoot._needsLayout) {
          result = true;
          return true;
        }

        if (!activeLayoutRoot._debugMutationsLocked) {
          activeLayoutRoot = activeLayoutRoot.debugLayoutParent;
        } else {
          // activeLayoutRoot found.
          break;
        }
      }

      final RenderObject debugActiveLayout = RenderObject.debugActiveLayout!;
      final culpritMethodName = debugActiveLayout.debugDoingThisLayout
          ? 'performLayout'
          : 'performResize';
      final culpritFullMethodName = '${debugActiveLayout.runtimeType}.$culpritMethodName';
      result = false;

      if (activeLayoutRoot == null) {
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('A $runtimeType was mutated in $culpritFullMethodName.'),
          ErrorDescription(
            'The RenderObject was mutated when none of its ancestors is actively performing layout.',
          ),
          DiagnosticsProperty<RenderObject>(
            'The RenderObject being mutated was',
            this,
            style: DiagnosticsTreeStyle.errorProperty,
          ),
          DiagnosticsProperty<RenderObject>(
            'The RenderObject that was mutating the said $runtimeType was',
            debugActiveLayout,
            style: DiagnosticsTreeStyle.errorProperty,
          ),
        ]);
      }

      if (activeLayoutRoot == this) {
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('A $runtimeType was mutated in its own $culpritMethodName implementation.'),
          ErrorDescription('A RenderObject must not re-dirty itself while still being laid out.'),
          DiagnosticsProperty<RenderObject>(
            'The RenderObject being mutated was',
            this,
            style: DiagnosticsTreeStyle.errorProperty,
          ),
          ErrorHint(
            'Consider using the LayoutBuilder widget to dynamically change a subtree during layout.',
          ),
        ]);
      }

      final summary = ErrorSummary('A $runtimeType was mutated in $culpritFullMethodName.');
      final isMutatedByAncestor = activeLayoutRoot == debugActiveLayout;
      final description = isMutatedByAncestor
          ? 'A RenderObject must not mutate its descendants in its $culpritMethodName method.'
          : 'A RenderObject must not mutate another RenderObject from a different render subtree '
                'in its $culpritMethodName method.';

      throw FlutterError.fromParts(<DiagnosticsNode>[
        summary,
        ErrorDescription(description),
        DiagnosticsProperty<RenderObject>(
          'The RenderObject being mutated was',
          this,
          style: DiagnosticsTreeStyle.errorProperty,
        ),
        DiagnosticsProperty<RenderObject>(
          'The ${isMutatedByAncestor ? 'ancestor ' : ''}RenderObject that was mutating the said $runtimeType was',
          debugActiveLayout,
          style: DiagnosticsTreeStyle.errorProperty,
        ),
        if (!isMutatedByAncestor)
          DiagnosticsProperty<RenderObject>(
            'Their common ancestor was',
            activeLayoutRoot,
            style: DiagnosticsTreeStyle.errorProperty,
          ),
        ErrorHint(
          'Mutating the layout of another RenderObject may cause some RenderObjects in its subtree to be laid out more than once. '
          'Consider using the LayoutBuilder widget to dynamically mutate a subtree during layout.',
        ),
      ]);
    }());
    return result;
  }

  /// The [RenderObject] that's expected to call [layout] on this [RenderObject]
  /// in its [performLayout] implementation.
  ///
  /// This method is used to implement an assert that ensures the render subtree
  /// actively performing layout can not get accidentally mutated. It's only
  /// implemented in debug mode and always returns null in release mode.
  ///
  /// The default implementation returns [parent] and overriding is rarely
  /// needed. A [RenderObject] subclass that expects its
  /// [RenderObject.performLayout] to be called from a different [RenderObject]
  /// that's not its [parent] should override this property to return the actual
  /// layout parent.
  @protected
  RenderObject? get debugLayoutParent {
    RenderObject? layoutParent;
    assert(() {
      layoutParent = parent;
      return true;
    }());
    return layoutParent;
  }

  /// The owner for this render object (null if unattached).
  ///
  /// The entire render tree that this render object belongs to
  /// will have the same owner.
  PipelineOwner? get owner => _owner;
  PipelineOwner? _owner;

  /// Whether the render tree this render object belongs to is attached to a [PipelineOwner].
  ///
  /// This becomes true during the call to [attach].
  ///
  /// This becomes false during the call to [detach].
  bool get attached => _owner != null;

  /// Mark this render object as attached to the given owner.
  ///
  /// Typically called only from the [parent]'s [attach] method, and by the
  /// [owner] to mark the root of a tree as attached.
  ///
  /// Subclasses with children should override this method to
  /// [attach] all their children to the same [owner]
  /// after calling the inherited method, as in `super.attach(owner)`.
  @mustCallSuper
  void attach(PipelineOwner owner) {
    assert(!_debugDisposed);
    assert(_owner == null);
    _owner = owner;
    // If the node was dirtied in some way while unattached, make sure to add
    // it to the appropriate dirty list now that an owner is available
    if (_needsLayout && _isRelayoutBoundary != null) {
      // Don't enter this block if we've never laid out at all;
      // scheduleInitialLayout() will handle it
      _needsLayout = false;
      markNeedsLayout();
    }
    if (_needsCompositingBitsUpdate) {
      _needsCompositingBitsUpdate = false;
      markNeedsCompositingBitsUpdate();
    }
    if (_needsPaint && _layerHandle.layer != null) {
      // Don't enter this block if we've never painted at all;
      // scheduleInitialPaint() will handle it
      _needsPaint = false;
      markNeedsPaint();
    }
    if (_semantics.configProvider.effective.isSemanticBoundary &&
        (_semantics.parentDataDirty || !_semantics.built)) {
      markNeedsSemanticsUpdate();
    }
  }

  /// Mark this render object as detached from its [PipelineOwner].
  ///
  /// Typically called only from the [parent]'s [detach], and by the [owner] to
  /// mark the root of a tree as detached.
  ///
  /// Subclasses with children should override this method to
  /// [detach] all their children after calling the inherited method,
  /// as in `super.detach()`.
  @mustCallSuper
  void detach() {
    assert(_owner != null);
    _owner = null;
    assert(parent == null || attached == parent!.attached);
  }

  /// Whether this render object's layout information is dirty.
  ///
  /// This is only set in debug mode. In general, render objects should not need
  /// to condition their runtime behavior on whether they are dirty or not,
  /// since they should only be marked dirty immediately prior to being laid
  /// out and painted. In release builds, this throws.
  ///
  /// It is intended to be used by tests and asserts.
  bool get debugNeedsLayout {
    late bool result;
    assert(() {
      result = _needsLayout;
      return true;
    }());
    return result;
  }

  bool _needsLayout = true;

  /// Whether this [RenderObject] is a known relayout boundary.
  ///
  /// A relayout boundary is a [RenderObject] whose parent does not rely on the
  /// child [RenderObject]'s size in its own layout algorithm. In other words,
  /// if a [RenderObject]'s [performLayout] implementation does not ask the child
  /// for its size at all, **the child** is a relayout boundary.
  ///
  /// The type of "size" is typically defined by the coordinate system a
  /// [RenderObject] subclass uses. For instance, [RenderSliver]s produce
  /// [SliverGeometry] and [RenderBox]es produce [Size]. A parent [RenderObject]
  /// may not read the child's size but still depend on the child's layout (using
  /// a [RenderBox] child's baseline location, for example), this flag does not
  /// reflect such dependencies and the [RenderObject] subclass must handle those
  /// cases in its own implementation. See [RenderBox.markNeedsLayout] for an
  /// example.
  ///
  /// Relayout boundaries enable an important layout optimization: the parent not
  /// depending on the size of a child means the child changing size does not
  /// affect the layout of the parent. When a relayout boundary is marked as
  /// needing layout, its parent does not have to be marked as dirty, hence the
  /// name. For details, see [markNeedsLayout].
  ///
  /// This flag is typically set in [RenderObject.layout], and consulted by
  /// [markNeedsLayout] in deciding whether to recursively mark the parent as
  /// also needing layout.
  ///
  /// The flag is initially set to `null` when [layout] has yet been called, and
  /// reset to `null` when the parent drops this child via [dropChild].
  bool? _isRelayoutBoundary;

  /// Whether [invokeLayoutCallback] for this render object is currently running.
  bool get debugDoingThisLayoutWithCallback => _doingThisLayoutWithCallback;
  bool _doingThisLayoutWithCallback = false;

  /// The layout constraints most recently supplied by the parent.
  ///
  /// If layout has not yet happened, accessing this getter will
  /// throw a [StateError] exception.
  @protected
  Constraints get constraints {
    if (_constraints == null) {
      throw StateError('A RenderObject does not have any constraints before it has been laid out.');
    }
    return _constraints!;
  }

  Constraints? _constraints;

  /// Verify that the object's constraints are being met. Override this function
  /// in a subclass to verify that your state matches the constraints object.
  /// This function is only called when asserts are enabled (i.e. in debug mode)
  /// and only when needsLayout is false. If the constraints are not met, it
  /// should assert or throw an exception.
  @protected
  void debugAssertDoesMeetConstraints();

  /// When true, a debug method ([debugAssertDoesMeetConstraints], for instance)
  /// is currently executing asserts for verifying the consistent behavior of
  /// intrinsic dimensions methods.
  ///
  /// This is typically set by framework debug methods. It is read by tests to
  /// selectively ignore custom layout callbacks. It should not be set outside of
  /// intrinsic-checking debug methods, and should not be checked in release mode
  /// (where it will always be false).
  static bool debugCheckingIntrinsics = false;

  bool _debugRelayoutBoundaryAlreadyMarkedNeedsLayout() {
    for (
      RenderObject? node = this;
      node != null && node._isRelayoutBoundary != null;
      node = node.parent
    ) {
      final bool alreadyMarkedNeedsLayout = node._needsLayout || node._debugDoingThisLayout;
      if (!alreadyMarkedNeedsLayout) {
        return false;
      }
      if (node._isRelayoutBoundary!) {
        return true;
      }
    }
    return true;
  }

  /// Mark this render object's layout information as dirty, and either register
  /// this object with its [PipelineOwner], or defer to the parent, depending on
  /// whether this object is a relayout boundary or not respectively.
  ///
  /// ## Background
  ///
  /// Rather than eagerly updating layout information in response to writes into
  /// a render object, we instead mark the layout information as dirty, which
  /// schedules a visual update. As part of the visual update, the rendering
  /// pipeline updates the render object's layout information.
  ///
  /// This mechanism batches the layout work so that multiple sequential writes
  /// are coalesced, removing redundant computation.
  ///
  /// If a render object's parent indicates that it uses the size of one of its
  /// render object children when computing its layout information, this
  /// function, when called for the child, will also mark the parent as needing
  /// layout. In that case, since both the parent and the child need to have
  /// their layout recomputed, the pipeline owner is only notified about the
  /// parent; when the parent is laid out, it will call the child's [layout]
  /// method and thus the child will be laid out as well.
  ///
  /// Once [markNeedsLayout] has been called on a render object,
  /// [debugNeedsLayout] returns true for that render object until just after
  /// the pipeline owner has called [layout] on the render object.
  ///
  /// ## Special cases
  ///
  /// Some subclasses of [RenderObject], notably [RenderBox], have other
  /// situations in which the parent needs to be notified if the child is
  /// dirtied (e.g., if the child's intrinsic dimensions or baseline changes).
  /// Such subclasses override markNeedsLayout and either call
  /// `super.markNeedsLayout()`, in the normal case, or call
  /// [markParentNeedsLayout], in the case where the parent needs to be laid out
  /// as well as the child.
  ///
  /// If [sizedByParent] has changed, calls
  /// [markNeedsLayoutForSizedByParentChange] instead of [markNeedsLayout].
  void markNeedsLayout() {
    assert(_debugCanPerformMutations);
    if (_needsLayout) {
      assert(_debugRelayoutBoundaryAlreadyMarkedNeedsLayout());
      return;
    }
    _needsLayout = true;
    if (owner case final PipelineOwner owner? when (_isRelayoutBoundary ?? false)) {
      assert(() {
        if (debugPrintMarkNeedsLayoutStacks) {
          debugPrintStack(label: 'markNeedsLayout() called for $this');
        }
        return true;
      }());
      owner._nodesNeedingLayout.add(this);
      owner.requestVisualUpdate();
    } else if (parent != null) {
      markParentNeedsLayout();
    }
  }

  /// Mark this render object's layout information as dirty, and then defer to
  /// the parent.
  ///
  /// This function should only be called from [markNeedsLayout] or
  /// [markNeedsLayoutForSizedByParentChange] implementations of subclasses that
  /// introduce more reasons for deferring the handling of dirty layout to the
  /// parent. See [markNeedsLayout] for details.
  ///
  /// Only call this if [parent] is not null.
  @protected
  void markParentNeedsLayout() {
    assert(_debugCanPerformMutations);
    _needsLayout = true;
    assert(this.parent != null);
    final RenderObject parent = this.parent!;
    if (!_doingThisLayoutWithCallback) {
      parent.markNeedsLayout();
    } else {
      assert(parent._debugDoingThisLayout);
    }
    assert(parent == this.parent);
  }

  /// Mark this render object's layout information as dirty (like
  /// [markNeedsLayout]), and additionally also handle any necessary work to
  /// handle the case where [sizedByParent] has changed value.
  ///
  /// This should be called whenever [sizedByParent] might have changed.
  ///
  /// Only call this if [parent] is not null.
  void markNeedsLayoutForSizedByParentChange() {
    markNeedsLayout();
    markParentNeedsLayout();
  }

  /// Bootstrap the rendering pipeline by scheduling the very first layout.
  ///
  /// Requires this render object to be attached and that this render object
  /// is the root of the render tree.
  ///
  /// See [RenderView] for an example of how this function is used.
  void scheduleInitialLayout() {
    assert(!_debugDisposed);
    assert(attached);
    assert(parent == null);
    assert(!owner!._debugDoingLayout);
    assert(_isRelayoutBoundary == null);
    _isRelayoutBoundary = true;
    assert(() {
      _debugCanParentUseSize = false;
      return true;
    }());
    owner!._nodesNeedingLayout.add(this);
  }

  @pragma('vm:notify-debugger-on-exception')
  void _layoutWithoutResize() {
    assert(_needsLayout);
    assert((_isRelayoutBoundary ?? false) || this is RenderObjectWithLayoutCallbackMixin);
    RenderObject? debugPreviousActiveLayout;
    assert(!_debugMutationsLocked);
    assert(!_doingThisLayoutWithCallback);
    assert(_debugCanParentUseSize != null);
    assert(() {
      _debugMutationsLocked = true;
      _debugDoingThisLayout = true;
      debugPreviousActiveLayout = _debugActiveLayout;
      _debugActiveLayout = this;
      if (debugPrintLayouts) {
        debugPrint('Laying out (without resize) $this');
      }
      return true;
    }());
    try {
      performLayout();
      markNeedsSemanticsUpdate();
    } catch (e, stack) {
      _reportException('performLayout', e, stack);
    }
    assert(() {
      _debugActiveLayout = debugPreviousActiveLayout;
      _debugDoingThisLayout = false;
      _debugMutationsLocked = false;
      return true;
    }());
    _needsLayout = false;
    markNeedsPaint();
  }

  /// Compute the layout for this render object.
  ///
  /// This method is the main entry point for parents to ask their children to
  /// update their layout information. The parent passes a constraints object,
  /// which informs the child as to which layouts are permissible. The child is
  /// required to obey the given constraints.
  ///
  /// If the parent reads information computed during the child's layout, the
  /// parent must pass true for `parentUsesSize`. In that case, the parent will
  /// be marked as needing layout whenever the child is marked as needing layout
  /// because the parent's layout information depends on the child's layout
  /// information. If the parent uses the default value (false) for
  /// `parentUsesSize`, the child can change its layout information (subject to
  /// the given constraints) without informing the parent.
  ///
  /// Subclasses should not override [layout] directly. Instead, they should
  /// override [performResize] and/or [performLayout]. The [layout] method
  /// delegates the actual work to [performResize] and [performLayout].
  ///
  /// The parent's [performLayout] method should call the [layout] of all its
  /// children unconditionally. It is the [layout] method's responsibility (as
  /// implemented here) to return early if the child does not need to do any
  /// work to update its layout information.
  @pragma('vm:notify-debugger-on-exception')
  void layout(Constraints constraints, {bool parentUsesSize = false}) {
    assert(!_debugDisposed);
    if (!kReleaseMode && debugProfileLayoutsEnabled) {
      Map<String, String>? debugTimelineArguments;
      assert(() {
        if (debugEnhanceLayoutTimelineArguments) {
          debugTimelineArguments = toDiagnosticsNode().toTimelineArguments();
        }
        return true;
      }());
      FlutterTimeline.startSync('$runtimeType', arguments: debugTimelineArguments);
    }
    assert(
      constraints.debugAssertIsValid(
        isAppliedConstraint: true,
        informationCollector: () {
          final List<String> stack = StackTrace.current.toString().split('\n');
          int? targetFrame;
          final Pattern layoutFramePattern = RegExp(r'^#[0-9]+ +Render(?:Object|Box).layout \(');
          for (var i = 0; i < stack.length; i += 1) {
            if (layoutFramePattern.matchAsPrefix(stack[i]) != null) {
              targetFrame = i + 1;
            } else if (targetFrame != null) {
              break;
            }
          }
          if (targetFrame != null && targetFrame < stack.length) {
            final Pattern targetFramePattern = RegExp(r'^#[0-9]+ +(.+)$');
            final Match? targetFrameMatch = targetFramePattern.matchAsPrefix(stack[targetFrame]);
            final String? problemFunction =
                (targetFrameMatch != null && targetFrameMatch.groupCount > 0)
                ? targetFrameMatch.group(1)
                : stack[targetFrame].trim();
            return <DiagnosticsNode>[
              ErrorDescription(
                "These invalid constraints were provided to $runtimeType's layout() "
                'function by the following function, which probably computed the '
                'invalid constraints in question:\n'
                '  $problemFunction',
              ),
            ];
          }
          return <DiagnosticsNode>[];
        },
      ),
    );
    assert(!_debugDoingThisResize);
    assert(!_debugDoingThisLayout);
    assert(() {
      _debugCanParentUseSize = parentUsesSize;
      return true;
    }());

    _isRelayoutBoundary = !parentUsesSize || sizedByParent || constraints.isTight || parent == null;
    if (!_needsLayout && constraints == _constraints) {
      assert(() {
        // in case parentUsesSize changed since the last invocation, set size
        // to itself, so it has the right internal debug values.
        _debugDoingThisResize = sizedByParent;
        _debugDoingThisLayout = !sizedByParent;
        final RenderObject? debugPreviousActiveLayout = _debugActiveLayout;
        _debugActiveLayout = this;
        debugResetSize();
        _debugActiveLayout = debugPreviousActiveLayout;
        _debugDoingThisLayout = false;
        _debugDoingThisResize = false;
        return true;
      }());
      if (!kReleaseMode && debugProfileLayoutsEnabled) {
        FlutterTimeline.finishSync();
      }
      return;
    }
    _constraints = constraints;

    assert(!_debugMutationsLocked);
    assert(!_doingThisLayoutWithCallback);
    assert(() {
      _debugMutationsLocked = true;
      if (debugPrintLayouts) {
        debugPrint(
          'Laying out (${sizedByParent ? "with separate resize" : "with resize allowed"}) $this',
        );
      }
      return true;
    }());
    if (sizedByParent) {
      assert(() {
        _debugDoingThisResize = true;
        return true;
      }());
      try {
        performResize();
        assert(() {
          debugAssertDoesMeetConstraints();
          return true;
        }());
      } catch (e, stack) {
        _reportException('performResize', e, stack);
      }
      assert(() {
        _debugDoingThisResize = false;
        return true;
      }());
    }
    RenderObject? debugPreviousActiveLayout;
    assert(() {
      _debugDoingThisLayout = true;
      debugPreviousActiveLayout = _debugActiveLayout;
      _debugActiveLayout = this;
      return true;
    }());
    try {
      performLayout();
      markNeedsSemanticsUpdate();
      assert(() {
        debugAssertDoesMeetConstraints();
        return true;
      }());
    } catch (e, stack) {
      _reportException('performLayout', e, stack);
    }
    assert(() {
      _debugActiveLayout = debugPreviousActiveLayout;
      _debugDoingThisLayout = false;
      _debugMutationsLocked = false;
      return true;
    }());
    _needsLayout = false;
    markNeedsPaint();

    if (!kReleaseMode && debugProfileLayoutsEnabled) {
      FlutterTimeline.finishSync();
    }
  }

  /// If a subclass has a "size" (the state controlled by `parentUsesSize`,
  /// whatever it is in the subclass, e.g. the actual `size` property of
  /// [RenderBox]), and the subclass verifies that in debug mode this "size"
  /// property isn't used when [debugCanParentUseSize] isn't set, then that
  /// subclass should override [debugResetSize] to reapply the current values of
  /// [debugCanParentUseSize] to that state.
  @protected
  void debugResetSize() {}

  /// Whether the constraints are the only input to the sizing algorithm (in
  /// particular, child nodes have no impact).
  ///
  /// Returning false is always correct, but returning true can be more
  /// efficient when computing the size of this render object because we don't
  /// need to recompute the size if the constraints don't change.
  ///
  /// Typically, subclasses will always return the same value. If the value can
  /// change, then, when it does change, the subclass should make sure to call
  /// [markNeedsLayoutForSizedByParentChange].
  ///
  /// Subclasses that return true must not change the dimensions of this render
  /// object in [performLayout]. Instead, that work should be done by
  /// [performResize] or - for subclasses of [RenderBox] - in
  /// [RenderBox.computeDryLayout].
  @protected
  bool get sizedByParent => false;

  /// {@template flutter.rendering.RenderObject.performResize}
  /// Updates the render objects size using only the constraints.
  ///
  /// Do not call this function directly: call [layout] instead. This function
  /// is called by [layout] when there is actually work to be done by this
  /// render object during layout. The layout constraints provided by your
  /// parent are available via the [constraints] getter.
  ///
  /// This function is called only if [sizedByParent] is true.
  /// {@endtemplate}
  ///
  /// Subclasses that set [sizedByParent] to true should override this method to
  /// compute their size. Subclasses of [RenderBox] should consider overriding
  /// [RenderBox.computeDryLayout] instead.
  @protected
  void performResize();

  /// Do the work of computing the layout for this render object.
  ///
  /// Do not call this function directly: call [layout] instead. This function
  /// is called by [layout] when there is actually work to be done by this
  /// render object during layout. The layout constraints provided by your
  /// parent are available via the [constraints] getter.
  ///
  /// If [sizedByParent] is true, then this function should not actually change
  /// the dimensions of this render object. Instead, that work should be done by
  /// [performResize]. If [sizedByParent] is false, then this function should
  /// both change the dimensions of this render object and instruct its children
  /// to layout.
  ///
  /// In implementing this function, you must call [layout] on each of your
  /// children, passing true for parentUsesSize if your layout information is
  /// dependent on your child's layout information. Passing true for
  /// parentUsesSize ensures that this render object will undergo layout if the
  /// child undergoes layout. Otherwise, the child can change its layout
  /// information without informing this render object.
  ///
  /// Some special [RenderObject] subclasses (such as the one used by
  /// [OverlayPortal.overlayChildLayoutBuilder]) call [applyPaintTransform] in
  /// their [performLayout] implementation. To ensure such [RenderObject]s get
  /// the up-to-date paint transform, [RenderObject] subclasses should typically
  /// update the paint transform (as reported by [applyPaintTransform]) in this
  /// method instead of [paint].
  @protected
  void performLayout();

  /// Allows mutations to be made to this object's child list (and any
  /// descendants) as well as to any other dirty nodes in the render tree owned
  /// by the same [PipelineOwner] as this object. The `callback` argument is
  /// invoked synchronously, and the mutations are allowed only during that
  /// callback's execution.
  ///
  /// This exists to allow child lists to be built on-demand during layout (e.g.
  /// based on the object's size), and to enable nodes to be moved around the
  /// tree as this happens (e.g. to handle [GlobalKey] reparenting), while still
  /// ensuring that any particular node is only laid out once per frame.
  ///
  /// Calling this function disables a number of assertions that are intended to
  /// catch likely bugs. As such, using this function is generally discouraged.
  ///
  /// This function can only be called during layout.
  @protected
  void invokeLayoutCallback<T extends Constraints>(LayoutCallback<T> callback) {
    assert(_debugMutationsLocked);
    assert(_debugDoingThisLayout);
    assert(!_doingThisLayoutWithCallback);
    _doingThisLayoutWithCallback = true;
    try {
      owner!._enableMutationsToDirtySubtrees(() {
        callback(constraints as T);
      });
    } finally {
      _doingThisLayoutWithCallback = false;
    }
  }

  // PAINTING

  /// Whether [paint] for this render object is currently running.
  ///
  /// Only valid when asserts are enabled. In release builds, always returns
  /// false.
  bool get debugDoingThisPaint => _debugDoingThisPaint;
  bool _debugDoingThisPaint = false;

  /// The render object that is actively painting.
  ///
  /// Only valid when asserts are enabled. In release builds, always returns
  /// null.
  static RenderObject? get debugActivePaint => _debugActivePaint;
  static RenderObject? _debugActivePaint;

  /// Whether this render object repaints separately from its parent.
  ///
  /// Override this in subclasses to indicate that instances of your class ought
  /// to repaint independently. For example, render objects that repaint
  /// frequently might want to repaint themselves without requiring their parent
  /// to repaint.
  ///
  /// If this getter returns true, the [paintBounds] are applied to this object
  /// and all descendants. The framework invokes [RenderObject.updateCompositedLayer]
  /// to create an [OffsetLayer] and assigns it to the [layer] field.
  /// Render objects that declare themselves as repaint boundaries must not replace
  /// the layer created by the framework.
  ///
  /// If the value of this getter changes, [markNeedsCompositingBitsUpdate] must
  /// be called.
  ///
  /// See [RepaintBoundary] for more information about how repaint boundaries function.
  bool get isRepaintBoundary => false;

  /// Called, in debug mode, if [isRepaintBoundary] is true, when either the
  /// this render object or its parent attempt to paint.
  ///
  /// This can be used to record metrics about whether the node should actually
  /// be a repaint boundary.
  void debugRegisterRepaintBoundaryPaint({
    bool includedParent = true,
    bool includedChild = false,
  }) {}

  /// Whether this render object always needs compositing.
  ///
  /// Override this in subclasses to indicate that your paint function always
  /// creates at least one composited layer. For example, videos should return
  /// true if they use hardware decoders.
  ///
  /// You must call [markNeedsCompositingBitsUpdate] if the value of this getter
  /// changes. (This is implied when [adoptChild] or [dropChild] are called.)
  @protected
  bool get alwaysNeedsCompositing => false;

  late bool _wasRepaintBoundary;

  /// Update the composited layer owned by this render object.
  ///
  /// This method is called by the framework when [isRepaintBoundary] is true.
  ///
  /// If [oldLayer] is `null`, this method must return a new [OffsetLayer]
  /// (or subtype thereof). If [oldLayer] is not `null`, then this method must
  /// reuse the layer instance that is provided - it is an error to create a new
  /// layer in this instance. The layer will be disposed by the framework when
  /// either the render object is disposed or if it is no longer a repaint
  /// boundary.
  ///
  /// The [OffsetLayer.offset] property will be managed by the framework and
  /// must not be updated by this method.
  ///
  /// If a property of the composited layer needs to be updated, the render object
  /// must call [markNeedsCompositedLayerUpdate] which will schedule this method
  /// to be called without repainting children. If this widget was marked as
  /// needing to paint and needing a composited layer update, this method is only
  /// called once.
  // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/102102 revisit the
  // constraint that the instance/type of layer cannot be changed at runtime.
  OffsetLayer updateCompositedLayer({required covariant OffsetLayer? oldLayer}) {
    assert(isRepaintBoundary);
    return oldLayer ?? OffsetLayer();
  }

  /// The compositing layer that this render object uses to repaint.
  ///
  /// If this render object is not a repaint boundary, it is the responsibility
  /// of the [paint] method to populate this field. If [needsCompositing] is
  /// true, this field may be populated with the root-most layer used by the
  /// render object implementation. When repainting, instead of creating a new
  /// layer the render object may update the layer stored in this field for better
  /// performance. It is also OK to leave this field as null and create a new
  /// layer on every repaint, but without the performance benefit. If
  /// [needsCompositing] is false, this field must be set to null either by
  /// never populating this field, or by setting it to null when the value of
  /// [needsCompositing] changes from true to false.
  ///
  /// If a new layer is created and stored in some other field on the render
  /// object, the render object must use a [LayerHandle] to store it. A layer
  /// handle will prevent the layer from being disposed before the render
  /// object is finished with it, and it will also make sure that the layer
  /// gets appropriately disposed when the render object creates a replacement
  /// or nulls it out. The render object must null out the [LayerHandle.layer]
  /// in its [dispose] method.
  ///
  /// If this render object is a repaint boundary, the framework automatically
  /// creates an [OffsetLayer] and populates this field prior to calling the
  /// [paint] method. The [paint] method must not replace the value of this
  /// field.
  @protected
  ContainerLayer? get layer {
    assert(!isRepaintBoundary || _layerHandle.layer == null || _layerHandle.layer is OffsetLayer);
    return _layerHandle.layer;
  }

  @protected
  set layer(ContainerLayer? newLayer) {
    assert(
      !isRepaintBoundary,
      'Attempted to set a layer to a repaint boundary render object.\n'
      'The framework creates and assigns an OffsetLayer to a repaint '
      'boundary automatically.',
    );
    _layerHandle.layer = newLayer;
  }

  final LayerHandle<ContainerLayer> _layerHandle = LayerHandle<ContainerLayer>();

  /// In debug mode, the compositing layer that this render object uses to repaint.
  ///
  /// This getter is intended for debugging purposes only. In release builds, it
  /// always returns null. In debug builds, it returns the layer even if the layer
  /// is dirty.
  ///
  /// For production code, consider [layer].
  ContainerLayer? get debugLayer {
    ContainerLayer? result;
    assert(() {
      result = _layerHandle.layer;
      return true;
    }());
    return result;
  }

  bool _needsCompositingBitsUpdate = false; // set to true when a child is added
  /// Mark the compositing state for this render object as dirty.
  ///
  /// This is called to indicate that the value for [needsCompositing] needs to
  /// be recomputed during the next [PipelineOwner.flushCompositingBits] engine
  /// phase.
  ///
  /// When the subtree is mutated, we need to recompute our
  /// [needsCompositing] bit, and some of our ancestors need to do the
  /// same (in case ours changed in a way that will change theirs). To
  /// this end, [adoptChild] and [dropChild] call this method, and, as
  /// necessary, this method calls the parent's, etc, walking up the
  /// tree to mark all the nodes that need updating.
  ///
  /// This method does not schedule a rendering frame, because since
  /// it cannot be the case that _only_ the compositing bits changed,
  /// something else will have scheduled a frame for us.
  void markNeedsCompositingBitsUpdate() {
    assert(!_debugDisposed);
    if (_needsCompositingBitsUpdate) {
      return;
    }
    _needsCompositingBitsUpdate = true;
    final RenderObject? parent = this.parent;
    if (parent != null) {
      if (parent._needsCompositingBitsUpdate) {
        return;
      }

      if ((!_wasRepaintBoundary || !isRepaintBoundary) && !parent.isRepaintBoundary) {
        parent.markNeedsCompositingBitsUpdate();
        return;
      }
    }
    // parent is fine (or there isn't one), but we are dirty
    owner?._nodesNeedingCompositingBitsUpdate.add(this);
  }

  late bool _needsCompositing; // initialized in the constructor
  /// Whether we or one of our descendants has a compositing layer.
  ///
  /// If this node needs compositing as indicated by this bit, then all ancestor
  /// nodes will also need compositing.
  ///
  /// Only legal to call after [PipelineOwner.flushLayout] and
  /// [PipelineOwner.flushCompositingBits] have been called.
  bool get needsCompositing {
    assert(!_needsCompositingBitsUpdate); // make sure we don't use this bit when it is dirty
    return _needsCompositing;
  }

  void _updateCompositingBits() {
    if (!_needsCompositingBitsUpdate) {
      return;
    }
    final bool oldNeedsCompositing = _needsCompositing;
    _needsCompositing = false;
    visitChildren((RenderObject child) {
      child._updateCompositingBits();
      if (child.needsCompositing) {
        _needsCompositing = true;
      }
    });
    if (isRepaintBoundary || alwaysNeedsCompositing) {
      _needsCompositing = true;
    }
    // If a node was previously a repaint boundary, but no longer is one, then
    // regardless of its compositing state we need to find a new parent to
    // paint from. To do this, we mark it clean again so that the traversal
    // in markNeedsPaint is not short-circuited. It is removed from _nodesNeedingPaint
    // so that we do not attempt to paint from it after locating a parent.
    if (!isRepaintBoundary && _wasRepaintBoundary) {
      _needsPaint = false;
      _needsCompositedLayerUpdate = false;
      owner?._nodesNeedingPaint.removeWhere((RenderObject t) => identical(t, this));
      _needsCompositingBitsUpdate = false;
      markNeedsPaint();
    } else if (oldNeedsCompositing != _needsCompositing) {
      _needsCompositingBitsUpdate = false;
      markNeedsPaint();
    } else {
      _needsCompositingBitsUpdate = false;
    }
  }

  /// Whether this render object's paint information is dirty.
  ///
  /// This is only set in debug mode. In general, render objects should not need
  /// to condition their runtime behavior on whether they are dirty or not,
  /// since they should only be marked dirty immediately prior to being laid
  /// out and painted. (In release builds, this throws.)
  ///
  /// It is intended to be used by tests and asserts.
  ///
  /// It is possible (and indeed, quite common) for [debugNeedsPaint] to be
  /// false and [debugNeedsLayout] to be true. The render object will still be
  /// repainted in the next frame when this is the case, because the
  /// [markNeedsPaint] method is implicitly called by the framework after a
  /// render object is laid out, prior to the paint phase.
  bool get debugNeedsPaint {
    late bool result;
    assert(() {
      result = _needsPaint;
      return true;
    }());
    return result;
  }

  bool _needsPaint = true;

  /// Whether this render object's layer information is dirty.
  ///
  /// This is only set in debug mode. In general, render objects should not need
  /// to condition their runtime behavior on whether they are dirty or not,
  /// since they should only be marked dirty immediately prior to being laid
  /// out and painted. (In release builds, this throws.)
  ///
  /// It is intended to be used by tests and asserts.
  bool get debugNeedsCompositedLayerUpdate {
    late bool result;
    assert(() {
      result = _needsCompositedLayerUpdate;
      return true;
    }());
    return result;
  }

  bool _needsCompositedLayerUpdate = false;

  /// Mark this render object as having changed its visual appearance.
  ///
  /// Rather than eagerly updating this render object's display list
  /// in response to writes, we instead mark the render object as needing to
  /// paint, which schedules a visual update. As part of the visual update, the
  /// rendering pipeline will give this render object an opportunity to update
  /// its display list.
  ///
  /// This mechanism batches the painting work so that multiple sequential
  /// writes are coalesced, removing redundant computation.
  ///
  /// Once [markNeedsPaint] has been called on a render object,
  /// [debugNeedsPaint] returns true for that render object until just after
  /// the pipeline owner has called [paint] on the render object.
  ///
  /// See also:
  ///
  ///  * [RepaintBoundary], to scope a subtree of render objects to their own
  ///    layer, thus limiting the number of nodes that [markNeedsPaint] must mark
  ///    dirty.
  void markNeedsPaint() {
    assert(!_debugDisposed);
    assert(owner == null || !owner!.debugDoingPaint);
    if (_needsPaint) {
      return;
    }
    _needsPaint = true;
    // If this was not previously a repaint boundary it will not have
    // a layer we can paint from.
    if (isRepaintBoundary && _wasRepaintBoundary) {
      assert(() {
        if (debugPrintMarkNeedsPaintStacks) {
          debugPrintStack(label: 'markNeedsPaint() called for $this');
        }
        return true;
      }());
      // If we always have our own layer, then we can just repaint
      // ourselves without involving any other nodes.
      assert(_layerHandle.layer is OffsetLayer);
      if (owner != null) {
        owner!._nodesNeedingPaint.add(this);
        owner!.requestVisualUpdate();
      }
    } else if (parent != null) {
      parent!.markNeedsPaint();
    } else {
      assert(() {
        if (debugPrintMarkNeedsPaintStacks) {
          debugPrintStack(label: 'markNeedsPaint() called for $this (root of render tree)');
        }
        return true;
      }());
      // If we are the root of the render tree and not a repaint boundary
      // then we have to paint ourselves, since nobody else can paint us.
      // We don't add ourselves to _nodesNeedingPaint in this case,
      // because the root is always told to paint regardless.
      //
      // Trees rooted at a RenderView do not go through this
      // code path because RenderViews are repaint boundaries.
      owner?.requestVisualUpdate();
    }
  }

  /// Mark this render object as having changed a property on its composited
  /// layer.
  ///
  /// Render objects that have a composited layer have [isRepaintBoundary] equal
  /// to true may update the properties of that composited layer without repainting
  /// their children. If this render object is a repaint boundary but does
  /// not yet have a composited layer created for it, this method will instead
  /// mark the nearest repaint boundary parent as needing to be painted.
  ///
  /// If this method is called on a render object that is not a repaint boundary
  /// or is a repaint boundary but hasn't been composited yet, it is equivalent
  /// to calling [markNeedsPaint].
  ///
  /// See also:
  ///
  ///  * [RenderOpacity], which uses this method when its opacity is updated to
  ///    update the layer opacity without repainting children.
  void markNeedsCompositedLayerUpdate() {
    assert(!_debugDisposed);
    assert(owner == null || !owner!.debugDoingPaint);
    if (_needsCompositedLayerUpdate || _needsPaint) {
      return;
    }
    _needsCompositedLayerUpdate = true;
    // If this was not previously a repaint boundary it will not have
    // a layer we can paint from.
    if (isRepaintBoundary && _wasRepaintBoundary) {
      // If we always have our own layer, then we can just repaint
      // ourselves without involving any other nodes.
      assert(_layerHandle.layer != null);
      if (owner != null) {
        owner!._nodesNeedingPaint.add(this);
        owner!.requestVisualUpdate();
      }
    } else {
      markNeedsPaint();
    }
  }

  // Called when flushPaint() tries to make us paint but our layer is detached.
  // To make sure that our subtree is repainted when it's finally reattached,
  // even in the case where some ancestor layer is itself never marked dirty, we
  // have to mark our entire detached subtree as dirty and needing to be
  // repainted. That way, we'll eventually be repainted.
  void _skippedPaintingOnLayer() {
    assert(attached);
    assert(isRepaintBoundary);
    assert(_needsPaint || _needsCompositedLayerUpdate);
    assert(_layerHandle.layer != null);
    assert(!_layerHandle.layer!.attached);
    RenderObject? node = parent;
    while (node != null) {
      if (node.isRepaintBoundary) {
        if (node._layerHandle.layer == null) {
          // Looks like the subtree here has never been painted. Let it handle itself.
          break;
        }
        if (node._layerHandle.layer!.attached) {
          // It's the one that detached us, so it's the one that will decide to repaint us.
          break;
        }
        node._needsPaint = true;
      }
      node = node.parent;
    }
  }

  /// Bootstrap the rendering pipeline by scheduling the very first paint.
  ///
  /// Requires that this render object is attached, is the root of the render
  /// tree, and has a composited layer.
  ///
  /// See [RenderView] for an example of how this function is used.
  void scheduleInitialPaint(ContainerLayer rootLayer) {
    assert(rootLayer.attached);
    assert(attached);
    assert(parent == null);
    assert(!owner!._debugDoingPaint);
    assert(isRepaintBoundary);
    assert(_layerHandle.layer == null);
    _layerHandle.layer = rootLayer;
    assert(_needsPaint);
    owner!._nodesNeedingPaint.add(this);
  }

  /// Replace the layer. This is only valid for the root of a render
  /// object subtree (whatever object [scheduleInitialPaint] was
  /// called on).
  ///
  /// This might be called if, e.g., the device pixel ratio changed.
  void replaceRootLayer(OffsetLayer rootLayer) {
    assert(!_debugDisposed);
    assert(rootLayer.attached);
    assert(attached);
    assert(parent == null);
    assert(!owner!._debugDoingPaint);
    assert(isRepaintBoundary);
    assert(_layerHandle.layer != null); // use scheduleInitialPaint the first time
    _layerHandle.layer!.detach();
    _layerHandle.layer = rootLayer;
    markNeedsPaint();
  }

  void _paintWithContext(PaintingContext context, Offset offset) {
    assert(!_debugDisposed);
    assert(() {
      if (_debugDoingThisPaint) {
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('Tried to paint a RenderObject reentrantly.'),
          describeForError(
            'The following RenderObject was already being painted when it was '
            'painted again',
          ),
          ErrorDescription(
            'Since this typically indicates an infinite recursion, it is '
            'disallowed.',
          ),
        ]);
      }
      return true;
    }());
    // If we still need layout, then that means that we were skipped in the
    // layout phase and therefore don't need painting. We might not know that
    // yet (that is, our layer might not have been detached yet), because the
    // same node that skipped us in layout is above us in the tree (obviously)
    // and therefore may not have had a chance to paint yet (since the tree
    // paints in reverse order). In particular this will happen if they have
    // a different layer, because there's a repaint boundary between us.
    if (_needsLayout) {
      return;
    }
    if (!kReleaseMode && debugProfilePaintsEnabled) {
      Map<String, String>? debugTimelineArguments;
      assert(() {
        if (debugEnhancePaintTimelineArguments) {
          debugTimelineArguments = toDiagnosticsNode().toTimelineArguments();
        }
        return true;
      }());
      FlutterTimeline.startSync('$runtimeType', arguments: debugTimelineArguments);
    }
    assert(() {
      if (_needsCompositingBitsUpdate) {
        final RenderObject? parent = this.parent;
        if (parent != null) {
          var visitedByParent = false;
          parent.visitChildren((RenderObject child) {
            if (child == this) {
              visitedByParent = true;
            }
          });
          if (!visitedByParent) {
            throw FlutterError.fromParts(<DiagnosticsNode>[
              ErrorSummary(
                "A RenderObject was not visited by the parent's visitChildren "
                'during paint.',
              ),
              parent.describeForError('The parent was'),
              describeForError('The child that was not visited was'),
              ErrorDescription(
                'A RenderObject with children must implement visitChildren and '
                'call the visitor exactly once for each child; it also should not '
                'paint children that were removed with dropChild.',
              ),
              ErrorHint('This usually indicates an error in the Flutter framework itself.'),
            ]);
          }
        }
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary(
            'Tried to paint a RenderObject before its compositing bits were '
            'updated.',
          ),
          describeForError(
            'The following RenderObject was marked as having dirty compositing '
            'bits at the time that it was painted',
          ),
          ErrorDescription(
            'A RenderObject that still has dirty compositing bits cannot be '
            'painted because this indicates that the tree has not yet been '
            'properly configured for creating the layer tree.',
          ),
          ErrorHint('This usually indicates an error in the Flutter framework itself.'),
        ]);
      }
      return true;
    }());
    RenderObject? debugLastActivePaint;
    assert(() {
      _debugDoingThisPaint = true;
      debugLastActivePaint = _debugActivePaint;
      _debugActivePaint = this;
      assert(!isRepaintBoundary || _layerHandle.layer != null);
      return true;
    }());
    _needsPaint = false;
    _needsCompositedLayerUpdate = false;
    _wasRepaintBoundary = isRepaintBoundary;
    try {
      paint(context, offset);
      assert(!_needsLayout); // check that the paint() method didn't mark us dirty again
      assert(!_needsPaint); // check that the paint() method didn't mark us dirty again
    } catch (e, stack) {
      _reportException('paint', e, stack);
    }
    assert(() {
      debugPaint(context, offset);
      _debugActivePaint = debugLastActivePaint;
      _debugDoingThisPaint = false;
      return true;
    }());
    if (!kReleaseMode && debugProfilePaintsEnabled) {
      FlutterTimeline.finishSync();
    }
  }

  /// An estimate of the bounds within which this render object will paint.
  /// Useful for debugging flags such as [debugPaintLayerBordersEnabled].
  ///
  /// These are also the bounds used by [showOnScreen] to make a [RenderObject]
  /// visible on screen.
  Rect get paintBounds;

  /// Override this method to paint debugging information.
  void debugPaint(PaintingContext context, Offset offset) {}

  /// Paint this render object into the given context at the given offset.
  ///
  /// Subclasses should override this method to provide a visual appearance
  /// for themselves. The render object's local coordinate system is
  /// axis-aligned with the coordinate system of the context's canvas and the
  /// render object's local origin (i.e, x=0 and y=0) is placed at the given
  /// offset in the context's canvas.
  ///
  /// Do not call this function directly. If you wish to paint yourself, call
  /// [markNeedsPaint] instead to schedule a call to this function. If you wish
  /// to paint one of your children, call [PaintingContext.paintChild] on the
  /// given `context`.
  ///
  /// When painting one of your children (via a paint child function on the
  /// given context), the current canvas held by the context might change
  /// because draw operations before and after painting children might need to
  /// be recorded on separate compositing layers.
  void paint(PaintingContext context, Offset offset) {}

  /// Applies the transform that would be applied when painting the given child
  /// to the given matrix.
  ///
  /// Used by coordinate conversion functions ([getTransformTo], for example) to
  /// translate coordinates local to one render object into coordinates local to
  /// another render object.
  ///
  /// Some RenderObjects will provide a zeroed out matrix in this method,
  /// indicating that the child should not paint anything or respond to hit
  /// tests currently. A parent may supply a non-zero matrix even though it
  /// does not paint its child currently, for example if the parent is a
  /// [RenderOffstage] with `offstage` set to true. In both of these cases,
  /// the parent must return `false` from [paintsChild].
  void applyPaintTransform(covariant RenderObject child, Matrix4 transform) {
    assert(child.parent == this);
  }

  /// Whether the given child would be painted if [paint] were called.
  ///
  /// Some RenderObjects skip painting their children if they are configured to
  /// not produce any visible effects. For example, a [RenderOffstage] with
  /// its `offstage` property set to true, or a [RenderOpacity] with its opacity
  /// value set to zero.
  ///
  /// In these cases, the parent may still supply a non-zero matrix in
  /// [applyPaintTransform] to inform callers about where it would paint the
  /// child if the child were painted at all. Alternatively, the parent may
  /// supply a zeroed out matrix if it would not otherwise be able to determine
  /// a valid matrix for the child and thus cannot meaningfully determine where
  /// the child would paint.
  bool paintsChild(covariant RenderObject child) {
    assert(child.parent == this);
    return true;
  }

  /// {@template flutter.rendering.RenderObject.getTransformTo}
  /// Applies the paint transform from this [RenderObject] to the `target`
  /// [RenderObject].
  ///
  /// Returns a matrix that maps the local paint coordinate system to the
  /// coordinate system of `target`, or a [Matrix4.zero] if the paint transform
  /// can not be computed.
  ///
  /// This method throws an exception when the `target` is not in the same render
  /// tree as this [RenderObject], as the behavior is undefined.
  ///
  /// This method ignores [RenderObject.paintsChild]. This means it will still
  /// try to compute the paint transform even if this [RenderObject] or
  /// `target` is currently not visible.
  ///
  /// If `target` is null, this method returns a matrix that maps from the
  /// local paint coordinate system to the coordinate system of the
  /// [PipelineOwner.rootNode].
  /// {@endtemplate}
  ///
  /// For the render tree owned by the [RendererBinding] (i.e. for the main
  /// render tree displayed on the device) this means that this method maps to
  /// the global coordinate system in logical pixels. To get physical pixels,
  /// use [applyPaintTransform] from the [RenderView] to further transform the
  /// coordinate.
  Matrix4 getTransformTo(RenderObject? target) {
    assert(attached);
    // The paths from to fromRenderObject and toRenderObject's common ancestor.
    // Each list's length is greater than 1 if not null.
    //
    // [this, ...., commonAncestorRenderObject], or null if `this` is the common
    // ancestor.
    List<RenderObject>? fromPath;
    // [target, ...., commonAncestorRenderObject], or null if `target` is the
    // common ancestor.
    List<RenderObject>? toPath;

    var from = this;
    RenderObject to = target ?? owner!.rootNode!;

    while (!identical(from, to)) {
      final int fromDepth = from.depth;
      final int toDepth = to.depth;

      if (fromDepth >= toDepth) {
        final RenderObject fromParent =
            from.parent ??
            (throw FlutterError('$target and $this are not in the same render tree.'));
        (fromPath ??= <RenderObject>[this]).add(fromParent);
        from = fromParent;
      }
      if (fromDepth <= toDepth) {
        final RenderObject toParent =
            to.parent ?? (throw FlutterError('$target and $this are not in the same render tree.'));
        assert(
          target != null,
          '$this has a depth that is less than or equal to ${owner?.rootNode}',
        );
        (toPath ??= <RenderObject>[target!]).add(toParent);
        to = toParent;
      }
    }

    Matrix4? fromTransform;
    if (fromPath != null) {
      assert(fromPath.length > 1);
      fromTransform = Matrix4.identity();
      final int lastIndex = target == null ? fromPath.length - 2 : fromPath.length - 1;
      for (var index = lastIndex; index > 0; index -= 1) {
        fromPath[index].applyPaintTransform(fromPath[index - 1], fromTransform);
      }
    }
    if (toPath == null) {
      return fromTransform ?? Matrix4.identity();
    }

    assert(toPath.length > 1);
    final toTransform = Matrix4.identity();
    for (int index = toPath.length - 1; index > 0; index -= 1) {
      toPath[index].applyPaintTransform(toPath[index - 1], toTransform);
    }
    if (toTransform.invert() == 0) {
      // If the matrix is singular then `invert()` doesn't do anything.
      return Matrix4.zero();
    }
    return (fromTransform?..multiply(toTransform)) ?? toTransform;
  }

  /// Returns a rect in this object's coordinate system that describes
  /// the approximate bounding box of the clip rect that would be
  /// applied to the given child during the paint phase, if any.
  ///
  /// Returns null if the child would not be clipped.
  ///
  /// This is used in the semantics phase to avoid including children
  /// that are not physically visible.
  ///
  /// RenderObjects that respect a [Clip] behavior when painting _must_ respect
  /// that same behavior when describing this value. For example, if passing
  /// [Clip.none] to [PaintingContext.pushClipRect] as the `clipBehavior`, then
  /// the implementation of this method must return null.
  Rect? describeApproximatePaintClip(covariant RenderObject child) => null;

  /// Returns a rect in this object's coordinate system that describes
  /// which [SemanticsNode]s produced by the `child` should be included in the
  /// semantics tree. [SemanticsNode]s from the `child` that are positioned
  /// outside of this rect will be dropped. Child [SemanticsNode]s that are
  /// positioned inside this rect, but outside of [describeApproximatePaintClip]
  /// will be included in the tree marked as hidden. Child [SemanticsNode]s
  /// that are inside of both rect will be included in the tree as regular
  /// nodes.
  ///
  /// This method only returns a non-null value if the semantics clip rect
  /// is different from the rect returned by [describeApproximatePaintClip].
  /// If the semantics clip rect and the paint clip rect are the same, this
  /// method returns null.
  ///
  /// A viewport would typically implement this method to include semantic nodes
  /// in the semantics tree that are currently hidden just before the leading
  /// or just after the trailing edge. These nodes have to be included in the
  /// semantics tree to implement implicit accessibility scrolling on iOS where
  /// the viewport scrolls implicitly when moving the accessibility focus from
  /// the last visible node in the viewport to the first hidden one.
  ///
  /// See also:
  ///
  /// * [RenderViewportBase.cacheExtent], used by viewports to extend their
  ///   semantics clip beyond their approximate paint clip.
  Rect? describeSemanticsClip(covariant RenderObject? child) => null;

  // SEMANTICS

  /// Bootstrap the semantics reporting mechanism by marking this node
  /// as needing a semantics update.
  ///
  /// Requires that this render object is attached, and is the root of
  /// the render tree.
  ///
  /// See [RendererBinding] for an example of how this function is used.
  void scheduleInitialSemantics() {
    assert(!_debugDisposed);
    assert(attached);
    assert(parent == null);
    assert(!owner!._debugDoingSemantics);
    assert(_semantics.parentDataDirty || !_semantics.built);
    assert(owner!._semanticsOwner != null);
    owner!._nodesNeedingSemantics.add(this);
    owner!.requestVisualUpdate();
  }

  /// Report the semantics of this node, for example for accessibility purposes.
  ///
  /// This method should be overridden by subclasses that have interesting
  /// semantic information.
  ///
  /// The given [SemanticsConfiguration] object is mutable and should be
  /// annotated in a manner that describes the current state. No reference
  /// should be kept to that object; mutating it outside of the context of the
  /// [describeSemanticsConfiguration] call (for example as a result of
  /// asynchronous computation) will at best have no useful effect and at worse
  /// will cause crashes as the data will be in an inconsistent state.
  ///
  /// {@tool snippet}
  ///
  /// The following snippet will describe the node as a button that responds to
  /// tap actions.
  ///
  /// ```dart
  /// abstract class SemanticButtonRenderObject extends RenderObject {
  ///   @override
  ///   void describeSemanticsConfiguration(SemanticsConfiguration config) {
  ///     super.describeSemanticsConfiguration(config);
  ///     config
  ///       ..onTap = _handleTap
  ///       ..label = 'I am a button'
  ///       ..isButton = true;
  ///   }
  ///
  ///   void _handleTap() {
  ///     // Do something.
  ///   }
  /// }
  /// ```
  /// {@end-tool}
  @protected
  void describeSemanticsConfiguration(SemanticsConfiguration config) {
    // Nothing to do by default.
  }

  /// Sends a [SemanticsEvent] associated with this render object's [SemanticsNode].
  ///
  /// If this render object has no semantics information, the first parent
  /// render object with a non-null semantic node is used.
  ///
  /// If semantics are disabled, no events are dispatched.
  ///
  /// See [SemanticsNode.sendEvent] for a full description of the behavior.
  void sendSemanticsEvent(SemanticsEvent semanticsEvent) {
    if (owner!.semanticsOwner == null) {
      return;
    }
    final SemanticsNode? node = _semantics.cachedSemanticsNode;
    if (node != null && !node.isMergedIntoParent) {
      node.sendEvent(semanticsEvent);
    } else if (parent != null) {
      parent!.sendSemanticsEvent(semanticsEvent);
    }
  }

  /// The bounding box, in the local coordinate system, of this
  /// object, for accessibility purposes.
  Rect get semanticBounds;

  /// Whether the semantics of this render object is dirty and await the update.
  ///
  /// Always returns false in release mode.
  bool get debugNeedsSemanticsUpdate {
    if (kReleaseMode) {
      return false;
    }
    return _semantics.parentDataDirty;
  }

  /// The semantics of this render object.
  ///
  /// Exposed only for testing and debugging. To learn about the semantics of
  /// render objects in production, obtain a [SemanticsHandle] from
  /// [PipelineOwner.ensureSemantics].
  ///
  /// Only valid in debug and profile mode. In release builds, always returns
  /// null.
  SemanticsNode? get debugSemantics {
    // If _semantics.built is not true, the semantics node is an old cache and
    // is not on the semantics tree.
    if (!kReleaseMode && _semantics.built) {
      return _semantics.cachedSemanticsNode;
    }
    return null;
  }

  /// Removes all semantics from this render object and its descendants.
  ///
  /// Should only be called on objects whose [parent] is not a [RenderObject].
  ///
  /// Override this method if you instantiate new [SemanticsNode]s in an
  /// overridden [assembleSemanticsNode] method, to dispose of those nodes.
  @mustCallSuper
  void clearSemantics() {
    _semantics.clear();
    visitChildren((RenderObject child) {
      child.clearSemantics();
    });
  }

  /// Mark this node as needing an update to its semantics description.
  ///
  /// This must be called whenever the semantics configuration of this
  /// [RenderObject] as annotated by [describeSemanticsConfiguration] changes in
  /// any way to update the semantics tree.
  void markNeedsSemanticsUpdate() {
    assert(!_debugDisposed);
    assert(!attached || !owner!._debugDoingSemantics);
    if (!attached || owner!._semanticsOwner == null) {
      return;
    }
    _semantics.markNeedsUpdate();
  }

  late final _RenderObjectSemantics _semantics = _RenderObjectSemantics(this);

  /// Called when collecting the semantics of this node.
  ///
  /// The implementation has to return the children in paint order skipping all
  /// children that are not semantically relevant (e.g. because they are
  /// invisible).
  ///
  /// The default implementation mirrors the behavior of
  /// [visitChildren] (which is supposed to walk all the children).
  void visitChildrenForSemantics(RenderObjectVisitor visitor) {
    visitChildren(visitor);
  }

  /// Assemble the [SemanticsNode] for this [RenderObject].
  ///
  /// If [describeSemanticsConfiguration] sets
  /// [SemanticsConfiguration.isSemanticBoundary] to true, this method is called
  /// with the `node` created for this [RenderObject], the `config` to be
  /// applied to that node and the `children` [SemanticsNode]s that descendants
  /// of this RenderObject have generated.
  ///
  /// By default, the method will annotate `node` with `config` and add the
  /// `children` to it.
  ///
  /// Subclasses can override this method to add additional [SemanticsNode]s
  /// to the tree. If new [SemanticsNode]s are instantiated in this method
  /// they must be disposed in [clearSemantics].
  void assembleSemanticsNode(
    SemanticsNode node,
    SemanticsConfiguration config,
    Iterable<SemanticsNode> children,
  ) {
    assert(node == _semantics.cachedSemanticsNode);
    // TODO(a14n): remove the following cast by updating type of parameter in either updateWith or assembleSemanticsNode
    node.updateWith(config: config, childrenInInversePaintOrder: children as List<SemanticsNode>);
  }

  // EVENTS

  /// Override this method to handle pointer events that hit this render object.
  @override
  void handleEvent(PointerEvent event, covariant HitTestEntry entry) {}

  // HIT TESTING

  // RenderObject subclasses are expected to have a method like the following
  // (with the signature being whatever passes for coordinates for this
  // particular class):
  //
  // bool hitTest(HitTestResult result, { required Offset position }) {
  //   // If the given position is not inside this node, then return false.
  //   // Otherwise:
  //   // For each child that intersects the position, in z-order starting from
  //   // the top, call hitTest() for that child, passing it /result/, and the
  //   // coordinates converted to the child's coordinate origin, and stop at
  //   // the first child that returns true.
  //   // Then, add yourself to /result/, and return true.
  // }
  //
  // If you add yourself to /result/ and still return false, then that means you
  // will see events but so will objects below you.

  /// Returns a human understandable name.
  @override
  String toStringShort() {
    String header = describeIdentity(this);
    if (!kReleaseMode) {
      if (_debugDisposed) {
        header += ' DISPOSED';
        return header;
      }

      var count = 0;
      for (
        RenderObject? node = this;
        node != null && !(node._isRelayoutBoundary ?? false);
        node = node.parent
      ) {
        if (node._isRelayoutBoundary == null) {
          count = -1;
          break;
        }
        count += 1;
      }
      if (count > 0) {
        header += ' relayoutBoundary=up$count';
      }
      if (_needsLayout) {
        header += ' NEEDS-LAYOUT';
      }
      if (_needsPaint) {
        header += ' NEEDS-PAINT';
      }
      if (_needsCompositingBitsUpdate) {
        header += ' NEEDS-COMPOSITING-BITS-UPDATE';
      }
      if (!attached) {
        header += ' DETACHED';
      }
    }
    return header;
  }

  @override
  String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) => toStringShort();

  /// Returns a description of the tree rooted at this node.
  /// If the prefix argument is provided, then every line in the output
  /// will be prefixed by that string.
  @override
  String toStringDeep({
    String prefixLineOne = '',
    String? prefixOtherLines = '',
    DiagnosticLevel minLevel = DiagnosticLevel.debug,
    int wrapWidth = 65,
  }) {
    return _withDebugActiveLayoutCleared(
      () => super.toStringDeep(
        prefixLineOne: prefixLineOne,
        prefixOtherLines: prefixOtherLines,
        minLevel: minLevel,
        wrapWidth: wrapWidth,
      ),
    );
  }

  /// Returns a one-line detailed description of the render object.
  /// This description is often somewhat long.
  ///
  /// This includes the same information for this RenderObject as given by
  /// [toStringDeep], but does not recurse to any children.
  @override
  String toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) {
    return _withDebugActiveLayoutCleared(
      () => super.toStringShallow(joiner: joiner, minLevel: minLevel),
    );
  }

  @protected
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(
      FlagProperty('needsCompositing', value: _needsCompositing, ifTrue: 'needs compositing'),
    );
    properties.add(
      DiagnosticsProperty<Object?>(
        'creator',
        debugCreator,
        defaultValue: null,
        level: DiagnosticLevel.debug,
      ),
    );
    properties.add(
      DiagnosticsProperty<ParentData>(
        'parentData',
        parentData,
        tooltip: (_debugCanParentUseSize ?? false) ? 'can use size' : null,
        missingIfNull: true,
      ),
    );
    properties.add(
      DiagnosticsProperty<Constraints>('constraints', _constraints, missingIfNull: true),
    );
    // don't access it via the "layer" getter since that's only valid when we don't need paint
    properties.add(
      DiagnosticsProperty<ContainerLayer>('layer', _layerHandle.layer, defaultValue: null),
    );
    properties.add(
      DiagnosticsProperty<SemanticsNode>('semantics node', debugSemantics, defaultValue: null),
    );
    properties.add(
      FlagProperty(
        'isBlockingSemanticsOfPreviouslyPaintedNodes',
        value: _semantics.configProvider.effective.isBlockingSemanticsOfPreviouslyPaintedNodes,
        ifTrue: 'blocks semantics of earlier render objects below the common boundary',
      ),
    );
    properties.add(
      FlagProperty(
        'isSemanticBoundary',
        value: _semantics.configProvider.effective.isSemanticBoundary,
        ifTrue: 'semantic boundary',
      ),
    );
  }

  @override
  List<DiagnosticsNode> debugDescribeChildren() => <DiagnosticsNode>[];

  /// Attempt to make (a portion of) this or a descendant [RenderObject] visible
  /// on screen.
  ///
  /// If `descendant` is provided, that [RenderObject] is made visible. If
  /// `descendant` is omitted, this [RenderObject] is made visible.
  ///
  /// The optional `rect` parameter describes which area of that [RenderObject]
  /// should be shown on screen. If `rect` is null, the entire
  /// [RenderObject] (as defined by its [paintBounds]) will be revealed. The
  /// `rect` parameter is interpreted relative to the coordinate system of
  /// `descendant` if that argument is provided and relative to this
  /// [RenderObject] otherwise.
  ///
  /// The `duration` parameter can be set to a non-zero value to bring the
  /// target object on screen in an animation defined by `curve`.
  ///
  /// See also:
  ///
  /// * [RenderViewportBase.showInViewport], which [RenderViewportBase] and
  ///   [SingleChildScrollView] delegate this method to.
  void showOnScreen({
    RenderObject? descendant,
    Rect? rect,
    Duration duration = Duration.zero,
    Curve curve = Curves.ease,
  }) {
    parent?.showOnScreen(
      descendant: descendant ?? this,
      rect: rect,
      duration: duration,
      curve: curve,
    );
  }

  /// Adds a debug representation of a [RenderObject] optimized for including in
  /// error messages.
  ///
  /// The default [style] of [DiagnosticsTreeStyle.shallow] ensures that all of
  /// the properties of the render object are included in the error output but
  /// none of the children of the object are.
  ///
  /// You should always include a RenderObject in an error message if it is the
  /// [RenderObject] causing the failure or contract violation of the error.
  DiagnosticsNode describeForError(
    String name, {
    DiagnosticsTreeStyle style = DiagnosticsTreeStyle.shallow,
  }) {
    return toDiagnosticsNode(name: name, style: style);
  }
}

/// Generic mixin for render objects with one child.
///
/// Provides a child model for a render object subclass that has
/// a unique child, which is accessible via the [child] getter.
///
/// This mixin is typically used to implement render objects created
/// in a [SingleChildRenderObjectWidget].
mixin RenderObjectWithChildMixin<ChildType extends RenderObject> on RenderObject {
  /// Checks whether the given render object has the correct [runtimeType] to be
  /// a child of this render object.
  ///
  /// Does nothing if assertions are disabled.
  ///
  /// Always returns true.
  bool debugValidateChild(RenderObject child) {
    assert(() {
      if (child is! ChildType) {
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary(
            'A $runtimeType expected a child of type $ChildType but received a '
            'child of type ${child.runtimeType}.',
          ),
          ErrorDescription(
            'RenderObjects expect specific types of children because they '
            'coordinate with their children during layout and paint. For '
            'example, a RenderSliver cannot be the child of a RenderBox because '
            'a RenderSliver does not understand the RenderBox layout protocol.',
          ),
          ErrorSpacer(),
          DiagnosticsProperty<Object?>(
            'The $runtimeType that expected a $ChildType child was created by',
            debugCreator,
            style: DiagnosticsTreeStyle.errorProperty,
          ),
          ErrorSpacer(),
          DiagnosticsProperty<Object?>(
            'The ${child.runtimeType} that did not match the expected child type '
            'was created by',
            child.debugCreator,
            style: DiagnosticsTreeStyle.errorProperty,
          ),
        ]);
      }
      return true;
    }());
    return true;
  }

  ChildType? _child;

  /// The render object's unique child.
  ChildType? get child => _child;
  set child(ChildType? value) {
    if (_child != null) {
      dropChild(_child!);
    }
    _child = value;
    if (_child != null) {
      adoptChild(_child!);
    }
  }

  @override
  void attach(PipelineOwner owner) {
    super.attach(owner);
    _child?.attach(owner);
  }

  @override
  void detach() {
    super.detach();
    _child?.detach();
  }

  @override
  void redepthChildren() {
    if (_child != null) {
      redepthChild(_child!);
    }
  }

  @override
  void visitChildren(RenderObjectVisitor visitor) {
    if (_child != null) {
      visitor(_child!);
    }
  }

  @override
  List<DiagnosticsNode> debugDescribeChildren() {
    return child != null
        ? <DiagnosticsNode>[child!.toDiagnosticsNode(name: 'child')]
        : <DiagnosticsNode>[];
  }
}

/// A mixin for managing [RenderObject] with a [layoutCallback], which will be
/// invoked during this [RenderObject]'s layout process if scheduled using
/// [scheduleLayoutCallback].
///
/// A layout callback is typically a callback that mutates the [RenderObject]'s
/// render subtree during the [RenderObject]'s layout process. When an ancestor
/// [RenderObject] chooses to skip laying out this [RenderObject] in its
/// [performLayout] implementation (for example, for performance reasons, an
/// [Overlay] may skip laying out an offstage [OverlayEntry] while keeping it in
/// the tree), normally the [layoutCallback] will not be invoked because the
/// [layout] method will not be called. This can be undesirable when the
/// [layoutCallback] involves rebuilding dirty widgets (most notably, the
/// [LayoutBuilder] widget). Unlike render subtrees, typically all dirty widgets
/// (even off-screen ones) in a widget tree must be rebuilt. This mixin makes
/// sure once scheduled, the [layoutCallback] method will be invoked even if it's
/// skipped by an ancestor [RenderObject], unless this [RenderObject] has never
/// been laid out.
///
/// Subclasses must not invoke the layout callback directly. Instead, call
/// [runLayoutCallback] in the [performLayout] implementation.
///
/// See also:
///
///  * [LayoutBuilder] and [SliverLayoutBuilder], which use the mixin.
mixin RenderObjectWithLayoutCallbackMixin on RenderObject {
  // The initial value of this flag must be set to true to prevent the layout
  // callback from being scheduled when the subtree has never been laid out (in
  // which case the `constraints` or any other layout information is unknown).
  bool _needsRebuild = true;

  /// The layout callback to be invoked during [performLayout].
  ///
  /// This method should not be invoked directly. Instead, call
  /// [runLayoutCallback] in the [performLayout] implementation. This callback
  /// will be invoked using [invokeLayoutCallback].
  @visibleForOverriding
  void layoutCallback();

  /// Invokes [layoutCallback] with [invokeLayoutCallback].
  ///
  /// This method must be called in [performLayout], typically as early as
  /// possible before any layout work is done, to avoid re-dirtying any child
  /// [RenderObject]s.
  @mustCallSuper
  void runLayoutCallback() {
    assert(debugDoingThisLayout);
    invokeLayoutCallback((_) => layoutCallback());
    _needsRebuild = false;
  }

  /// Informs the framework that the layout callback has been updated and must be
  /// invoked again when this [RenderObject] is ready for layout, even when an
  /// ancestor [RenderObject] chooses to skip laying out this render subtree.
  @mustCallSuper
  void scheduleLayoutCallback() {
    if (_needsRebuild) {
      assert(debugNeedsLayout);
      return;
    }
    _needsRebuild = true;
    // This ensures that the layout callback will be run even if an ancestor
    // chooses to not lay out this subtree (for example, obstructed OverlayEntries
    // with `maintainState` set to true), to maintain the widget tree integrity
    // (making sure global keys are unique, for example).
    owner?._nodesNeedingLayout.add(this);
    // In an active tree, markNeedsLayout is needed to inform the layout boundary
    // that its child size may change.
    super.markNeedsLayout();
  }
}

/// Parent data to support a doubly-linked list of children.
///
/// The children can be traversed using [nextSibling] or [previousSibling],
/// which can be called on the parent data of the render objects
/// obtained via [ContainerRenderObjectMixin.firstChild] or
/// [ContainerRenderObjectMixin.lastChild].
mixin ContainerParentDataMixin<ChildType extends RenderObject> on ParentData {
  /// The previous sibling in the parent's child list.
  ChildType? previousSibling;

  /// The next sibling in the parent's child list.
  ChildType? nextSibling;

  /// Clear the sibling pointers.
  @override
  void detach() {
    assert(
      previousSibling == null,
      'Pointers to siblings must be nulled before detaching ParentData.',
    );
    assert(nextSibling == null, 'Pointers to siblings must be nulled before detaching ParentData.');
    super.detach();
  }
}

/// Generic mixin for render objects with a list of children.
///
/// Provides a child model for a render object subclass that has a doubly-linked
/// list of children.
///
/// The [ChildType] specifies the type of the children (extending [RenderObject]),
/// e.g. [RenderBox].
///
/// [ParentDataType] stores parent container data on its child render objects.
/// It must extend [ContainerParentDataMixin], which provides the interface
/// for visiting children. This data is populated by
/// [RenderObject.setupParentData] implemented by the class using this mixin.
///
/// When using [RenderBox] as the child type, you will usually want to make use of
/// [RenderBoxContainerDefaultsMixin] and extend [ContainerBoxParentData] for the
/// parent data.
///
/// Moreover, this is a required mixin for render objects returned to [MultiChildRenderObjectWidget].
///
/// See also:
///
///  * [SlottedContainerRenderObjectMixin], which organizes its children
///    in different named slots.
mixin ContainerRenderObjectMixin<
  ChildType extends RenderObject,
  ParentDataType extends ContainerParentDataMixin<ChildType>
>
    on RenderObject {
  bool _debugUltimatePreviousSiblingOf(ChildType child, {ChildType? equals}) {
    var childParentData = child.parentData! as ParentDataType;
    while (childParentData.previousSibling != null) {
      assert(childParentData.previousSibling != child);
      child = childParentData.previousSibling!;
      childParentData = child.parentData! as ParentDataType;
    }
    return child == equals;
  }

  bool _debugUltimateNextSiblingOf(ChildType child, {ChildType? equals}) {
    var childParentData = child.parentData! as ParentDataType;
    while (childParentData.nextSibling != null) {
      assert(childParentData.nextSibling != child);
      child = childParentData.nextSibling!;
      childParentData = child.parentData! as ParentDataType;
    }
    return child == equals;
  }

  int _childCount = 0;

  /// The number of children.
  int get childCount => _childCount;

  /// Checks whether the given render object has the correct [runtimeType] to be
  /// a child of this render object.
  ///
  /// Does nothing if assertions are disabled.
  ///
  /// Always returns true.
  bool debugValidateChild(RenderObject child) {
    assert(() {
      if (child is! ChildType) {
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary(
            'A $runtimeType expected a child of type $ChildType but received a '
            'child of type ${child.runtimeType}.',
          ),
          ErrorDescription(
            'RenderObjects expect specific types of children because they '
            'coordinate with their children during layout and paint. For '
            'example, a RenderSliver cannot be the child of a RenderBox because '
            'a RenderSliver does not understand the RenderBox layout protocol.',
          ),
          ErrorSpacer(),
          DiagnosticsProperty<Object?>(
            'The $runtimeType that expected a $ChildType child was created by',
            debugCreator,
            style: DiagnosticsTreeStyle.errorProperty,
          ),
          ErrorSpacer(),
          DiagnosticsProperty<Object?>(
            'The ${child.runtimeType} that did not match the expected child type '
            'was created by',
            child.debugCreator,
            style: DiagnosticsTreeStyle.errorProperty,
          ),
        ]);
      }
      return true;
    }());
    return true;
  }

  ChildType? _firstChild;
  ChildType? _lastChild;
  void _insertIntoChildList(ChildType child, {ChildType? after}) {
    final childParentData = child.parentData! as ParentDataType;
    assert(childParentData.nextSibling == null);
    assert(childParentData.previousSibling == null);
    _childCount += 1;
    assert(_childCount > 0);
    if (after == null) {
      // insert at the start (_firstChild)
      childParentData.nextSibling = _firstChild;
      if (_firstChild != null) {
        final firstChildParentData = _firstChild!.parentData! as ParentDataType;
        firstChildParentData.previousSibling = child;
      }
      _firstChild = child;
      _lastChild ??= child;
    } else {
      assert(_firstChild != null);
      assert(_lastChild != null);
      assert(_debugUltimatePreviousSiblingOf(after, equals: _firstChild));
      assert(_debugUltimateNextSiblingOf(after, equals: _lastChild));
      final afterParentData = after.parentData! as ParentDataType;
      if (afterParentData.nextSibling == null) {
        // insert at the end (_lastChild); we'll end up with two or more children
        assert(after == _lastChild);
        childParentData.previousSibling = after;
        afterParentData.nextSibling = child;
        _lastChild = child;
      } else {
        // insert in the middle; we'll end up with three or more children
        // set up links from child to siblings
        childParentData.nextSibling = afterParentData.nextSibling;
        childParentData.previousSibling = after;
        // set up links from siblings to child
        final childPreviousSiblingParentData =
            childParentData.previousSibling!.parentData! as ParentDataType;
        final childNextSiblingParentData =
            childParentData.nextSibling!.parentData! as ParentDataType;
        childPreviousSiblingParentData.nextSibling = child;
        childNextSiblingParentData.previousSibling = child;
        assert(afterParentData.nextSibling == child);
      }
    }
  }

  /// Insert child into this render object's child list after the given child.
  ///
  /// If `after` is null, then this inserts the child at the start of the list,
  /// and the child becomes the new [firstChild].
  void insert(ChildType child, {ChildType? after}) {
    assert(child != this, 'A RenderObject cannot be inserted into itself.');
    assert(
      after != this,
      'A RenderObject cannot simultaneously be both the parent and the sibling of another RenderObject.',
    );
    assert(child != after, 'A RenderObject cannot be inserted after itself.');
    assert(child != _firstChild);
    assert(child != _lastChild);
    adoptChild(child);
    assert(
      child.parentData is ParentDataType,
      'A child of $runtimeType has parentData of type ${child.parentData.runtimeType}, '
      'which does not conform to $ParentDataType. Class using ContainerRenderObjectMixin '
      'should override setupParentData() to set parentData to type $ParentDataType.',
    );
    _insertIntoChildList(child, after: after);
  }

  /// Append child to the end of this render object's child list.
  void add(ChildType child) {
    insert(child, after: _lastChild);
  }

  /// Add all the children to the end of this render object's child list.
  void addAll(List<ChildType>? children) {
    children?.forEach(add);
  }

  void _removeFromChildList(ChildType child) {
    final childParentData = child.parentData! as ParentDataType;
    assert(_debugUltimatePreviousSiblingOf(child, equals: _firstChild));
    assert(_debugUltimateNextSiblingOf(child, equals: _lastChild));
    assert(_childCount >= 0);
    if (childParentData.previousSibling == null) {
      assert(_firstChild == child);
      _firstChild = childParentData.nextSibling;
    } else {
      final childPreviousSiblingParentData =
          childParentData.previousSibling!.parentData! as ParentDataType;
      childPreviousSiblingParentData.nextSibling = childParentData.nextSibling;
    }
    if (childParentData.nextSibling == null) {
      assert(_lastChild == child);
      _lastChild = childParentData.previousSibling;
    } else {
      final childNextSiblingParentData = childParentData.nextSibling!.parentData! as ParentDataType;
      childNextSiblingParentData.previousSibling = childParentData.previousSibling;
    }
    childParentData.previousSibling = null;
    childParentData.nextSibling = null;
    _childCount -= 1;
  }

  /// Remove this child from the child list.
  ///
  /// Requires the child to be present in the child list.
  void remove(ChildType child) {
    _removeFromChildList(child);
    dropChild(child);
  }

  /// Remove all their children from this render object's child list.
  ///
  /// More efficient than removing them individually.
  void removeAll() {
    ChildType? child = _firstChild;
    while (child != null) {
      final childParentData = child.parentData! as ParentDataType;
      final ChildType? next = childParentData.nextSibling;
      childParentData.previousSibling = null;
      childParentData.nextSibling = null;
      dropChild(child);
      child = next;
    }
    _firstChild = null;
    _lastChild = null;
    _childCount = 0;
  }

  /// Move the given `child` in the child list to be after another child.
  ///
  /// More efficient than removing and re-adding the child. Requires the child
  /// to already be in the child list at some position. Pass null for `after` to
  /// move the child to the start of the child list.
  void move(ChildType child, {ChildType? after}) {
    assert(child != this);
    assert(after != this);
    assert(child != after);
    assert(child.parent == this);
    final childParentData = child.parentData! as ParentDataType;
    if (childParentData.previousSibling == after) {
      return;
    }
    _removeFromChildList(child);
    _insertIntoChildList(child, after: after);
    markNeedsLayout();
  }

  @override
  void attach(PipelineOwner owner) {
    super.attach(owner);
    ChildType? child = _firstChild;
    while (child != null) {
      child.attach(owner);
      final childParentData = child.parentData! as ParentDataType;
      child = childParentData.nextSibling;
    }
  }

  @override
  void detach() {
    super.detach();
    ChildType? child = _firstChild;
    while (child != null) {
      child.detach();
      final childParentData = child.parentData! as ParentDataType;
      child = childParentData.nextSibling;
    }
  }

  @override
  void redepthChildren() {
    ChildType? child = _firstChild;
    while (child != null) {
      redepthChild(child);
      final childParentData = child.parentData! as ParentDataType;
      child = childParentData.nextSibling;
    }
  }

  @override
  void visitChildren(RenderObjectVisitor visitor) {
    ChildType? child = _firstChild;
    while (child != null) {
      visitor(child);
      final childParentData = child.parentData! as ParentDataType;
      child = childParentData.nextSibling;
    }
  }

  /// The first child in the child list.
  ChildType? get firstChild => _firstChild;

  /// The last child in the child list.
  ChildType? get lastChild => _lastChild;

  /// The previous child before the given child in the child list.
  ChildType? childBefore(ChildType child) {
    assert(child.parent == this);
    final childParentData = child.parentData! as ParentDataType;
    return childParentData.previousSibling;
  }

  /// The next child after the given child in the child list.
  ChildType? childAfter(ChildType child) {
    assert(child.parent == this);
    final childParentData = child.parentData! as ParentDataType;
    return childParentData.nextSibling;
  }

  @override
  List<DiagnosticsNode> debugDescribeChildren() {
    final children = <DiagnosticsNode>[];
    if (firstChild != null) {
      ChildType child = firstChild!;
      var count = 1;
      while (true) {
        children.add(child.toDiagnosticsNode(name: 'child $count'));
        if (child == lastChild) {
          break;
        }
        count += 1;
        final childParentData = child.parentData! as ParentDataType;
        child = childParentData.nextSibling!;
      }
    }
    return children;
  }
}

/// Mixin for [RenderObject] that will call [systemFontsDidChange] whenever the
/// system fonts change.
///
/// System fonts can change when the OS installs or removes a font. Use this
/// mixin if the [RenderObject] uses [TextPainter] or [Paragraph] to correctly
/// update the text when it happens.
mixin RelayoutWhenSystemFontsChangeMixin on RenderObject {
  /// A callback that is called when system fonts have changed.
  ///
  /// The framework defers the invocation of the callback to the
  /// [SchedulerPhase.transientCallbacks] phase to ensure that the
  /// [RenderObject]'s text layout is still valid when user interactions are in
  /// progress (which usually take place during the [SchedulerPhase.idle] phase).
  ///
  /// By default, [markNeedsLayout] is called on the [RenderObject]
  /// implementing this mixin.
  ///
  /// Subclass should override this method to clear any extra cache that depend
  /// on font-related metrics.
  @protected
  @mustCallSuper
  void systemFontsDidChange() {
    markNeedsLayout();
  }

  bool _hasPendingSystemFontsDidChangeCallBack = false;
  void _scheduleSystemFontsUpdate() {
    assert(
      SchedulerBinding.instance.schedulerPhase == SchedulerPhase.idle,
      '${objectRuntimeType(this, "RelayoutWhenSystemFontsChangeMixin")}._scheduleSystemFontsUpdate() '
      'called during ${SchedulerBinding.instance.schedulerPhase}.',
    );
    if (_hasPendingSystemFontsDidChangeCallBack) {
      return;
    }
    _hasPendingSystemFontsDidChangeCallBack = true;
    SchedulerBinding.instance.scheduleFrameCallback((Duration timeStamp) {
      assert(_hasPendingSystemFontsDidChangeCallBack);
      _hasPendingSystemFontsDidChangeCallBack = false;
      assert(
        attached || (debugDisposed ?? true),
        '$this is detached during ${SchedulerBinding.instance.schedulerPhase} but is not disposed.',
      );
      if (attached) {
        systemFontsDidChange();
      }
    });
  }

  @override
  void attach(PipelineOwner owner) {
    super.attach(owner);
    // If there's a pending callback that would imply this node was detached
    // between the idle phase and the next transientCallbacks phase. The tree
    // can not be mutated between those two phases so that should never happen.
    assert(!_hasPendingSystemFontsDidChangeCallBack);
    PaintingBinding.instance.systemFonts.addListener(_scheduleSystemFontsUpdate);
  }

  @override
  void detach() {
    assert(!_hasPendingSystemFontsDidChangeCallBack);
    PaintingBinding.instance.systemFonts.removeListener(_scheduleSystemFontsUpdate);
    super.detach();
  }
}

/// A mixin for [RenderObject]s that want to annotate the [SemanticsNode]
/// for their subtree.
mixin SemanticsAnnotationsMixin on RenderObject {
  /// Initializes the semantics annotations for this mixin.
  // Parameters added to this method should be marked as required to ensure
  // callers of the method provide a value.
  void initSemanticsAnnotations({
    required SemanticsProperties properties,
    required bool container,
    required bool explicitChildNodes,
    required bool excludeSemantics,
    required bool blockUserActions,
    required Locale? localeForSubtree,
    required TextDirection? textDirection,
  }) {
    _properties = properties;
    _container = container;
    _explicitChildNodes = explicitChildNodes;
    _excludeSemantics = excludeSemantics;
    _blockUserActions = blockUserActions;
    _localeForSubtree = localeForSubtree;
    _textDirection = textDirection;
    _updateAttributedFields(_properties);
  }

  /// All of the [SemanticsProperties] for this [SemanticsAnnotationsMixin].
  SemanticsProperties get properties => _properties;
  late SemanticsProperties _properties;
  set properties(SemanticsProperties value) {
    if (_properties == value) {
      return;
    }
    _properties = value;
    _updateAttributedFields(_properties);
    markNeedsSemanticsUpdate();
  }

  /// If 'container' is true, this [RenderObject] will introduce a new
  /// node in the semantics tree. Otherwise, the semantics will be
  /// merged with the semantics of any ancestors.
  ///
  /// Whether descendants of this [RenderObject] can add their semantic information
  /// to the [SemanticsNode] introduced by this configuration is controlled by
  /// [explicitChildNodes].
  bool get container => _container;
  late bool _container;
  set container(bool value) {
    if (container == value) {
      return;
    }
    _container = value;
    markNeedsSemanticsUpdate();
  }

  /// Whether descendants of this [RenderObject] are allowed to add semantic
  /// information to the [SemanticsNode] annotated by this widget.
  ///
  /// When set to false descendants are allowed to annotate [SemanticsNode]s of
  /// their parent with the semantic information they want to contribute to the
  /// semantic tree.
  /// When set to true the only way for descendants to contribute semantic
  /// information to the semantic tree is to introduce new explicit
  /// [SemanticsNode]s to the tree.
  ///
  /// This setting is often used in combination with
  /// [SemanticsConfiguration.isSemanticBoundary] to create semantic boundaries
  /// that are either writable or not for children.
  bool get explicitChildNodes => _explicitChildNodes;
  late bool _explicitChildNodes;
  set explicitChildNodes(bool value) {
    if (_explicitChildNodes == value) {
      return;
    }
    _explicitChildNodes = value;
    markNeedsSemanticsUpdate();
  }

  /// Whether descendants of this [RenderObject] should have their semantic
  /// information ignored.
  ///
  /// When this flag is set to true, all child semantics nodes are ignored.
  /// This can be used as a convenience for cases where a child is wrapped in
  /// an [ExcludeSemantics] widget and then another [Semantics] widget.
  bool get excludeSemantics => _excludeSemantics;
  late bool _excludeSemantics;
  set excludeSemantics(bool value) {
    if (_excludeSemantics == value) {
      return;
    }
    _excludeSemantics = value;
    markNeedsSemanticsUpdate();
  }

  /// Whether to block user interactions for the semantics subtree.
  ///
  /// Setting this true prevents user from activating pointer related
  /// [SemanticsAction]s, such as [SemanticsAction.tap] or
  /// [SemanticsAction.longPress].
  bool get blockUserActions => _blockUserActions;
  late bool _blockUserActions;
  set blockUserActions(bool value) {
    if (_blockUserActions == value) {
      return;
    }
    _blockUserActions = value;
    markNeedsSemanticsUpdate();
  }

  /// The [Locale] for the semantics subtree.
  ///
  /// Setting this to null will inherit locale from ancestor semantics node.
  Locale? get localeForSubtree => _localeForSubtree;
  Locale? _localeForSubtree;
  set localeForSubtree(Locale? value) {
    if (_localeForSubtree == value) {
      return;
    }
    _localeForSubtree = value;
    markNeedsSemanticsUpdate();
  }

  void _updateAttributedFields(SemanticsProperties value) {
    _attributedLabel = _effectiveAttributedLabel(value);
    _attributedValue = _effectiveAttributedValue(value);
    _attributedIncreasedValue = _effectiveAttributedIncreasedValue(value);
    _attributedDecreasedValue = _effectiveAttributedDecreasedValue(value);
    _attributedHint = _effectiveAttributedHint(value);
  }

  AttributedString? _effectiveAttributedLabel(SemanticsProperties value) {
    return value.attributedLabel ?? (value.label == null ? null : AttributedString(value.label!));
  }

  AttributedString? _effectiveAttributedValue(SemanticsProperties value) {
    return value.attributedValue ?? (value.value == null ? null : AttributedString(value.value!));
  }

  AttributedString? _effectiveAttributedIncreasedValue(SemanticsProperties value) {
    return value.attributedIncreasedValue ??
        (value.increasedValue == null ? null : AttributedString(value.increasedValue!));
  }

  AttributedString? _effectiveAttributedDecreasedValue(SemanticsProperties value) {
    return properties.attributedDecreasedValue ??
        (value.decreasedValue == null ? null : AttributedString(value.decreasedValue!));
  }

  AttributedString? _effectiveAttributedHint(SemanticsProperties value) {
    return value.attributedHint ?? (value.hint == null ? null : AttributedString(value.hint!));
  }

  AttributedString? _attributedLabel;
  AttributedString? _attributedValue;
  AttributedString? _attributedIncreasedValue;
  AttributedString? _attributedDecreasedValue;
  AttributedString? _attributedHint;

  /// If non-null, sets the [SemanticsNode.textDirection] semantic to the given
  /// value.
  ///
  /// This must not be null if [SemanticsProperties.attributedLabel],
  /// [SemanticsProperties.attributedHint],
  /// [SemanticsProperties.attributedValue],
  /// [SemanticsProperties.attributedIncreasedValue], or
  /// [SemanticsProperties.attributedDecreasedValue] are not null.
  TextDirection? get textDirection => _textDirection;
  TextDirection? _textDirection;
  set textDirection(TextDirection? value) {
    if (textDirection == value) {
      return;
    }
    _textDirection = value;
    markNeedsSemanticsUpdate();
  }

  @override
  void visitChildrenForSemantics(RenderObjectVisitor visitor) {
    if (excludeSemantics) {
      return;
    }
    super.visitChildrenForSemantics(visitor);
  }

  @override
  void describeSemanticsConfiguration(SemanticsConfiguration config) {
    super.describeSemanticsConfiguration(config);
    config.isSemanticBoundary = container;
    config.explicitChildNodes = explicitChildNodes;
    config.isBlockingUserActions = blockUserActions;
    if (localeForSubtree != null) {
      config.localeForSubtree = localeForSubtree;
    }
    assert(
      ((_properties.scopesRoute ?? false) && explicitChildNodes) ||
          !(_properties.scopesRoute ?? false),
      'explicitChildNodes must be set to true if scopes route is true',
    );
    assert(
      !((_properties.toggled ?? false) && (_properties.checked ?? false)),
      'A semantics node cannot be toggled and checked at the same time',
    );

    if (_properties.enabled != null) {
      config.isEnabled = _properties.enabled;
    }
    if (_properties.checked != null) {
      config.isChecked = _properties.checked;
    }
    if (_properties.mixed != null) {
      config.isCheckStateMixed = _properties.mixed;
    }
    if (_properties.toggled != null) {
      config.isToggled = _properties.toggled;
    }
    if (_properties.selected != null) {
      config.isSelected = _properties.selected!;
    }
    if (_properties.button != null) {
      config.isButton = _properties.button!;
    }
    if (_properties.expanded != null) {
      config.isExpanded = _properties.expanded;
    }
    if (_properties.link != null) {
      config.isLink = _properties.link!;
    }
    if (_properties.linkUrl != null) {
      config.linkUrl = _properties.linkUrl;
    }
    if (_properties.slider != null) {
      config.isSlider = _properties.slider!;
    }
    if (_properties.keyboardKey != null) {
      config.isKeyboardKey = _properties.keyboardKey!;
    }
    if (_properties.header != null) {
      config.isHeader = _properties.header!;
    }
    if (_properties.headingLevel != null) {
      config.headingLevel = _properties.headingLevel!;
    }
    if (_properties.textField != null) {
      config.isTextField = _properties.textField!;
    }
    if (_properties.readOnly != null) {
      config.isReadOnly = _properties.readOnly!;
    }
    if (_properties.focusable != null) {
      config.isFocusable = _properties.focusable!;
    }
    if (_properties.focused != null) {
      config.isFocused = _properties.focused;
    }
    if (_properties.accessiblityFocusBlockType != null) {
      config.accessiblityFocusBlockType = _properties.accessiblityFocusBlockType!;
    }
    if (_properties.inMutuallyExclusiveGroup != null) {
      config.isInMutuallyExclusiveGroup = _properties.inMutuallyExclusiveGroup!;
    }
    if (_properties.obscured != null) {
      config.isObscured = _properties.obscured!;
    }
    if (_properties.multiline != null) {
      config.isMultiline = _properties.multiline!;
    }
    if (_properties.hidden != null) {
      config.isHidden = _properties.hidden!;
    }
    if (_properties.image != null) {
      config.isImage = _properties.image!;
    }
    if (_properties.isRequired != null) {
      config.isRequired = _properties.isRequired;
    }
    if (_properties.identifier != null) {
      config.identifier = _properties.identifier!;
    }
    if (_properties.traversalParentIdentifier != null) {
      config.traversalParentIdentifier = _properties.traversalParentIdentifier;
    }
    if (_properties.traversalChildIdentifier != null) {
      config.traversalChildIdentifier = _properties.traversalChildIdentifier;
    }
    if (_attributedLabel != null) {
      config.attributedLabel = _attributedLabel!;
    }
    if (_attributedValue != null) {
      config.attributedValue = _attributedValue!;
    }
    if (_attributedIncreasedValue != null) {
      config.attributedIncreasedValue = _attributedIncreasedValue!;
    }
    if (_attributedDecreasedValue != null) {
      config.attributedDecreasedValue = _attributedDecreasedValue!;
    }
    if (_attributedHint != null) {
      config.attributedHint = _attributedHint!;
    }
    if (_properties.tooltip != null) {
      config.tooltip = _properties.tooltip!;
    }
    if (_properties.hintOverrides != null && _properties.hintOverrides!.isNotEmpty) {
      config.hintOverrides = _properties.hintOverrides;
    }
    if (_properties.scopesRoute != null) {
      config.scopesRoute = _properties.scopesRoute!;
    }
    if (_properties.namesRoute != null) {
      config.namesRoute = _properties.namesRoute!;
    }
    if (_properties.liveRegion != null) {
      config.liveRegion = _properties.liveRegion!;
    }
    if (_properties.maxValueLength != null) {
      config.maxValueLength = _properties.maxValueLength;
    }
    if (_properties.currentValueLength != null) {
      config.currentValueLength = _properties.currentValueLength;
    }
    if (textDirection != null) {
      config.textDirection = textDirection;
    }
    if (_properties.sortKey != null) {
      config.sortKey = _properties.sortKey;
    }
    if (_properties.tagForChildren != null) {
      config.addTagForChildren(_properties.tagForChildren!);
    }
    if (properties.role != null) {
      config.role = _properties.role!;
    }
    if (_properties.controlsNodes != null) {
      config.controlsNodes = _properties.controlsNodes;
    }
    if (config.validationResult != _properties.validationResult) {
      config.validationResult = _properties.validationResult;
    }

    if (_properties.hitTestBehavior != null) {
      config.hitTestBehavior = _properties.hitTestBehavior!;
    }

    if (_properties.inputType != null) {
      config.inputType = _properties.inputType!;
    }
    if (_properties.minValue != null) {
      config.minValue = _properties.minValue;
    }
    if (_properties.maxValue != null) {
      config.maxValue = _properties.maxValue;
    }

    // Registering _perform* as action handlers instead of the user provided
    // ones to ensure that changing a user provided handler from a non-null to
    // another non-null value doesn't require a semantics update.
    if (_properties.onTap != null) {
      config.onTap = _performTap;
    }
    if (_properties.onLongPress != null) {
      config.onLongPress = _performLongPress;
    }
    if (_properties.onDismiss != null) {
      config.onDismiss = _performDismiss;
    }
    if (_properties.onScrollLeft != null) {
      config.onScrollLeft = _performScrollLeft;
    }
    if (_properties.onScrollRight != null) {
      config.onScrollRight = _performScrollRight;
    }
    if (_properties.onScrollUp != null) {
      config.onScrollUp = _performScrollUp;
    }
    if (_properties.onScrollDown != null) {
      config.onScrollDown = _performScrollDown;
    }
    if (_properties.onIncrease != null) {
      config.onIncrease = _performIncrease;
    }
    if (_properties.onDecrease != null) {
      config.onDecrease = _performDecrease;
    }
    if (_properties.onCopy != null) {
      config.onCopy = _performCopy;
    }
    if (_properties.onCut != null) {
      config.onCut = _performCut;
    }
    if (_properties.onPaste != null) {
      config.onPaste = _performPaste;
    }
    if (_properties.onMoveCursorForwardByCharacter != null) {
      config.onMoveCursorForwardByCharacter = _performMoveCursorForwardByCharacter;
    }
    if (_properties.onMoveCursorBackwardByCharacter != null) {
      config.onMoveCursorBackwardByCharacter = _performMoveCursorBackwardByCharacter;
    }
    if (_properties.onMoveCursorForwardByWord != null) {
      config.onMoveCursorForwardByWord = _performMoveCursorForwardByWord;
    }
    if (_properties.onMoveCursorBackwardByWord != null) {
      config.onMoveCursorBackwardByWord = _performMoveCursorBackwardByWord;
    }
    if (_properties.onSetSelection != null) {
      config.onSetSelection = _performSetSelection;
    }
    if (_properties.onSetText != null) {
      config.onSetText = _performSetText;
    }
    if (_properties.onDidGainAccessibilityFocus != null) {
      config.onDidGainAccessibilityFocus = _performDidGainAccessibilityFocus;
    }
    if (_properties.onDidLoseAccessibilityFocus != null) {
      config.onDidLoseAccessibilityFocus = _performDidLoseAccessibilityFocus;
    }
    if (_properties.onFocus != null) {
      config.onFocus = _performFocus;
    }
    if (_properties.onExpand != null) {
      config.onExpand = _performExpand;
    }
    if (_properties.onCollapse != null) {
      config.onCollapse = _performCollapse;
    }
    if (_properties.customSemanticsActions != null) {
      config.customSemanticsActions = _properties.customSemanticsActions!;
    }
  }

  void _performTap() {
    _properties.onTap?.call();
  }

  void _performLongPress() {
    _properties.onLongPress?.call();
  }

  void _performDismiss() {
    _properties.onDismiss?.call();
  }

  void _performScrollLeft() {
    _properties.onScrollLeft?.call();
  }

  void _performScrollRight() {
    _properties.onScrollRight?.call();
  }

  void _performScrollUp() {
    _properties.onScrollUp?.call();
  }

  void _performScrollDown() {
    _properties.onScrollDown?.call();
  }

  void _performIncrease() {
    _properties.onIncrease?.call();
  }

  void _performDecrease() {
    _properties.onDecrease?.call();
  }

  void _performCopy() {
    _properties.onCopy?.call();
  }

  void _performCut() {
    _properties.onCut?.call();
  }

  void _performPaste() {
    _properties.onPaste?.call();
  }

  void _performMoveCursorForwardByCharacter(bool extendSelection) {
    _properties.onMoveCursorForwardByCharacter?.call(extendSelection);
  }

  void _performMoveCursorBackwardByCharacter(bool extendSelection) {
    _properties.onMoveCursorBackwardByCharacter?.call(extendSelection);
  }

  void _performMoveCursorForwardByWord(bool extendSelection) {
    _properties.onMoveCursorForwardByWord?.call(extendSelection);
  }

  void _performMoveCursorBackwardByWord(bool extendSelection) {
    _properties.onMoveCursorBackwardByWord?.call(extendSelection);
  }

  void _performSetSelection(TextSelection selection) {
    _properties.onSetSelection?.call(selection);
  }

  void _performSetText(String text) {
    _properties.onSetText?.call(text);
  }

  void _performDidGainAccessibilityFocus() {
    _properties.onDidGainAccessibilityFocus?.call();
  }

  void _performDidLoseAccessibilityFocus() {
    _properties.onDidLoseAccessibilityFocus?.call();
  }

  void _performFocus() {
    _properties.onFocus?.call();
  }

  void _performExpand() {
    _properties.onExpand?.call();
  }

  void _performCollapse() {
    _properties.onCollapse?.call();
  }
}

/// Properties of _RenderObjectSemantics that are imposed from parent.
@immutable
final class _SemanticsParentData {
  const _SemanticsParentData({
    required this.mergeIntoParent,
    required this.blocksUserActions,
    required this.explicitChildNodes,
    required this.tagsForChildren,
    required this.localeForChildren,
    required this.accessiblityFocusBlockType,
  });

  /// Whether [SemanticsNode]s created from this render object semantics subtree
  /// will be merged into parent.
  ///
  /// This is imposed by render objects of parent [MergeSemantics]s.
  final bool mergeIntoParent;

  /// Whether [SemanticsNode]s created from this render object semantics subtree
  /// ignores user action such as [SemanticsAction.tap] and its friends.
  ///
  /// This is imposed by render objects of parent [IgnorePointer]s or
  /// [AbsorbPointer]s.
  final bool blocksUserActions;

  /// The **Accessibility Focus Block Type** controls how accessibility focus is blocked.
  ///
  /// * **none**: Accessibility focus is **not blocked**.
  /// * **blockSubtree**: Blocks accessibility focus for the entire subtree.
  /// * **blockNode**: Blocks accessibility focus for the **current node only**.
  ///
  /// Only `blockSubtree` from a parent will be propagated down.
  final AccessiblityFocusBlockType? accessiblityFocusBlockType;

  /// Any immediate render object semantics that
  /// [_RenderObjectSemantics.contributesToSemanticsTree] should forms a node
  ///
  /// This is imposed by parent render objects that set
  /// [SemanticsConfiguration.explicitChildNodes] to true.
  final bool explicitChildNodes;

  /// Tags for immediate render object semantics that
  /// [_RenderObjectSemantics.shouldFormSemanticsNode] is true.
  final Set<SemanticsTag>? tagsForChildren;

  final Locale? localeForChildren;

  @override
  bool operator ==(Object other) {
    return other is _SemanticsParentData &&
        other.mergeIntoParent == mergeIntoParent &&
        other.blocksUserActions == blocksUserActions &&
        other.explicitChildNodes == explicitChildNodes &&
        other.localeForChildren == localeForChildren &&
        setEquals<SemanticsTag>(other.tagsForChildren, tagsForChildren);
  }

  @override
  int get hashCode {
    return Object.hash(
      mergeIntoParent,
      blocksUserActions,
      explicitChildNodes,
      localeForChildren,
      Object.hashAllUnordered(tagsForChildren ?? const <SemanticsTag>{}),
    );
  }
}

/// A wrapper class that handles the life cycle of the [SemanticsConfiguration]
/// of a [RenderObject].
///
/// Typically, this class calls [RenderObject.describeSemanticsConfiguration] to
/// update the config and owner of this object does not directly mutate the
/// the config.
///
/// In some cases during [PipelineOwner.flushSemantics], the config has to be
/// mutated due to [_SemanticsParentData] update to propagate updated property
/// to semantics node. One should use [updateConfig] to update the config in this
/// case.
///
/// To access the config stored in this wrapper, uses
/// [_SemanticsConfigurationProvider.effective] to access the latest config.
/// Uses [_SemanticsConfigurationProvider.original] if one wants to access the
/// raw config without post mutations.
class _SemanticsConfigurationProvider {
  _SemanticsConfigurationProvider(this._renderObject);

  /// The owning rendering object for this object.
  final RenderObject _renderObject;

  bool _isEffectiveConfigWritable = false;
  SemanticsConfiguration? _originalConfiguration;
  SemanticsConfiguration? _effectiveConfiguration;

  bool get wasSemanticsBoundary => _originalConfiguration?.isSemanticBoundary ?? false;

  /// The latest config that reflect any change done through [updateConfig].
  SemanticsConfiguration get effective {
    return _effectiveConfiguration ?? original;
  }

  /// The original config without any change through [updateConfig].
  ///
  /// This is typically use to recalculate certain properties when mutating
  /// [effective] since [effective] may contain stale data from previous update.
  /// An example is [SemanticsConfiguration.isBlockingUserActions]. Otherwise,
  /// use [effective] instead.
  SemanticsConfiguration get original {
    if (_originalConfiguration == null) {
      _effectiveConfiguration = _originalConfiguration = SemanticsConfiguration();
      _renderObject.describeSemanticsConfiguration(_originalConfiguration!);
      assert(
        !_originalConfiguration!.explicitChildNodes ||
            _originalConfiguration!.childConfigurationsDelegate == null,
        'A SemanticsConfiguration with explicitChildNode set to true cannot have a non-null childConfigsDelegate.',
      );
    }
    return _originalConfiguration!;
  }

  /// Mutates the config
  ///
  /// This does not change the [original], and the change reflects in
  /// [effective].
  void updateConfig(ValueSetter<SemanticsConfiguration> callback) {
    if (!_isEffectiveConfigWritable) {
      _effectiveConfiguration = original.copy();
      _isEffectiveConfigWritable = true;
    }
    callback(_effectiveConfiguration!);
  }

  /// Absorb a list of config into [effective].
  void absorbAll(Iterable<SemanticsConfiguration> configs) {
    updateConfig((SemanticsConfiguration config) {
      configs.forEach(config.absorb);
    });
  }

  /// Reset any post mutation to [effective].
  void reset() {
    _effectiveConfiguration = original;
    _isEffectiveConfigWritable = false;
  }

  /// Remove every cache in this wrapper.
  ///
  /// This cause the [RenderObject.describeSemanticsConfiguration] to be
  /// re-evaluated next time [effective] or [original] is called.
  void clear() {
    _isEffectiveConfigWritable = false;
    _effectiveConfiguration = null;
    _originalConfiguration = null;
  }
}

/// A convenient abstract interface used for constructing the
/// [_RenderObjectSemantics] tree.
///
/// The _SemanticsFragment can be an [_IncompleteSemanticsFragment] or a
/// [_RenderObjectSemantics]. This interface is used so that
/// [_RenderObjectSemantics] can handle semantics configuration merging without
/// knowing whether the child fragment is backed by a render object or an
/// incomplete semantics fragment.
abstract class _SemanticsFragment {
  SemanticsConfiguration? get configToMergeUp;

  _RenderObjectSemantics get owner;

  bool mergesToSibling = false;

  void markSiblingConfigurationConflict(bool conflict);
}

/// A fragment that is generated from
/// [SemanticsConfiguration.childConfigurationsDelegate]
///
/// A render object can choose to add additional semantics config to be merged
/// upward besides itself. These configs can be added through
/// [SemanticsConfiguration.childConfigurationsDelegate] and will form
/// `_IncompleteSemanticsFragment`s
///
/// See [RenderParagraph] for an example usage.
class _IncompleteSemanticsFragment extends _SemanticsFragment {
  _IncompleteSemanticsFragment(this.configToMergeUp, this.owner);

  @override
  final SemanticsConfiguration configToMergeUp;

  @override
  final _RenderObjectSemantics owner;

  @override
  void markSiblingConfigurationConflict(bool conflict) {
    assert(!conflict);
  }
}

typedef _MergeUpAndSiblingMergeGroups = (
  List<_SemanticsFragment> mergeUp,
  List<List<_SemanticsFragment>> siblingMergeGroups,
);

/// A wrapper class for a [RenderObject] that provides semantics related
/// properties and compilations.
///
/// ## A high level summary
///
/// The [PipelineOwner.flushSemantics] calls the [updateChildren] to
/// build/update a tree of [_RenderObjectSemantics] by querying dirty
/// RenderObjects about their [SemanticsConfiguration] and updating the
/// _RenderObjectSemantics of the render objects according to these information.
/// While doing that, [updateChildren] also decide what
/// _RenderObjectSemantics will have their own SemanticsNode later on.
/// After that, [PipelineOwner.flushSemantics] calls [ensureGeometry] to
/// calculate the geometries for these _RenderObjectSemantics. Finally,
/// [ensureSemanticsNode] compiles these _RenderObjectSemantics into the actual
/// SemanticsNodes that form the semantics tree.
///
/// ## Steps Breakdown
///
/// The _RenderObjectSemantics tree is compiled in four phases. Phase 1 and 2
/// are done in [updateChildren], Phase 3 is done in [ensureGeometry], and phase
/// 4 is done in [ensureSemanticsNode].
///
/// ### Phase 1
///
/// Gather all the merge up _RenderObjectSemantics(s) by walking the rendering
/// object tree.
///
/// They are stored in [mergeUp] and [siblingMergeGroups] and should mimic
/// rendering object tree closely but only contain [_RenderObjectSemantics] that
/// contributes to semantics tree. i.e. where [contributesToSemanticsTree] is
/// true.
///
/// ### Phase 2
///
/// Merge all fragments from [mergeUp] and decide which [_RenderObjectSemantics]
/// should form a node, i.e. [shouldFormSemanticsNode] is true. Stores the
/// [_RenderObjectSemantics] that should form a node into [_children].
///
/// At this point, walking the [_children] forms a tree
/// that exactly resemble the resulting semantics node tree.
///
/// ### Phase 3
///
/// Walks the [_children] and calculate their
/// [_SemanticsGeometry] based on renderObject relationship.
///
/// ### Phase 4
///
/// Walks the [_children] and produce semantics node for
/// each [_RenderObjectSemantics] plus the sibling nodes.
///
/// Phase 2, 3, 4 each depends on previous step to finished updating the the
/// entire _RenderObjectSemantics tree. All three of them require separate tree
/// walk.
class _RenderObjectSemantics extends _SemanticsFragment with DiagnosticableTreeMixin {
  _RenderObjectSemantics(this.renderObject)
    : configProvider = _SemanticsConfigurationProvider(renderObject);

  /// The owning rendering object for this wrapper.
  final RenderObject renderObject;

  bool _hasSiblingConflict = false;
  bool? _blocksPreviousSibling;

  // TODO(chunhtai): Figure out what to do when incomplete fragments are asked
  // to form a semantics node.
  //
  // If this is true, the [contributesToSemanticsTree] will also return true.
  // This is a workaround so that the incomplete fragments will not be forced to
  // form nodes if the parent has explicitChildNode = true.
  bool _containsIncompleteFragment = false;

  // Whether the semantics information in [cachedSemanticsNode] is up-to-date.
  //
  // When this flag is false, the cached semantics node must not be presented to
  // the platform a11y system until it's updated or removed from the tree.
  bool built = false;

  /// The cached node created directly by this Object.
  ///
  /// This cache is filled after the this object is compiled (usually by
  /// calling [ensureSemanticsNode] on this object or ancestors) and forms a
  /// semantics node.
  ///
  /// Caching the semantics node ensures the id is consistent in the life time
  /// of this object.
  ///
  /// `_RenderSemanticsObject` only forms semantics node if
  /// `shouldFormSemanticsNode` is true.
  SemanticsNode? cachedSemanticsNode;

  /// The semantics nodes produced by this render object.
  ///
  /// This is filled after [ensureSemanticsNode] is called on this object or
  /// ancestors when [shouldFormSemanticsNode] is true. In most cases, this only
  /// contains one semantics node equals to [cachedSemanticsNode].
  ///
  /// If there are [siblingMergeGroups], the nodes produced from the sibling
  /// merge groups are also stored in this list.
  final List<SemanticsNode> semanticsNodes = <SemanticsNode>[];

  /// Fragments that will merge up to parent rendering object semantics.
  final List<_SemanticsFragment> mergeUp = <_SemanticsFragment>[];

  /// A list to store immediate child [_RenderObjectSemantics]s that will form
  /// semantics nodes.
  final List<_RenderObjectSemantics> _children = <_RenderObjectSemantics>[];

  /// Merge groups that will form additional sibling nodes.
  final List<List<_SemanticsFragment>> siblingMergeGroups = <List<_SemanticsFragment>>[];
  final Map<SemanticsNode, List<_SemanticsFragment>> _producedSiblingNodesAndOwners =
      <SemanticsNode, List<_SemanticsFragment>>{};

  _SemanticsParentData? parentData;
  _SemanticsGeometry? geometry;

  final _SemanticsConfigurationProvider configProvider;

  @override
  _RenderObjectSemantics get owner => this;

  bool get parentDataDirty {
    if (isRoot) {
      return false;
    }
    return parentData == null;
  }

  /// If this forms a semantics node, all of the properties in config are
  /// used in creating the node. There is nothing to be merged up.
  @override
  SemanticsConfiguration? get configToMergeUp =>
      shouldFormSemanticsNode ? null : configProvider.effective;

  bool get contributesToSemanticsTree {
    return configProvider.effective.hasBeenAnnotated ||
        _containsIncompleteFragment ||
        configProvider.effective.isSemanticBoundary ||
        isRoot;
  }

  bool get isRoot => renderObject.parent == null;

  bool get shouldFormSemanticsNode {
    if (configProvider.effective.isSemanticBoundary) {
      return true;
    }
    if (isRoot) {
      return true;
    }
    if (!contributesToSemanticsTree) {
      return false;
    }

    assert(
      parentData != null,
      'If there is no explicit flag that enforce semantics node, parent data '
      'must be updated before determining whether this object will form a node',
    );
    return parentData!.explicitChildNodes || _hasSiblingConflict;
  }

  static void debugCheckForParentData(RenderObject root) {
    void debugCheckParentDataNotDirty(_RenderObjectSemantics semantics) {
      assert(!semantics.parentDataDirty);
      semantics._getNonBlockedChildren().forEach(debugCheckParentDataNotDirty);
    }

    debugCheckParentDataNotDirty(root._semantics);
  }

  /// Whether this render object semantics will block other render object
  /// semantics behind it in render object order from parent.
  ///
  /// The [BlockSemantics] widget will cause this property to be true and hide
  /// any sibling widget behind it from semantics.
  bool get isBlockingPreviousSibling {
    if (_blocksPreviousSibling != null) {
      return _blocksPreviousSibling!;
    }

    _blocksPreviousSibling = configProvider.effective.isBlockingSemanticsOfPreviouslyPaintedNodes;

    if (_blocksPreviousSibling!) {
      return true;
    }

    if (configProvider.effective.isSemanticBoundary) {
      return false;
    }

    renderObject.visitChildrenForSemantics((RenderObject child) {
      final _RenderObjectSemantics childSemantics = child._semantics;
      if (childSemantics.isBlockingPreviousSibling) {
        _blocksPreviousSibling = true;
      }
    });
    return _blocksPreviousSibling!;
  }

  static bool shouldDrop(SemanticsNode node) => node.isInvisible;

  void markNeedsBuild() {
    built = false;
    if (!parentDataDirty && !shouldFormSemanticsNode) {
      return;
    }
    for (final List<_SemanticsFragment> group in siblingMergeGroups) {
      for (final _RenderObjectSemantics semantics in group.whereType<_RenderObjectSemantics>()) {
        if (semantics.parentDataDirty) {
          continue;
        }
        if (!semantics.shouldFormSemanticsNode) {
          // This render object semantics will need to be merged into a sibling
          // node.
          semantics.markNeedsBuild();
        }
      }
    }
  }

  /// Updates the [parentData] for the [_RenderObjectSemantics]s in the
  /// rendering subtree and forms a [_RenderObjectSemantics] tree where children
  /// are stored in [_children].
  ///
  /// This method does the the phase 1 and 2 of the four phases documented on
  /// [_RenderObjectSemantics].
  ///
  /// Gather all the merge up _RenderObjectSemantics(s) by walking the rendering
  /// object tree.
  ///
  /// They are stored in [mergeUp] and [siblingMergeGroups] and should mimic
  /// rendering object tree closely but only contain [_RenderObjectSemantics] that
  /// contributes to semantics tree. i.e.
  /// [contributesToSemanticsTree] is true.
  ///
  /// Merge all fragments from [mergeUp] and decide which [_RenderObjectSemantics]
  /// should form a node. i.e. [shouldFormSemanticsNode] is true. Stores the
  /// [_RenderObjectSemantics] that should form a node with elevation adjustments
  /// into [_children].
  void updateChildren() {
    assert(parentData != null || isRoot, 'parent data can only be null for root rendering object');
    configProvider.reset();
    final Set<SemanticsTag>? tagsForChildren = _getTagsForChildren();
    final bool explicitChildNodesForChildren =
        isRoot ||
        configProvider.effective.explicitChildNodes ||
        // ParentData's explicitChildNode only
        // propagate to children if this node doesn't
        // contribute to semantics tree
        (!contributesToSemanticsTree && (parentData?.explicitChildNodes ?? true));

    final bool blocksUserAction =
        (parentData?.blocksUserActions ?? false) || configProvider.effective.isBlockingUserActions;

    AccessiblityFocusBlockType accessiblityFocusBlockType;
    if (parentData?.accessiblityFocusBlockType == AccessiblityFocusBlockType.blockSubtree) {
      accessiblityFocusBlockType = AccessiblityFocusBlockType.blockSubtree;
    } else {
      accessiblityFocusBlockType = configProvider.effective.accessiblityFocusBlockType;
    }

    // localeForSubtree from the config overrides parentData's inherited locale.
    final Locale? localeForChildren =
        configProvider.effective.localeForSubtree ?? parentData?.localeForChildren;

    siblingMergeGroups.clear();
    mergeUp.clear();
    final childParentData = _SemanticsParentData(
      mergeIntoParent:
          (parentData?.mergeIntoParent ?? false) ||
          configProvider.effective.isMergingSemanticsOfDescendants,
      blocksUserActions: blocksUserAction,
      accessiblityFocusBlockType: accessiblityFocusBlockType,
      localeForChildren: localeForChildren,
      explicitChildNodes: explicitChildNodesForChildren,
      tagsForChildren: tagsForChildren,
    );

    final _MergeUpAndSiblingMergeGroups result = _collectChildMergeUpAndSiblingGroup(
      childParentData,
    );
    mergeUp.addAll(result.$1);
    siblingMergeGroups.addAll(result.$2);

    // Construct tree for nodes that will form semantics nodes.
    _children.clear();
    if (!contributesToSemanticsTree) {
      return;
    }
    _marksConflictsInMergeGroup(mergeUp, isMergeUp: true);
    siblingMergeGroups.forEach(_marksConflictsInMergeGroup);

    final Iterable<SemanticsConfiguration> mergeUpConfigs = mergeUp
        .map<SemanticsConfiguration?>((_SemanticsFragment fragment) => fragment.configToMergeUp)
        .whereType<SemanticsConfiguration>();
    configProvider.absorbAll(mergeUpConfigs);
    // merge up fragments below this object will not be visible to parent
    // because they are either absorbed or will form a semantics node.
    mergeUp.clear();
    mergeUp.add(this);
    for (final _RenderObjectSemantics childSemantics
        in result.$1.whereType<_RenderObjectSemantics>()) {
      assert(childSemantics.contributesToSemanticsTree);
      if (childSemantics.shouldFormSemanticsNode) {
        _children.add(childSemantics);
      } else {
        _children.addAll(childSemantics._children);
        siblingMergeGroups.addAll(childSemantics.siblingMergeGroups);
      }
    }

    final Set<SemanticsTag>? tags = parentData?.tagsForChildren;
    if (tags != null) {
      assert(tags.isNotEmpty);
      configProvider.updateConfig((SemanticsConfiguration config) {
        tags.forEach(config.addTagForChildren);
      });
    }
    if (accessiblityFocusBlockType != configProvider.effective.accessiblityFocusBlockType) {
      configProvider.updateConfig((SemanticsConfiguration config) {
        config.accessiblityFocusBlockType = accessiblityFocusBlockType;
      });
    }

    if (blocksUserAction != configProvider.effective.isBlockingUserActions) {
      configProvider.updateConfig((SemanticsConfiguration config) {
        config.isBlockingUserActions = blocksUserAction;
      });
    }
    if (localeForChildren != configProvider.effective.locale) {
      configProvider.updateConfig((SemanticsConfiguration config) {
        config.locale = localeForChildren;
      });
    }
  }

  List<_RenderObjectSemantics> _getNonBlockedChildren() {
    final result = <_RenderObjectSemantics>[];
    renderObject.visitChildrenForSemantics((RenderObject renderChild) {
      if (renderChild._semantics.isBlockingPreviousSibling) {
        result.clear();
      }
      result.add(renderChild._semantics);
    });
    return result;
  }

  Set<SemanticsTag>? _getTagsForChildren() {
    if (contributesToSemanticsTree) {
      return configProvider.original.tagsForChildren?.toSet();
    }
    Set<SemanticsTag>? result;
    if (configProvider.original.tagsForChildren != null) {
      result = configProvider.original.tagsForChildren!.toSet();
    }
    if (parentData?.tagsForChildren != null) {
      if (result == null) {
        result = parentData!.tagsForChildren;
      } else {
        result.addAll(parentData!.tagsForChildren!);
      }
    }
    return result;
  }

  _MergeUpAndSiblingMergeGroups _collectChildMergeUpAndSiblingGroup(
    _SemanticsParentData childParentData,
  ) {
    final mergeUp = <_SemanticsFragment>[];
    final siblingMergeGroups = <List<_SemanticsFragment>>[];

    final childConfigurations = <SemanticsConfiguration>[];
    final ChildSemanticsConfigurationsDelegate? childConfigurationsDelegate =
        configProvider.effective.childConfigurationsDelegate;
    final hasChildConfigurationsDelegate = childConfigurationsDelegate != null;
    final configToFragment = <SemanticsConfiguration, _SemanticsFragment>{};

    // It is possible the childConfigurationsDelegate may produce incomplete
    // fragments. In this case, this render object semantics need to absorb all
    // the mergeUp from children before present itself to the parent to avoid
    // the parent forcing incomplete fragments to form a node. This is done by
    // _containsIncompleteFragment which in turns flips the
    // contributesToSemanticsTree.
    //
    // The problem is we won't know whether it will generate incomplete
    // fragments until it runs, but we have to decide whether to propagate the
    // parent's explicitChildNodes before we collect child fragments.
    //
    // Therefore, we have to make an assumption now to assume it will generate
    // incomplete fragment and not propagate explicitChildNodes.
    final bool needsToMakeIncompleteFragmentAssumption =
        hasChildConfigurationsDelegate && childParentData.explicitChildNodes;

    final _SemanticsParentData effectiveChildParentData;
    if (needsToMakeIncompleteFragmentAssumption) {
      effectiveChildParentData = _SemanticsParentData(
        mergeIntoParent: childParentData.mergeIntoParent,
        blocksUserActions: childParentData.blocksUserActions,
        accessiblityFocusBlockType: childParentData.accessiblityFocusBlockType,
        explicitChildNodes: false,
        tagsForChildren: childParentData.tagsForChildren,
        localeForChildren: childParentData.localeForChildren,
      );
    } else {
      effectiveChildParentData = childParentData;
    }
    for (final _RenderObjectSemantics childSemantics in _getNonBlockedChildren()) {
      assert(!childSemantics.renderObject._needsLayout);
      childSemantics._didUpdateParentData(effectiveChildParentData);
      for (final _SemanticsFragment fragment in childSemantics.mergeUp) {
        if (hasChildConfigurationsDelegate && fragment.configToMergeUp != null) {
          // This fragment need to go through delegate to determine whether it
          // merge up or not.
          childConfigurations.add(fragment.configToMergeUp!);
          configToFragment[fragment.configToMergeUp!] = fragment;
        } else {
          mergeUp.add(fragment);
        }
      }

      if (!childSemantics.contributesToSemanticsTree) {
        // This child semantics needs to propagate sibling merge group to be
        // compiled by parent that contributes to semantics tree.
        siblingMergeGroups.addAll(childSemantics.siblingMergeGroups);
      }
    }
    _containsIncompleteFragment = false;
    assert(childConfigurationsDelegate != null || configToFragment.isEmpty);
    if (hasChildConfigurationsDelegate) {
      final ChildSemanticsConfigurationsResult result = childConfigurationsDelegate(
        childConfigurations,
      );
      mergeUp.addAll(
        result.mergeUp.map<_SemanticsFragment>((SemanticsConfiguration config) {
          final _SemanticsFragment? fragment = configToFragment[config];
          if (fragment != null) {
            return fragment;
          }
          _containsIncompleteFragment = true;
          return _IncompleteSemanticsFragment(config, this);
        }),
      );
      for (final Iterable<SemanticsConfiguration> group in result.siblingMergeGroups) {
        siblingMergeGroups.add(
          group.map<_SemanticsFragment>((SemanticsConfiguration config) {
            final _SemanticsFragment? fragment = configToFragment[config];
            if (fragment != null) {
              return fragment;
            }
            _containsIncompleteFragment = true;
            return _IncompleteSemanticsFragment(config, this);
          }).toList(),
        );
      }
    }

    if (!_containsIncompleteFragment && needsToMakeIncompleteFragmentAssumption) {
      // Assumption was wrong, we have to re-update the child.
      mergeUp.clear();
      siblingMergeGroups.clear();

      for (final _RenderObjectSemantics childSemantics in _getNonBlockedChildren()) {
        assert(childParentData.explicitChildNodes);
        childSemantics._didUpdateParentData(childParentData);
        mergeUp.addAll(childSemantics.mergeUp);

        if (!childSemantics.contributesToSemanticsTree) {
          // This child semantics needs to propagate sibling merge group to be
          // compiled by parent that contributes to semantics tree.
          siblingMergeGroups.addAll(childSemantics.siblingMergeGroups);
        }
      }
    }

    return (mergeUp, siblingMergeGroups);
  }

  void _didUpdateParentData(_SemanticsParentData newParentData) {
    if (parentData == newParentData) {
      return;
    }
    // Parent data changes may result in node formation changes.
    geometry = null;
    markNeedsBuild();
    parentData = newParentData;
    updateChildren();
  }

  /// Makes whether this fragment has a sibling fragment with conflicting
  /// [SemanticsConfiguration].
  @override
  void markSiblingConfigurationConflict(bool conflict) {
    _hasSiblingConflict = conflict;
  }

  /// Updates the [geometry] for this [_RenderObjectSemantics]s and its subtree
  /// in [_children].
  ///
  /// This method does the the phase 3 of the four phases documented on
  /// [_RenderObjectSemantics].
  ///
  /// This method is short-circuited if the subtree geometry won't
  /// be affect after the update. (e.g. the size doesn't change, or new clip
  /// rect doesn't clip the content).
  void ensureGeometry() {
    if (isRoot) {
      if (geometry?.rect != renderObject.semanticBounds) {
        markNeedsBuild();
      }
      geometry = _SemanticsGeometry.root(renderObject.semanticBounds);
    }
    assert(geometry != null);
    _updateChildGeometry();
  }

  void _updateChildGeometry() {
    assert(geometry != null);
    final _SemanticsGeometry parentGeometry = geometry!;
    for (final _RenderObjectSemantics child in _children) {
      final _SemanticsGeometry childGeometry = _SemanticsGeometry.computeChildGeometry(
        parentPaintClipRect: parentGeometry.paintClipRect,
        parentSemanticsClipRect: parentGeometry.semanticsClipRect,
        parentTransform: null,
        parent: this,
        child: child,
      );
      child._updateGeometry(newGeometry: childGeometry);
    }
    for (final _RenderObjectSemantics explicitSiblingChild
        in siblingMergeGroups
            .expand<_SemanticsFragment>((List<_SemanticsFragment> group) => group)
            .whereType<_RenderObjectSemantics>()
            .expand(
              (_RenderObjectSemantics siblingChild) => siblingChild.shouldFormSemanticsNode
                  ? <_RenderObjectSemantics>[siblingChild]
                  : siblingChild._children,
            )) {
      final _SemanticsGeometry childGeometry = _SemanticsGeometry.computeChildGeometry(
        parentPaintClipRect: parentGeometry.paintClipRect,
        parentSemanticsClipRect: parentGeometry.semanticsClipRect,
        parentTransform: parentGeometry.transform,
        parent: this,
        child: explicitSiblingChild,
      );
      explicitSiblingChild._updateGeometry(newGeometry: childGeometry);
    }
  }

  void _updateGeometry({required _SemanticsGeometry newGeometry}) {
    geometry = newGeometry;
    markNeedsBuild();
    _updateChildGeometry();
  }

  /// Ensures the semantics nodes from this render object semantics subtree are
  /// generated and up to date.
  ///
  /// This method does the the phase 4 of the four phases documented on
  /// [_RenderObjectSemantics].
  ///
  /// This can only be called if the owning rendering object is a semantics
  /// boundary. For non boundary rendering objects, they require semantics
  /// information from both their parent and child rendering objects to update
  /// its cache, so it can't update by themselves.
  void ensureSemanticsNode() {
    assert(configProvider.effective.isSemanticBoundary || isRoot);
    if (!built) {
      _buildSemantics(usedSemanticsIds: <int>{});
    } else {
      assert(built);
      // parent data and parent geometry didn't change, there isn't anything to
      // update for semantics nodes generated in this render object semantics.
      //
      // Therefore, we only need to update the subtree.
      _buildSemanticsSubtree(usedSemanticsIds: <int>{});
    }
  }

  /// Builds the semantics node and its semantics node subtree.
  ///
  /// This method will in turn call [_buildSemanticsSubtree].
  ///
  /// This method will short-circuit itself if [cachedSemanticsNode] is
  /// already up-to-date.
  void _buildSemantics({required Set<int> usedSemanticsIds}) {
    assert(shouldFormSemanticsNode);
    if (cachedSemanticsNode != null) {
      // Any node other than producedNode in _semanticsNodes are sibling nodes
      // from children fragments. This fragment is responsible for updating
      // tags as well as cleaning up.
      //
      // Clean up the properties now so that we don't have stale data in them
      // after the _produceSemanticsNode.
      for (final SemanticsNode node in semanticsNodes) {
        if (node != cachedSemanticsNode) {
          node.tags = null;
        }
      }
    }
    if (!built) {
      semanticsNodes.clear();
      _producedSiblingNodesAndOwners.clear();
      _produceSemanticsNode(usedSemanticsIds: usedSemanticsIds);
    }
    assert(built);

    // Any node other than producedNode in _semanticsNodes are sibling nodes
    // from children fragments. They share the same tags as the producedNode.
    final SemanticsNode producedNode = cachedSemanticsNode!;
    for (final SemanticsNode node in semanticsNodes) {
      if (node != producedNode) {
        if (parentData?.tagsForChildren != null) {
          node.tags ??= <SemanticsTag>{};
          node.tags!.addAll(parentData!.tagsForChildren!);
        } else if (node.tags?.isEmpty ?? false) {
          node.tags = null;
        }
      }
    }
  }

  /// Builds the semantics subtree under the [cachedSemanticsNode].
  void _buildSemanticsSubtree({required Set<int> usedSemanticsIds}) {
    final children = <SemanticsNode>[];
    for (final _RenderObjectSemantics child in _children) {
      assert(child.shouldFormSemanticsNode);
      // Cached semantics node may be part of sibling merging group prior
      // to this update. In this case, the semantics node may continue to
      // be reused in that sibling merging group.
      if (child.cachedSemanticsNode != null &&
          usedSemanticsIds.contains(child.cachedSemanticsNode!.id)) {
        child.markNeedsBuild();
        child.cachedSemanticsNode = null;
      }

      child._buildSemantics(usedSemanticsIds: usedSemanticsIds);
      children.addAll(child.semanticsNodes);
    }

    final SemanticsNode node = cachedSemanticsNode!;
    children.removeWhere(shouldDrop);
    if (configProvider.effective.isSemanticBoundary) {
      renderObject.assembleSemanticsNode(node, configProvider.effective, children);
    } else {
      node.updateWith(config: configProvider.effective, childrenInInversePaintOrder: children);
    }
  }

  void _produceSemanticsNode({required Set<int> usedSemanticsIds}) {
    assert(!built);
    built = true;
    final SemanticsNode node = cachedSemanticsNode ??= _createSemanticsNode();
    semanticsNodes.add(node);
    node
      ..isMergedIntoParent = (parentData?.mergeIntoParent ?? false)
      ..tags = parentData?.tagsForChildren;
    _updateSemanticsNodeGeometry();

    _mergeSiblingGroup(usedSemanticsIds);
    _buildSemanticsSubtree(usedSemanticsIds: usedSemanticsIds);
  }

  SemanticsNode _createSemanticsNode() {
    if (isRoot) {
      return SemanticsNode.root(
        showOnScreen: owner.renderObject.showOnScreen,
        owner: owner.renderObject.owner!.semanticsOwner!,
      );
    }
    return SemanticsNode(showOnScreen: owner.renderObject.showOnScreen);
  }

  void _mergeSiblingGroup(Set<int> usedSemanticsIds) {
    for (final List<_SemanticsFragment> group in siblingMergeGroups) {
      SemanticsConfiguration? configuration;
      SemanticsNode? node;
      final explicitChildren = <_RenderObjectSemantics>[];
      for (final fragment in group) {
        if (fragment is _RenderObjectSemantics) {
          if (fragment.shouldFormSemanticsNode) {
            explicitChildren.add(fragment);
            assert(fragment.configToMergeUp == null);
            continue;
          }
          explicitChildren.addAll(fragment._children);
        }
        if (fragment.configToMergeUp != null) {
          fragment.mergesToSibling = true;
          node ??= fragment.owner.cachedSemanticsNode;
          configuration ??= SemanticsConfiguration();
          configuration.absorb(fragment.configToMergeUp!);
        }
      }
      final childrenNodes = <SemanticsNode>[];
      for (final explicitChild in explicitChildren) {
        explicitChild._buildSemantics(usedSemanticsIds: usedSemanticsIds);
        childrenNodes.addAll(explicitChild.semanticsNodes);
      }
      // Can be null if all fragments in switchableFragments are marked as explicit.
      if (configuration != null) {
        if (node == null || usedSemanticsIds.contains(node.id)) {
          node = SemanticsNode(showOnScreen: renderObject.showOnScreen);
        }
        usedSemanticsIds.add(node.id);
        for (final fragment in group) {
          if (fragment.configToMergeUp != null) {
            fragment.owner.built = true;
            fragment.owner.cachedSemanticsNode = node;
          }
        }
        node.updateWith(config: configuration, childrenInInversePaintOrder: childrenNodes);
        _producedSiblingNodesAndOwners[node] = group;
        semanticsNodes.add(node);

        final Set<SemanticsTag> tags = group
            .map<Set<SemanticsTag>?>(
              (_SemanticsFragment fragment) => fragment.owner.parentData!.tagsForChildren,
            )
            .whereType<Set<SemanticsTag>>()
            .expand<SemanticsTag>((Set<SemanticsTag> tags) => tags)
            .toSet();
        // This fragment is only allowed to add tags into the node instead of
        // cleaning it since some of the tags may be added by the parent fragment
        // who actually take these node as their siblings.
        //
        // It will be that fragment's responsibility to clean up the tags.
        //
        // This is the same for the transform as well.
        //
        // See _SwitchableFragment.compileSemanticsNodes
        if (tags.isNotEmpty) {
          if (node.tags == null) {
            node.tags = tags;
          } else {
            node.tags!.addAll(tags);
          }
        }
        node.isMergedIntoParent = parentData?.mergeIntoParent ?? false;
      }
    }
    _updateSiblingNodesGeometries();
  }

  /// Updates the semantics geometry of the cached semantics node.
  void _updateSemanticsNodeGeometry() {
    final SemanticsNode node = cachedSemanticsNode!;
    final _SemanticsGeometry nodeGeometry = geometry!;
    final bool isSemanticsHidden =
        configProvider.original.isHidden ||
        (!(parentData?.mergeIntoParent ?? false) && nodeGeometry.hidden);
    node
      ..rect = nodeGeometry.rect
      ..transform = nodeGeometry.transform
      ..parentSemanticsClipRect = nodeGeometry.semanticsClipRect
      ..parentPaintClipRect = nodeGeometry.paintClipRect;
    if (configProvider.effective.isHidden != isSemanticsHidden) {
      configProvider.updateConfig((SemanticsConfiguration config) {
        config.isHidden = isSemanticsHidden;
      });
    }
  }

  void _updateSiblingNodesGeometries() {
    final _SemanticsGeometry mainGeometry = geometry!;
    for (final MapEntry<SemanticsNode, List<_SemanticsFragment>> entry
        in _producedSiblingNodesAndOwners.entries) {
      Rect? rect;
      Rect? semanticsClipRect;
      Rect? paintClipRect;
      for (final _SemanticsFragment fragment in entry.value) {
        if (fragment.owner.shouldFormSemanticsNode) {
          continue;
        }
        final _SemanticsGeometry parentGeometry = _SemanticsGeometry.computeChildGeometry(
          parentTransform: mainGeometry.transform,
          parentSemanticsClipRect: mainGeometry.semanticsClipRect,
          parentPaintClipRect: mainGeometry.paintClipRect,
          parent: this,
          child: fragment.owner,
        );
        final Rect rectInFragmentOwnerCoordinates =
            parentGeometry.semanticsClipRect?.intersect(
              fragment.owner.renderObject.semanticBounds,
            ) ??
            fragment.owner.renderObject.semanticBounds;
        final Rect rectInParentCoordinates = MatrixUtils.transformRect(
          parentGeometry.transform,
          rectInFragmentOwnerCoordinates,
        );
        rect = rect?.expandToInclude(rectInParentCoordinates) ?? rectInParentCoordinates;
        if (parentGeometry.semanticsClipRect != null) {
          final Rect rect = MatrixUtils.transformRect(
            parentGeometry.transform,
            parentGeometry.semanticsClipRect!,
          );
          semanticsClipRect = semanticsClipRect?.intersect(rect) ?? rect;
        }
        if (parentGeometry.paintClipRect != null) {
          final Rect rect = MatrixUtils.transformRect(
            parentGeometry.transform,
            parentGeometry.paintClipRect!,
          );
          paintClipRect = paintClipRect?.intersect(rect) ?? rect;
        }
      }
      final SemanticsNode node = entry.key;
      node
        ..rect = rect!
        ..transform =
            null // transform has be taking into account when
        // calculating the rect.
        ..parentSemanticsClipRect = semanticsClipRect
        ..parentPaintClipRect = paintClipRect;
    }
  }

  /// The [renderObject]'s semantics information has changed.
  void markNeedsUpdate() {
    final SemanticsNode? producedSemanticsNode = cachedSemanticsNode;
    // Dirty the semantics tree starting at `this` until we have reached a
    // RenderObject that is a semantics boundary. All semantics past this
    // RenderObject are still up-to date. Therefore, we will later only rebuild
    // the semantics subtree starting at the identified semantics boundary.
    final bool wasSemanticsBoundary =
        producedSemanticsNode != null && configProvider.wasSemanticsBoundary;

    configProvider.clear();
    _containsIncompleteFragment = false;

    var mayProduceSiblingNodes = configProvider.effective.childConfigurationsDelegate != null;
    bool isEffectiveSemanticsBoundary =
        configProvider.effective.isSemanticBoundary && wasSemanticsBoundary;
    RenderObject node = renderObject;

    // The sibling nodes will be attached to the parent of immediate semantics
    // node, thus marking this semantics boundary dirty is not enough, it needs
    // to find the first parent semantics boundary that does not have any
    // possible sibling node.
    while (node.parent != null && (mayProduceSiblingNodes || !isEffectiveSemanticsBoundary)) {
      if (node != renderObject && node._semantics.parentDataDirty && !mayProduceSiblingNodes) {
        break;
      }
      node._semantics.geometry = null;
      node._semantics.parentData = null;
      node._semantics._blocksPreviousSibling = null;
      // Since this node is a semantics boundary, the produced sibling nodes will
      // be attached to the parent semantics boundary. Thus, these sibling nodes
      // will not be carried to the next loop.
      if (isEffectiveSemanticsBoundary) {
        mayProduceSiblingNodes = false;
      }
      mayProduceSiblingNodes |=
          node._semantics.configProvider.effective.childConfigurationsDelegate != null;

      node = node.parent!;
      // If node._semantics.built is false, this branch is currently blocked.
      // In that case, it should continue dirty upward until it reach a
      // unblocked semantics boundary because blocked branch will not rebuild
      // semantics during PipelineOwner.flushSemantics.
      //
      // If we stop here and not dirty the rendering parent and a flush semantics
      // is called, it will end up with a blocked branch where some sub-branch
      // is dirty. There won't be a way to rebuild these dirty sub-branch
      // without rebuilding the entire blocked branch (which is costly) when the
      // branch is later unblocked.
      isEffectiveSemanticsBoundary =
          node._semantics.configProvider.effective.isSemanticBoundary && node._semantics.built;
    }
    if (node != renderObject && producedSemanticsNode != null && node._semantics.parentDataDirty) {
      // If `this` node has already been added to [owner._nodesNeedingSemantics]
      // remove it as it is no longer guaranteed that its semantics
      // node will continue to be in the tree. If it still is in the tree, the
      // ancestor `node` added to [owner._nodesNeedingSemantics] at the end of
      // this block will ensure that the semantics of `this` node actually gets
      // updated.
      // (See semantics_10_test.dart for an example why this is required).
      renderObject.owner!._nodesNeedingSemantics.remove(renderObject);
    }
    if (!node._semantics.parentDataDirty) {
      if (renderObject.owner != null) {
        assert(node._semantics.configProvider.effective.isSemanticBoundary || node.parent == null);
        if (renderObject.owner!._nodesNeedingSemantics.add(node)) {
          renderObject.owner!.requestVisualUpdate();
        }
      }
    }
  }

  void _marksConflictsInMergeGroup(List<_SemanticsFragment> mergeGroup, {bool isMergeUp = false}) {
    final hasSiblingConflict = <_SemanticsFragment>{};
    for (var i = 0; i < mergeGroup.length; i += 1) {
      final _SemanticsFragment fragment = mergeGroup[i];
      // Remove old value
      fragment.markSiblingConfigurationConflict(false);
      if (fragment.configToMergeUp == null) {
        continue;
      }
      if (isMergeUp && !configProvider.original.isCompatibleWith(fragment.configToMergeUp)) {
        hasSiblingConflict.add(fragment);
      }
      final siblingLength = i;
      for (var j = 0; j < siblingLength; j += 1) {
        final _SemanticsFragment siblingFragment = mergeGroup[j];
        if (!fragment.configToMergeUp!.isCompatibleWith(siblingFragment.configToMergeUp)) {
          hasSiblingConflict.add(fragment);
          hasSiblingConflict.add(siblingFragment);
        }
      }
    }
    for (final fragment in hasSiblingConflict) {
      fragment.markSiblingConfigurationConflict(true);
    }
  }

  /// Removes any cache stored in this object as if it is newly created.
  void clear() {
    built = false;
    cachedSemanticsNode = null;
    parentData = null;
    geometry = null;
    _blocksPreviousSibling = null;
    _containsIncompleteFragment = false;
    mergeUp.clear();
    siblingMergeGroups.clear();
    _children.clear();
    semanticsNodes.clear();
    configProvider.clear();
  }

  @override
  List<DiagnosticsNode> debugDescribeChildren() {
    return _getNonBlockedChildren()
        .map<DiagnosticsNode>((_RenderObjectSemantics child) => child.toDiagnosticsNode())
        .toList();
  }

  @protected
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('owner', describeIdentity(renderObject)));
    properties.add(
      FlagProperty('noParentData', value: parentData == null, ifTrue: 'NO PARENT DATA'),
    );
    properties.add(
      FlagProperty(
        'semanticsBlock',
        value: configProvider.effective.isBlockingSemanticsOfPreviouslyPaintedNodes,
        ifTrue: 'BLOCK PREVIOUS',
      ),
    );
    if (contributesToSemanticsTree) {
      final String semanticsNodeStatus;
      if (built) {
        semanticsNodeStatus = 'formed ${cachedSemanticsNode?.id}';
      } else if (shouldFormSemanticsNode) {
        semanticsNodeStatus = 'needs build';
      } else {
        semanticsNodeStatus = 'no semantics node';
      }
      properties.add(StringProperty('formedSemanticsNode', semanticsNodeStatus, quoted: false));
    }
    properties.add(
      FlagProperty(
        'isSemanticBoundary',
        value: configProvider.effective.isSemanticBoundary,
        ifTrue: 'semantic boundary',
      ),
    );
    properties.add(
      FlagProperty('blocksSemantics', value: isBlockingPreviousSibling, ifTrue: 'BLOCKS SEMANTICS'),
    );
    if (contributesToSemanticsTree && siblingMergeGroups.isNotEmpty) {
      properties.add(StringProperty('Sibling group', siblingMergeGroups.toString(), quoted: false));
    }
  }
}

/// Dumps the render object semantics tree.
void debugDumpRenderObjectSemanticsTree() {
  debugPrint(_debugCollectRenderObjectSemanticsTrees());
}

String _debugCollectRenderObjectSemanticsTrees() {
  if (RendererBinding.instance.renderViews.isEmpty) {
    return 'No render tree root was added to the binding.';
  }
  return <String>[
    for (final RenderObject renderView in RendererBinding.instance.renderViews)
      renderView._semantics.toStringDeep(),
  ].join('\n\n');
}

/// Helper class that keeps track of the geometry of a [SemanticsNode].
///
/// It is used to annotate a [SemanticsNode] with the current information for
/// [SemanticsNode.rect] and [SemanticsNode.transform].
@immutable
final class _SemanticsGeometry {
  /// The `paintClipRect` may be null if no clip is to be applied.
  const _SemanticsGeometry({
    required this.paintClipRect,
    required this.semanticsClipRect,
    required this.transform,
    required this.rect,
    required this.hidden,
  });

  factory _SemanticsGeometry.root(Rect rect) {
    return _SemanticsGeometry(
      paintClipRect: null,
      semanticsClipRect: null,
      transform: Matrix4.identity(),
      hidden: false,
      rect: rect,
    );
  }

  /// Value for [SemanticsNode.transform].
  final Matrix4 transform;

  /// Value for [SemanticsNode.parentSemanticsClipRect].
  final Rect? semanticsClipRect;

  /// Value for [SemanticsNode.parentPaintClipRect].
  final Rect? paintClipRect;

  /// Value for [SemanticsNode.rect].
  final Rect rect;

  /// Whether the semantics node is completely clipped from ui, i.e. by
  /// paintClipRect, but is still present in semantics tree.
  final bool hidden;

  static _SemanticsGeometry computeChildGeometry({
    required Matrix4? parentTransform,
    required Rect? parentPaintClipRect,
    required Rect? parentSemanticsClipRect,
    required _RenderObjectSemantics parent,
    required _RenderObjectSemantics child,
  }) {
    RenderObject childRenderObject = child.renderObject;
    final RenderObject parentRenderObject = parent.renderObject;

    final childToCommonAncestor = <RenderObject>[childRenderObject];

    // Find the path from childRenderObject to parentRenderObject.
    // Currently the framework assumes that parentRenderObject is an ancestor of
    // childRenderObject.
    while (childRenderObject.depth > parentRenderObject.depth) {
      assert(
        childRenderObject.parent != null,
        'The render object of $parent is not an ancestor of the render object of $child.',
      );
      childRenderObject = childRenderObject.parent!;
      childToCommonAncestor.add(childRenderObject);
    }
    assert(childToCommonAncestor.length >= 2);
    assert(identical(childRenderObject, parentRenderObject));

    // Calculate clips and transform.

    Rect? paintClipRect;
    Rect? semanticsClipRect;
    final transform = Matrix4.identity();
    // Traverse from `parent`'s render object to `child`'s.
    for (int i = childToCommonAncestor.length - 1; i > 0; i -= 1) {
      final RenderObject nodeParent = childToCommonAncestor[i];
      final RenderObject node = childToCommonAncestor[i - 1];

      final Rect? localPaintClipInParent = _transformRect(
        nodeParent.describeApproximatePaintClip(node),
        transform, // paint transform of nodeParent in relation to parent
        MatrixUtils.transformRect,
      );
      final Rect? localSemanticsClipInParent = _transformRect(
        nodeParent.describeSemanticsClip(node),
        transform, // paint transform of nodeParent in relation to parent
        MatrixUtils.transformRect,
      );
      paintClipRect = _intersectRects(paintClipRect, localPaintClipInParent);
      semanticsClipRect =
          localSemanticsClipInParent ??
          semanticsClipRect?.intersect(localPaintClipInParent ?? semanticsClipRect);
      nodeParent.applyPaintTransform(node, transform);
    }

    // Apply the parent paint / semantics clipping.
    semanticsClipRect =
        semanticsClipRect ?? _intersectRects(paintClipRect, parentSemanticsClipRect);
    paintClipRect = _intersectRects(paintClipRect, parentPaintClipRect);

    if (paintClipRect != null || semanticsClipRect != null) {
      final Matrix4 inverted = transform.clone();
      final hasInverse = inverted.invert() != 0.0;
      semanticsClipRect = hasInverse
          ? _transformRect(semanticsClipRect, inverted, MatrixUtils.transformRect)
          : null;
      paintClipRect = hasInverse
          ? _transformRect(paintClipRect, inverted, MatrixUtils.transformRect)
          : null;
    }

    if (parentTransform != null) {
      MatrixUtils.multiplyInPlace(parentTransform, transform);
    }

    Rect rect =
        semanticsClipRect?.intersect(child.renderObject.semanticBounds) ??
        child.renderObject.semanticBounds;
    var isRectHidden = false;
    if (paintClipRect != null) {
      final Rect paintRect = paintClipRect.intersect(rect);
      isRectHidden = paintRect.isEmpty && !rect.isEmpty;
      if (!isRectHidden) {
        rect = paintRect;
      }
    }

    return _SemanticsGeometry(
      transform: transform,
      paintClipRect: paintClipRect,
      semanticsClipRect: semanticsClipRect,
      rect: rect,
      hidden: isRectHidden,
    );
  }

  /// From parent to child coordinate system.
  static Rect? _transformRect(
    Rect? rect,
    Matrix4 transform, [
    _TransformRect apply = MatrixUtils.inverseTransformRect,
  ]) {
    if (rect == null) {
      return null;
    }
    if (rect.isEmpty || transform.isZero()) {
      return Rect.zero;
    }
    return apply(transform, rect);
  }

  static Rect? _intersectRects(Rect? a, Rect? b) {
    if (b == null) {
      return a;
    }
    return a?.intersect(b) ?? b;
  }
}

/// A class that creates [DiagnosticsNode] by wrapping [RenderObject.debugCreator].
///
/// Attach a [DiagnosticsDebugCreator] into [FlutterErrorDetails.informationCollector]
/// when a [RenderObject.debugCreator] is available. This will lead to improved
/// error message.
class DiagnosticsDebugCreator extends DiagnosticsProperty<Object> {
  /// Create a [DiagnosticsProperty] with its [value] initialized to input
  /// [RenderObject.debugCreator].
  DiagnosticsDebugCreator(Object value)
    : super('debugCreator', value, level: DiagnosticLevel.hidden);
}
