// 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;

  /// Nodes that need semantics update.
  ///
  /// When a [_RenderObjectSemantics.markNeedsUpdate] is called, the [_RenderObjectSemantics]'s
  /// closest semantics boundary ancestor is added to this set.
  ///
  /// All nodes in this set are guaranteed to be semantics boundaries.
  final Set<RenderObject> _nodesNeedingSemanticsUpdate = <RenderObject>{};

  /// Nodes that need semantics geometry update.
  ///
  /// Nodes are added when their [_RenderObjectSemantics.markNeedsUpdate]s are called.
  ///
  /// This is used to track nodes that need their semantics geometry updated.
  /// Compare to [_nodesNeedingSemanticsUpdate], which tracks semantics boundaries of dirty nodes,
  /// this set only tracks the dirty nodes that need their semantics geometry updated directly.
  final Set<RenderObject> _nodesNeedingSemanticsGeometryUpdate = <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 a top-down order to be more performant. Otherwise, a parent
      // change can invalidate the whole subtree.
      final List<RenderObject> nodesToProcess =
          _nodesNeedingSemanticsUpdate
              .where((RenderObject object) => !object._needsLayout && object.owner == this)
              .toList()
            ..sort((RenderObject a, RenderObject b) => a.depth - b.depth);
      _nodesNeedingSemanticsUpdate.clear();
      if (!kReleaseMode) {
        FlutterTimeline.startSync('Semantics.updateChildren');
      }
      final RenderObject? rootNode = this.rootNode;
      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.
          //
          // We MUST NOT update the parent data now since it may create a gap of
          // render objects with dirty parent data when this branch later rejoins
          // the rendering tree.
          continue;
        }
        node._semantics.updateChildren();
      }
      if (!kReleaseMode) {
        FlutterTimeline.finishSync();
      }

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

      if (!kReleaseMode) {
        FlutterTimeline.startSync('Semantics.ensureGeometry');
      }
      // It is possible the updateChildren above caused some nodes to be added
      // to _nodesNeedingSemanticsGeometryUpdate. Therefore, we need to
      // process them here.
      final List<RenderObject> nodesToProcessGeometry = _nodesNeedingSemanticsGeometryUpdate
          .where(
            (RenderObject object) =>
                !object._needsLayout && object.owner == this && !object._semantics.parentDataDirty,
          )
          .toList();
      _nodesNeedingSemanticsGeometryUpdate.clear();

      // For every node in this list, needs to clear geometry immediate _RenderObjectSemantics
      // that forms semantics node in the subtree.
      //
      // Case 1, this node forms semantics node, then clear the geometry of this node if it is
      // a relayout boundary. Otherwise, the parent should handle clearing the geometry.
      //
      // Case 2, this node does not form semantics node, then clear immediate children's
      // geometry if they form semantics node because this node's transform and clip may affect
      // the geometry of the children.
      for (final node in nodesToProcessGeometry) {
        if (node._semantics.shouldFormSemanticsNode && node._semantics.geometryDirty) {
          // This node is already dirty, skip it.
          continue;
        }

        if (node._semantics.shouldFormSemanticsNode && (node._isRelayoutBoundary ?? false)) {
          // If this node is a relayout boundary, it can change size without parent relayout.
          // In this case, we still need to clear its geometry.
          node._semantics.geometry = null;
          continue;
        }

        if (!node._semantics.contributesToSemanticsTree) {
          // This node merely presents its subtree in the mergeup, so we need to clear
          // the geometry for all the semantics nodes in the mergeup.
          for (final _RenderObjectSemantics child
              in node._semantics.mergeUp.whereType<_RenderObjectSemantics>()) {
            if (child.shouldFormSemanticsNode) {
              child.geometry = null;
            } else {
              // Even though this node does not form a semantics node, it still
              // represents a group of render objects in the subtree, where a node that
              // forms a semantics node is in its _children.
              for (final _RenderObjectSemantics nodeInSubtree in child._children) {
                assert(nodeInSubtree.shouldFormSemanticsNode);
                nodeInSubtree.geometry = null;
              }
            }
          }
          continue;
        }
        // If we reach here, this node either forms a node but not a relayout boundary,
        // or it does not form a node but still contributes to the semantics tree.
        // In both cases, we need to clear the geometry for all the semantics nodes in
        // the subtree.
        for (final _RenderObjectSemantics child in node._semantics._children) {
          child.geometry = null;
        }
      }

      // Used to invalidate the [_RenderObjectSemantics.firstAncestorNodeWithCleanGeometry] cache.
      //
      // Multiple items in [nodesToProcessGeometry] often share the same first
      // ancestor, making redundant searches expensive. Passing this token allows
      // nodes to reuse cached ancestor lookups.
      //
      // See [_RenderObjectSemantics.computeAncestorInfo] for details.
      final treeShapeToken = Object();

      final nodeToEnsureGeometry = <_RenderObjectSemantics>{};
      for (final node in nodesToProcessGeometry) {
        // We need a node that has clean geometry to start from.
        node._semantics.computeAncestorInfo(treeShapeToken);
        if (node._semantics.firstAncestorNodeWithCleanGeometry != null) {
          nodeToEnsureGeometry.add(node._semantics.firstAncestorNodeWithCleanGeometry!);
        }
      }

      for (final _RenderObjectSemantics node
          in nodeToEnsureGeometry.toList()..sort(
            (_RenderObjectSemantics a, _RenderObjectSemantics b) =>
                a.renderObject.depth - b.renderObject.depth,
          )) {
        node.ensureGeometry();
      }

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

      if (!kReleaseMode) {
        FlutterTimeline.startSync('Semantics.ensureSemanticsNode');
      }
      for (final RenderObject node in nodesToProcess.reversed) {
        node._semantics.computeAncestorInfo(treeShapeToken);
        final targets = <_RenderObjectSemantics>[];
        if (node._semantics.geometryDirty) {
          if (node._semantics.firstAncestorNodeWithCleanGeometry != null) {
            targets.add(node._semantics.firstAncestorNodeWithCleanGeometry!);
          }
        } else {
          // When this node is a semantics boundary and a layout boundary and its
          // geometry becomes invisible after the ensureGeometry call above,
          // the parent of this node will have to update its semantics subtree to remove
          // this node from its children.
          if (!node._semantics.geometry!.isVisible && !node._semantics.isRoot) {
            final _RenderObjectSemantics? parentInSemanticsTree =
                node._semantics.parentInSemanticsTree;
            if (parentInSemanticsTree != null) {
              if (!parentInSemanticsTree.geometryDirty) {
                targets.add(parentInSemanticsTree);
              } else {
                final _RenderObjectSemantics? firstAncestorNodeWithCleanGeometry =
                    parentInSemanticsTree.firstAncestorNodeWithCleanGeometry;
                // firstAncestorNodeWithCleanGeometry can be null if this is a blocked branch.
                if (firstAncestorNodeWithCleanGeometry != null) {
                  targets.add(firstAncestorNodeWithCleanGeometry);
                }
              }
            }
          }
          targets.add(node._semantics);
        }

        for (final target in targets) {
          if (target.parentDataDirty) {
            // This node can't be updated since it is not in the tree.
            continue;
          }
          target.ensureSemanticsNode();
        }
      }

      assert(() {
        if (rootNode != null) {
          _RenderObjectSemantics.debugCheckForBuilds(rootNode._semantics);
        }
        return true;
      }());

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

      _semanticsOwner!.sendSemanticsUpdate();
      for (final PipelineOwner child in _children) {
        child.flushSemantics();
      }
      assert(
        _nodesNeedingSemanticsUpdate.isEmpty,
        'Child PipelineOwners must not dirty nodes in their parent.',
      );
      assert(
        _nodesNeedingSemanticsGeometryUpdate.isEmpty,
        "Child PipelineOwners must not dirty nodes' geometry 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();
    _nodesNeedingSemanticsUpdate.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;

  // Returns the closest ancestor that determines whether this RenderObject is
  // currently allowed to mutate, and a boolean indicating whether this
  // RenderObject is allowed to mutate.
  //
  // This method must only be called during layout, as mutations are always
  // allowed before layout. A null return value indicates another render subtree
  // is actively performing layout and, in the process, illegally mutating this
  // RenderObject's subtree.
  (RenderObject, bool)? get _debugClosestMutationRoot {
    return switch (this) {
      // This subtree is being mutated in a layout callback.
      RenderObject(_doingThisLayoutWithCallback: true) => (this, true),
      // A different part of the render tree is doing a layout callback,
      // and this subtree is being reparented there, due to global key
      // reparenting.
      RenderObject(
        owner: PipelineOwner(_debugAllowMutationsToDirtySubtrees: true),
        _needsLayout: true,
      ) =>
        (this, true),
      // This is the node currently doing layout.
      RenderObject(_debugMutationsLocked: true) => (this, false),
      RenderObject() => debugLayoutParent?._debugClosestMutationRoot,
    };
  }

  /// 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 isMutationAllowed;
    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) {
        isMutationAllowed = true;
        return true;
      }

      final RenderObject? activeLayoutRoot;
      // If there is no mutation root, this subtree is likely being mutated by a different subtree
      // which is not allowed.
      (activeLayoutRoot, isMutationAllowed) = _debugClosestMutationRoot ?? (null, false);
      if (isMutationAllowed) {
        return true;
      }
      final RenderObject debugActiveLayout = RenderObject.debugActiveLayout!;
      final culpritMethodName = debugActiveLayout.debugDoingThisLayout
          ? 'performLayout'
          : 'performResize';
      final culpritFullMethodName = '${debugActiveLayout.runtimeType}.$culpritMethodName';

      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 isMutationAllowed;
  }

  /// 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], and becomes false during the call to [detach].
  @nonVirtual
  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. Always returns false in non-debug builds.
  ///
  /// It is intended to be used by tests and asserts.
  bool get debugNeedsLayout {
    if (!kDebugMode) {
      return false;
    }
    return _needsLayout;
  }

  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.
  ///
  /// Layout callbacks are a special part of this render object's layout phase:
  /// they are allowed to mutate child lists and dirty render subtrees while the
  /// callback is executing. This flag lets debug-only assertions distinguish
  /// that special callback phase from the regular [performLayout] body.
  ///
  /// This does not imply that a widget rebuild is currently in progress. A
  /// layout callback can trigger rebuild work by mutating the render or element
  /// tree, but this flag only describes the synchronous callback passed to
  /// [invokeLayoutCallback].
  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. Always returns false in non-debug builds.
  ///
  /// 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 {
    if (!kDebugMode) {
      return false;
    }
    return _needsPaint;
  }

  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. Always returns false in non-debug builds.
  ///
  /// It is intended to be used by tests and asserts.
  bool get debugNeedsCompositedLayerUpdate {
    if (!kDebugMode) {
      return false;
    }
    return _needsCompositedLayerUpdate;
  }

  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!._nodesNeedingSemanticsUpdate.add(this);
    owner!._nodesNeedingSemanticsGeometryUpdate.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,
  ) {
    // 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() {
    if (_hasPendingSystemFontsDidChangeCallBack) {
      return;
    }
    _hasPendingSystemFontsDidChangeCallBack = true;

    // The system fonts notification can arrive during any scheduler phase
    // (e.g. midFrameMicrotasks on web when fonts load asynchronously).
    // scheduleFrameCallback is safe to call during any phase; if called
    // mid-frame, the callback runs in the next frame's transient callback
    // phase since handleBeginFrame snapshots and replaces _transientCallbacks.
    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 || (_properties.identifier != null);
    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.accessibilityFocusBlockType != null) {
      config.accessibilityFocusBlockType = _properties.accessibilityFocusBlockType!;
    }
    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.accessibilityFocusBlockType,
  });

  /// 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 AccessibilityFocusBlockType? accessibilityFocusBlockType;

  /// 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 &&
        other.accessibilityFocusBlockType == accessibilityFocusBlockType &&
        setEquals<SemanticsTag>(other.tagsForChildren, tagsForChildren);
  }

  @override
  int get hashCode {
    return Object.hash(
      mergeIntoParent,
      blocksUserActions,
      explicitChildNodes,
      localeForChildren,
      accessibilityFocusBlockType,
      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
/// 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;

  _RenderObjectSemantics? parentInSemanticsTree;

  // Parent in render object order.
  _RenderObjectSemantics? get parent => renderObject.parent?._semantics;

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

  bool get geometryDirty {
    if (isRoot) {
      return false;
    }
    return geometry == null;
  }

  /// Validates the [firstAncestorNodeWithCleanGeometry] cache.
  ///
  /// Updated by [computeAncestorInfo] during [PipelineOwner.flushSemantics] to
  /// prevent redundant ancestor lookups within a single flush cycle.
  Object _currentTreeShapeToken = const Object();

  /// The nearest semantics-forming ancestor node with clean geometry.
  ///
  /// Cached by [computeAncestorInfo] during [PipelineOwner.flushSemantics].
  _RenderObjectSemantics? firstAncestorNodeWithCleanGeometry;

  /// Finds and caches the nearest semantics-forming ancestor with up-to-date geometry.
  ///
  /// The [treeShapeToken] parameter prevents redundant calculation by verifying
  /// whether the tree shape changed since the previous lookup.
  ///
  /// This method requires all dirty nodes in [PipelineOwner._nodesNeedingSemanticsUpdate]
  /// to have completed their [updateChildren] calls.
  ///
  /// See phase 2 in the [_RenderObjectSemantics] documentation.
  void computeAncestorInfo(Object treeShapeToken) {
    if (treeShapeToken == _currentTreeShapeToken) {
      return;
    }
    _currentTreeShapeToken = treeShapeToken;
    if (isRoot) {
      firstAncestorNodeWithCleanGeometry = this;
      return;
    }
    firstAncestorNodeWithCleanGeometry = null;
    if (parentDataDirty) {
      return;
    }
    _RenderObjectSemantics? next;
    if (shouldFormSemanticsNode) {
      if (!geometryDirty) {
        firstAncestorNodeWithCleanGeometry = this;
      }
      next = parentInSemanticsTree;
    } else {
      next = this;
      while (!next!.parentDataDirty && !next.shouldFormSemanticsNode) {
        next = next.parent;
        // The next should be at least at or below the root node. Since
        // root node's parentData is always not dirty and form semantics
        // node, the loop will terminate at or before the root node.
        assert(next != null);
      }
    }

    if (next == null) {
      return;
    }

    if (firstAncestorNodeWithCleanGeometry == null) {
      next.computeAncestorInfo(treeShapeToken);
      firstAncestorNodeWithCleanGeometry = next.firstAncestorNodeWithCleanGeometry;
    }
  }

  /// 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 => parent == null;

  bool get _needsMergingSiblingNodesIntoSelf {
    return configProvider.effective.isMergingSemanticsOfDescendants &&
        _producedSiblingNodesAndOwners.isNotEmpty;
  }

  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);
  }

  static void debugCheckForBuilds(_RenderObjectSemantics node) {
    assert(node.built);
    node._children.forEach(debugCheckForBuilds);
  }

  /// 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 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;

    AccessibilityFocusBlockType accessibilityFocusBlockType;
    if (parentData?.accessibilityFocusBlockType == AccessibilityFocusBlockType.blockSubtree) {
      accessibilityFocusBlockType = AccessibilityFocusBlockType.blockSubtree;
    } else {
      accessibilityFocusBlockType = configProvider.effective.accessibilityFocusBlockType;
    }

    // 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,
      accessibilityFocusBlockType: accessibilityFocusBlockType,
      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.
    final Set<_RenderObjectSemantics> oldChildren = _children.toSet();
    _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) {
        for (final _RenderObjectSemantics child in childSemantics._children) {
          child.parentInSemanticsTree = childSemantics;
        }
        // In general geometry is only dirty during the first build or markNeedsLayout.
        // In both cases, the renderobject will be added to the list of nodes needing
        // geometry update.
        //
        // This specific case can happen if a parent somwhere above this node decided to
        // conditionally include this node.
        //
        // For example, render object A->B->C, where A is the root and all of them
        // creates semantics nodes.
        //
        // Frame 1: B and C both mark layout dirty, and B suddenly decide not to
        // inlcude C in the semantics tree.
        //
        // In this case, C's geometry will remain dirty because it is considered as
        // blocked.
        //
        // Frame 2: B is marked dirty again and decide C should be included
        // in the semantics tree. We will run into this situation where C's geometry
        // is dirty but it is not in the _nodesNeedingSemanticsGeometryUpdate.
        if (childSemantics.geometryDirty) {
          renderObject.owner!._nodesNeedingSemanticsGeometryUpdate.add(childSemantics.renderObject);
        }
        _children.add(childSemantics);
      } else {
        _children.addAll(childSemantics._children);
        siblingMergeGroups.addAll(childSemantics.siblingMergeGroups);
      }
    }
    // If this node is the root, then all of its children are in the semantics tree.
    // Otherwise, we won't know if this node shouldFormSemanticsNode until the parent
    // of this node determines it.
    if (isRoot || configProvider.effective.isSemanticBoundary) {
      for (final _RenderObjectSemantics child in _children) {
        child.parentInSemanticsTree = this;
      }
    }
    oldChildren.removeAll(_children);
    for (final removedChild in oldChildren) {
      if (removedChild.parentInSemanticsTree == this) {
        removedChild.parentInSemanticsTree = null;
      }
    }

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

    if (blocksUserAction != configProvider.effective.isBlockingUserActions) {
      configProvider.updateConfig((SemanticsConfiguration config) {
        config.isBlockingUserActions = blocksUserAction;
      });
    }
    if (localeForChildren != configProvider.effective.locale) {
      configProvider.updateConfig((SemanticsConfiguration config) {
        config.locale = localeForChildren;
      });
    }
    if (accessibilityFocusBlockType != AccessibilityFocusBlockType.none) {
      configProvider.updateConfig((SemanticsConfiguration config) {
        config.isFocused = null;
      });
    }
  }

  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,
        accessibilityFocusBlockType: childParentData.accessibilityFocusBlockType,
        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;
    }
    final bool wasParentDataDirty = parentDataDirty;
    // Parent data changes may result in node formation changes.
    markNeedsBuild();
    parentData = newParentData;
    if (wasParentDataDirty) {
      geometry = null;
    }
    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 the dirty
  /// children's subtree in [_children].
  ///
  /// This method does 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() {
    assert(!geometryDirty);
    if (isRoot) {
      if (geometry?.rect != renderObject.semanticBounds) {
        markNeedsBuild();
      }
      geometry = _SemanticsGeometry.root(renderObject.semanticBounds);
    }
    _updateChildGeometry(onlyDirtyChildren: true);
  }

  void _updateChildGeometry({bool onlyDirtyChildren = false}) {
    assert(geometry != null);
    final _SemanticsGeometry parentGeometry = geometry!;
    for (final _RenderObjectSemantics child in _children) {
      if (onlyDirtyChildren && !child.geometryDirty) {
        continue;
      }
      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,
            )) {
      if (onlyDirtyChildren && !explicitSiblingChild.geometryDirty) {
        continue;
      }
      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}) {
    final _SemanticsGeometry? currentGeometry = geometry;
    geometry = newGeometry;
    if (currentGeometry != null) {
      final bool isSemanticsHidden =
          configProvider.original.isHidden ||
          (!(parentData?.mergeIntoParent ?? false) && newGeometry.hidden);
      final sizeChanged = currentGeometry.rect.size != newGeometry.rect.size;
      final visibilityChanged = configProvider.effective.isHidden != isSemanticsHidden;
      if (!sizeChanged && !visibilityChanged) {
        return;
      }
    }
    markNeedsBuild();
    _updateChildGeometry();
  }

  /// Ensures the semantics nodes from this render object semantics subtree are
  /// generated and up to date.
  ///
  /// This method does 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(shouldFormSemanticsNode);
    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) {
      _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) {
      if (child.parentDataDirty) {
        continue;
      }
      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);
    final bool isSemanticsHidden =
        configProvider.original.isHidden ||
        (!(parentData?.mergeIntoParent ?? false) && geometry!.hidden);
    if (configProvider.effective.isHidden != isSemanticsHidden) {
      configProvider.updateConfig((SemanticsConfiguration config) {
        config.isHidden = isSemanticsHidden;
      });
    }
    if (configProvider.effective.isSemanticBoundary) {
      if (_needsMergingSiblingNodesIntoSelf) {
        // This node needs to merge the sibling nodes in the sub tree.
        //
        // Create an inner node to hold the configuration and children, and the cachedSemanticsNode will
        // hold the inner node and the sibling nodes so that all of them can be merged together.
        final innerNode = SemanticsNode(showOnScreen: renderObject.showOnScreen);
        renderObject.assembleSemanticsNode(innerNode, configProvider.effective, children);

        final config = SemanticsConfiguration()
          ..isSemanticBoundary = true
          ..isMergingSemanticsOfDescendants = true;

        node.updateWith(
          config: config,
          childrenInInversePaintOrder: <SemanticsNode>[
            innerNode,
            ..._producedSiblingNodesAndOwners.keys,
          ],
        );
      } else {
        renderObject.assembleSemanticsNode(node, configProvider.effective, children);
      }
    } else {
      assert(!configProvider.effective.isMergingSemanticsOfDescendants);
      node.updateWith(config: configProvider.effective, childrenInInversePaintOrder: children);
    }
  }

  void _produceSemanticsNode({required Set<int> usedSemanticsIds}) {
    assert(!built);
    semanticsNodes.clear();
    _producedSiblingNodesAndOwners.clear();

    final SemanticsNode node = cachedSemanticsNode ??= _createSemanticsNode();
    node
      ..isMergedIntoParent = (parentData?.mergeIntoParent ?? false)
      ..tags = parentData?.tagsForChildren;
    _updateSemanticsNodeGeometry();

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

    // At this point, the cachedSemanticsNode should be latest semantics node
    // representing this render object and _producedSiblingNodesAndOwners contains the latest
    // sibling nodes.
    semanticsNodes.add(node);
    if (!_needsMergingSiblingNodesIntoSelf) {
      semanticsNodes.addAll(_producedSiblingNodesAndOwners.keys);
    }
    built = true;
  }

  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;

        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!;
    node
      ..rect = nodeGeometry.rect
      ..transform = nodeGeometry.transform
      ..parentSemanticsClipRect = nodeGeometry.semanticsClipRect
      ..parentPaintClipRect = nodeGeometry.paintClipRect;
  }

  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() {
    renderObject.owner!._nodesNeedingSemanticsGeometryUpdate.add(renderObject);
    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.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._nodesNeedingSemanticsUpdate]
      // 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._nodesNeedingSemanticsUpdate] 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!._nodesNeedingSemanticsUpdate.remove(renderObject);
    }

    if (!node._semantics.parentDataDirty || node._semantics.isRoot) {
      if (renderObject.owner != null) {
        assert(node._semantics.configProvider.effective.isSemanticBoundary || node.parent == null);
        if (renderObject.owner!._nodesNeedingSemanticsUpdate.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 _children
        .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: parentDataDirty, ifTrue: 'NO PARENT DATA'));
    properties.add(FlagProperty('geometry', value: geometryDirty, ifTrue: 'NO GEOMETRY'));
    properties.add(
      FlagProperty(
        'semanticsBlock',
        value: configProvider.effective.isBlockingSemanticsOfPreviouslyPaintedNodes,
        ifTrue: 'BLOCK PREVIOUS',
      ),
    );
    if (!parentDataDirty && 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() {
  if (RendererBinding.instance.renderViews.isEmpty) {
    debugPrint('No render tree root was added to the binding.');
    return;
  }

  debugPrint(
    <String>[
      for (final RenderObject renderView in RendererBinding.instance.renderViews)
        _debugCollectRenderObjectSemanticsTrees(renderView),
    ].join('\n\n'),
  );
}

String _debugCollectRenderObjectSemanticsTrees(RenderObject root) {
  return root._semantics.toStringDeep();
}

/// 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;

  bool get isVisible => !rect.isEmpty && !transform.isZero();

  /// 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);
}
