mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
computeDryBaseline
for rendering / widgets RenderBoxes (#146143)
RenderWrap, Table, Overlay / Stack are not included
This commit is contained in:
parent
99874c1c57
commit
ef7019e801
@ -4,7 +4,7 @@
|
||||
|
||||
import 'dart:collection';
|
||||
import 'dart:math' as math;
|
||||
import 'dart:ui' as ui show BoxHeightStyle, BoxWidthStyle, LineMetrics, PlaceholderAlignment, TextBox;
|
||||
import 'dart:ui' as ui show BoxHeightStyle, BoxWidthStyle, LineMetrics, TextBox;
|
||||
|
||||
import 'package:characters/characters.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@ -777,7 +777,6 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin,
|
||||
_textPainter.text = value;
|
||||
_cachedAttributedValue = null;
|
||||
_cachedCombinedSemanticsInfos = null;
|
||||
_canComputeIntrinsicsCached = null;
|
||||
markNeedsLayout();
|
||||
markNeedsSemanticsUpdate();
|
||||
}
|
||||
@ -1828,10 +1827,11 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin,
|
||||
|
||||
@override
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
if (!_canComputeIntrinsics) {
|
||||
return 0.0;
|
||||
}
|
||||
final List<PlaceholderDimensions> placeholderDimensions = layoutInlineChildren(double.infinity, (RenderBox child, BoxConstraints constraints) => Size(child.getMinIntrinsicWidth(double.infinity), 0.0));
|
||||
final List<PlaceholderDimensions> placeholderDimensions = layoutInlineChildren(
|
||||
double.infinity,
|
||||
(RenderBox child, BoxConstraints constraints) => Size(child.getMinIntrinsicWidth(double.infinity), 0.0),
|
||||
ChildLayoutHelper.getDryBaseline,
|
||||
);
|
||||
final (double minWidth, double maxWidth) = _adjustConstraints();
|
||||
return (_textIntrinsics
|
||||
..setPlaceholderDimensions(placeholderDimensions)
|
||||
@ -1841,14 +1841,12 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin,
|
||||
|
||||
@override
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
if (!_canComputeIntrinsics) {
|
||||
return 0.0;
|
||||
}
|
||||
final List<PlaceholderDimensions> placeholderDimensions = layoutInlineChildren(
|
||||
double.infinity,
|
||||
// Height and baseline is irrelevant as all text will be laid
|
||||
// out in a single line. Therefore, using 0.0 as a dummy for the height.
|
||||
(RenderBox child, BoxConstraints constraints) => Size(child.getMaxIntrinsicWidth(double.infinity), 0.0),
|
||||
ChildLayoutHelper.getDryBaseline,
|
||||
);
|
||||
final (double minWidth, double maxWidth) = _adjustConstraints();
|
||||
return (_textIntrinsics
|
||||
@ -1926,10 +1924,9 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin,
|
||||
|
||||
@override
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
if (!_canComputeIntrinsics) {
|
||||
return 0.0;
|
||||
}
|
||||
_textIntrinsics.setPlaceholderDimensions(layoutInlineChildren(width, ChildLayoutHelper.dryLayoutChild));
|
||||
_textIntrinsics.setPlaceholderDimensions(
|
||||
layoutInlineChildren(width, ChildLayoutHelper.dryLayoutChild, ChildLayoutHelper.getDryBaseline),
|
||||
);
|
||||
return _preferredHeight(width);
|
||||
}
|
||||
|
||||
@ -2291,35 +2288,12 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin,
|
||||
);
|
||||
}
|
||||
|
||||
bool _canComputeDryLayoutForInlineWidgets() {
|
||||
return text?.visitChildren((InlineSpan span) {
|
||||
return (span is! PlaceholderSpan) || switch (span.alignment) {
|
||||
ui.PlaceholderAlignment.baseline ||
|
||||
ui.PlaceholderAlignment.aboveBaseline ||
|
||||
ui.PlaceholderAlignment.belowBaseline => false,
|
||||
ui.PlaceholderAlignment.top ||
|
||||
ui.PlaceholderAlignment.middle ||
|
||||
ui.PlaceholderAlignment.bottom => true,
|
||||
};
|
||||
}) ?? true;
|
||||
}
|
||||
|
||||
bool? _canComputeIntrinsicsCached;
|
||||
bool get _canComputeIntrinsics => _canComputeIntrinsicsCached ??= _canComputeDryLayoutForInlineWidgets();
|
||||
|
||||
@override
|
||||
@protected
|
||||
Size computeDryLayout(covariant BoxConstraints constraints) {
|
||||
if (!_canComputeIntrinsics) {
|
||||
assert(debugCannotComputeDryLayout(
|
||||
reason: 'Dry layout not available for alignments that require baseline.',
|
||||
));
|
||||
return Size.zero;
|
||||
}
|
||||
|
||||
final (double minWidth, double maxWidth) = _adjustConstraints(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
|
||||
_textIntrinsics
|
||||
..setPlaceholderDimensions(layoutInlineChildren(constraints.maxWidth, ChildLayoutHelper.dryLayoutChild))
|
||||
..setPlaceholderDimensions(layoutInlineChildren(constraints.maxWidth, ChildLayoutHelper.dryLayoutChild, ChildLayoutHelper.getDryBaseline))
|
||||
..layout(minWidth: minWidth, maxWidth: maxWidth);
|
||||
final double width = forceLine
|
||||
? constraints.maxWidth
|
||||
@ -2330,7 +2304,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin,
|
||||
@override
|
||||
void performLayout() {
|
||||
final BoxConstraints constraints = this.constraints;
|
||||
_placeholderDimensions = layoutInlineChildren(constraints.maxWidth, ChildLayoutHelper.layoutChild);
|
||||
_placeholderDimensions = layoutInlineChildren(constraints.maxWidth, ChildLayoutHelper.layoutChild, ChildLayoutHelper.getBaseline);
|
||||
final (double minWidth, double maxWidth) = _adjustConstraints(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
|
||||
_textPainter
|
||||
..setPlaceholderDimensions(_placeholderDimensions)
|
||||
|
@ -63,6 +63,39 @@ class RenderListBody extends RenderBox
|
||||
/// [axisDirection].
|
||||
Axis get mainAxis => axisDirectionToAxis(axisDirection);
|
||||
|
||||
@override
|
||||
double? computeDryBaseline(covariant BoxConstraints constraints, TextBaseline baseline) {
|
||||
assert(_debugCheckConstraints(constraints));
|
||||
RenderBox? child;
|
||||
final RenderBox? Function(RenderBox) nextChild;
|
||||
switch (axisDirection) {
|
||||
case AxisDirection.right:
|
||||
case AxisDirection.left:
|
||||
final BoxConstraints childConstraints = BoxConstraints.tightFor(height: constraints.maxHeight);
|
||||
BaselineOffset baselineOffset = BaselineOffset.noBaseline;
|
||||
for (child = firstChild; child != null; child = childAfter(child)) {
|
||||
baselineOffset = baselineOffset.minOf(BaselineOffset(child.getDryBaseline(childConstraints, baseline)));
|
||||
}
|
||||
return baselineOffset.offset;
|
||||
case AxisDirection.up:
|
||||
child = lastChild;
|
||||
nextChild = childBefore;
|
||||
case AxisDirection.down:
|
||||
child = firstChild;
|
||||
nextChild = childAfter;
|
||||
}
|
||||
final BoxConstraints childConstraints = BoxConstraints.tightFor(width: constraints.maxWidth);
|
||||
double mainAxisExtent = 0.0;
|
||||
for (; child != null; child = nextChild(child)) {
|
||||
final double? childBaseline = child.getDryBaseline(childConstraints, baseline);
|
||||
if (childBaseline != null) {
|
||||
return childBaseline + mainAxisExtent;
|
||||
}
|
||||
mainAxisExtent += child.getDryLayout(childConstraints).height;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
@protected
|
||||
Size computeDryLayout(covariant BoxConstraints constraints) {
|
||||
|
@ -125,14 +125,14 @@ mixin RenderInlineChildrenContainerDefaults on RenderBox, ContainerRenderObjectM
|
||||
}
|
||||
}
|
||||
|
||||
static PlaceholderDimensions _layoutChild(RenderBox child, double maxWidth, ChildLayouter layoutChild) {
|
||||
static PlaceholderDimensions _layoutChild(RenderBox child, BoxConstraints childConstraints, ChildLayouter layoutChild, ChildBaselineGetter getBaseline) {
|
||||
final TextParentData parentData = child.parentData! as TextParentData;
|
||||
final PlaceholderSpan? span = parentData.span;
|
||||
assert(span != null);
|
||||
return span == null
|
||||
? PlaceholderDimensions.empty
|
||||
: PlaceholderDimensions(
|
||||
size: layoutChild(child, BoxConstraints(maxWidth: maxWidth)),
|
||||
size: layoutChild(child, childConstraints),
|
||||
alignment: span.alignment,
|
||||
baseline: span.baseline,
|
||||
baselineOffset: switch (span.alignment) {
|
||||
@ -141,17 +141,21 @@ mixin RenderInlineChildrenContainerDefaults on RenderBox, ContainerRenderObjectM
|
||||
ui.PlaceholderAlignment.bottom ||
|
||||
ui.PlaceholderAlignment.middle ||
|
||||
ui.PlaceholderAlignment.top => null,
|
||||
ui.PlaceholderAlignment.baseline => child.getDistanceToBaseline(span.baseline!),
|
||||
ui.PlaceholderAlignment.baseline => getBaseline(child, childConstraints, span.baseline!),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Computes the layout for every inline child using the given `layoutChild`
|
||||
/// function and the `maxWidth` constraint.
|
||||
/// Computes the layout for every inline child using the `maxWidth` constraint.
|
||||
///
|
||||
/// Returns a list of [PlaceholderDimensions], representing the layout results
|
||||
/// for each child managed by the [ContainerRenderObjectMixin] mixin.
|
||||
///
|
||||
/// The `getChildBaseline` parameter and the `layoutChild` parameter must be
|
||||
/// consistent: if `layoutChild` computes the size of the child without
|
||||
/// modifying the actual layout of that child, then `getChildBaseline` must
|
||||
/// also be "dry", and vice versa.
|
||||
///
|
||||
/// Since this method does not impose a maximum height constraint on the
|
||||
/// inline children, some children may become taller than this [RenderBox].
|
||||
///
|
||||
@ -160,10 +164,11 @@ mixin RenderInlineChildrenContainerDefaults on RenderBox, ContainerRenderObjectM
|
||||
/// * [TextPainter.setPlaceholderDimensions], the method that usually takes
|
||||
/// the layout results from this method as the input.
|
||||
@protected
|
||||
List<PlaceholderDimensions> layoutInlineChildren(double maxWidth, ChildLayouter layoutChild) {
|
||||
List<PlaceholderDimensions> layoutInlineChildren(double maxWidth, ChildLayouter layoutChild, ChildBaselineGetter getChildBaseline) {
|
||||
final BoxConstraints constraints = BoxConstraints(maxWidth: maxWidth);
|
||||
return <PlaceholderDimensions>[
|
||||
for (RenderBox? child = firstChild; child != null; child = childAfter(child))
|
||||
_layoutChild(child, maxWidth, layoutChild),
|
||||
_layoutChild(child, constraints, layoutChild, getChildBaseline),
|
||||
];
|
||||
}
|
||||
|
||||
@ -352,7 +357,6 @@ class RenderParagraph extends RenderBox with ContainerRenderObjectMixin<RenderBo
|
||||
case RenderComparison.paint:
|
||||
_textPainter.text = value;
|
||||
_cachedAttributedLabels = null;
|
||||
_canComputeIntrinsicsCached = null;
|
||||
_cachedCombinedSemanticsInfos = null;
|
||||
markNeedsPaint();
|
||||
markNeedsSemanticsUpdate();
|
||||
@ -361,7 +365,6 @@ class RenderParagraph extends RenderBox with ContainerRenderObjectMixin<RenderBo
|
||||
_overflowShader = null;
|
||||
_cachedAttributedLabels = null;
|
||||
_cachedCombinedSemanticsInfos = null;
|
||||
_canComputeIntrinsicsCached = null;
|
||||
markNeedsLayout();
|
||||
_removeSelectionRegistrarSubscription();
|
||||
_disposeSelectableFragments();
|
||||
@ -671,12 +674,10 @@ class RenderParagraph extends RenderBox with ContainerRenderObjectMixin<RenderBo
|
||||
|
||||
@override
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
if (!_canComputeIntrinsics()) {
|
||||
return 0.0;
|
||||
}
|
||||
final List<PlaceholderDimensions> placeholderDimensions = layoutInlineChildren(
|
||||
double.infinity,
|
||||
(RenderBox child, BoxConstraints constraints) => Size(child.getMinIntrinsicWidth(double.infinity), 0.0),
|
||||
ChildLayoutHelper.getDryBaseline,
|
||||
);
|
||||
return (_textIntrinsics..setPlaceholderDimensions(placeholderDimensions)..layout())
|
||||
.minIntrinsicWidth;
|
||||
@ -684,25 +685,20 @@ class RenderParagraph extends RenderBox with ContainerRenderObjectMixin<RenderBo
|
||||
|
||||
@override
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
if (!_canComputeIntrinsics()) {
|
||||
return 0.0;
|
||||
}
|
||||
final List<PlaceholderDimensions> placeholderDimensions = layoutInlineChildren(
|
||||
double.infinity,
|
||||
// Height and baseline is irrelevant as all text will be laid
|
||||
// out in a single line. Therefore, using 0.0 as a dummy for the height.
|
||||
(RenderBox child, BoxConstraints constraints) => Size(child.getMaxIntrinsicWidth(double.infinity), 0.0),
|
||||
ChildLayoutHelper.getDryBaseline,
|
||||
);
|
||||
return (_textIntrinsics..setPlaceholderDimensions(placeholderDimensions)..layout())
|
||||
.maxIntrinsicWidth;
|
||||
}
|
||||
|
||||
double _computeIntrinsicHeight(double width) {
|
||||
if (!_canComputeIntrinsics()) {
|
||||
return 0.0;
|
||||
}
|
||||
return (_textIntrinsics
|
||||
..setPlaceholderDimensions(layoutInlineChildren(width, ChildLayoutHelper.dryLayoutChild))
|
||||
..setPlaceholderDimensions(layoutInlineChildren(width, ChildLayoutHelper.dryLayoutChild, ChildLayoutHelper.getDryBaseline))
|
||||
..layout(minWidth: width, maxWidth: _adjustMaxWidth(width)))
|
||||
.height;
|
||||
}
|
||||
@ -717,52 +713,6 @@ class RenderParagraph extends RenderBox with ContainerRenderObjectMixin<RenderBo
|
||||
return _computeIntrinsicHeight(width);
|
||||
}
|
||||
|
||||
@override
|
||||
double computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
assert(!debugNeedsLayout);
|
||||
assert(constraints.debugAssertIsValid());
|
||||
_layoutTextWithConstraints(constraints);
|
||||
// TODO(garyq): Since our metric for ideographic baseline is currently
|
||||
// inaccurate and the non-alphabetic baselines are based off of the
|
||||
// alphabetic baseline, we use the alphabetic for now to produce correct
|
||||
// layouts. We should eventually change this back to pass the `baseline`
|
||||
// property when the ideographic baseline is properly implemented
|
||||
// (https://github.com/flutter/flutter/issues/22625).
|
||||
return _textPainter.computeDistanceToActualBaseline(TextBaseline.alphabetic);
|
||||
}
|
||||
|
||||
/// Whether all inline widget children of this [RenderBox] support dry layout
|
||||
/// calculation.
|
||||
bool _canComputeDryLayoutForInlineWidgets() {
|
||||
// Dry layout cannot be calculated without a full layout for
|
||||
// alignments that require the baseline (baseline, aboveBaseline,
|
||||
// belowBaseline).
|
||||
return text.visitChildren((InlineSpan span) {
|
||||
return (span is! PlaceholderSpan) || switch (span.alignment) {
|
||||
ui.PlaceholderAlignment.baseline ||
|
||||
ui.PlaceholderAlignment.aboveBaseline ||
|
||||
ui.PlaceholderAlignment.belowBaseline => false,
|
||||
ui.PlaceholderAlignment.top ||
|
||||
ui.PlaceholderAlignment.middle ||
|
||||
ui.PlaceholderAlignment.bottom => true,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
bool? _canComputeIntrinsicsCached;
|
||||
// Intrinsics cannot be calculated without a full layout for
|
||||
// alignments that require the baseline (baseline, aboveBaseline,
|
||||
// belowBaseline).
|
||||
bool _canComputeIntrinsics() {
|
||||
final bool returnValue = _canComputeIntrinsicsCached ??= _canComputeDryLayoutForInlineWidgets();
|
||||
assert(
|
||||
returnValue || RenderObject.debugCheckingIntrinsics,
|
||||
'Intrinsics are not available for PlaceholderAlignment.baseline, '
|
||||
'PlaceholderAlignment.aboveBaseline, or PlaceholderAlignment.belowBaseline.',
|
||||
);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
@override
|
||||
bool hitTestSelf(Offset position) => true;
|
||||
|
||||
@ -822,23 +772,40 @@ class RenderParagraph extends RenderBox with ContainerRenderObjectMixin<RenderBo
|
||||
@override
|
||||
@protected
|
||||
Size computeDryLayout(covariant BoxConstraints constraints) {
|
||||
if (!_canComputeIntrinsics()) {
|
||||
assert(debugCannotComputeDryLayout(
|
||||
reason: 'Dry layout not available for alignments that require baseline.',
|
||||
));
|
||||
return Size.zero;
|
||||
}
|
||||
final Size size = (_textIntrinsics
|
||||
..setPlaceholderDimensions(layoutInlineChildren(constraints.maxWidth, ChildLayoutHelper.dryLayoutChild))
|
||||
..setPlaceholderDimensions(layoutInlineChildren(constraints.maxWidth, ChildLayoutHelper.dryLayoutChild, ChildLayoutHelper.getDryBaseline))
|
||||
..layout(minWidth: constraints.minWidth, maxWidth: _adjustMaxWidth(constraints.maxWidth)))
|
||||
.size;
|
||||
return constraints.constrain(size);
|
||||
}
|
||||
|
||||
@override
|
||||
double computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
assert(!debugNeedsLayout);
|
||||
assert(constraints.debugAssertIsValid());
|
||||
_layoutTextWithConstraints(constraints);
|
||||
// TODO(garyq): Since our metric for ideographic baseline is currently
|
||||
// inaccurate and the non-alphabetic baselines are based off of the
|
||||
// alphabetic baseline, we use the alphabetic for now to produce correct
|
||||
// layouts. We should eventually change this back to pass the `baseline`
|
||||
// property when the ideographic baseline is properly implemented
|
||||
// (https://github.com/flutter/flutter/issues/22625).
|
||||
return _textPainter.computeDistanceToActualBaseline(TextBaseline.alphabetic);
|
||||
}
|
||||
|
||||
@override
|
||||
double computeDryBaseline(covariant BoxConstraints constraints, TextBaseline baseline) {
|
||||
assert(constraints.debugAssertIsValid());
|
||||
_textIntrinsics
|
||||
..setPlaceholderDimensions(layoutInlineChildren(constraints.maxWidth, ChildLayoutHelper.dryLayoutChild, ChildLayoutHelper.getDryBaseline))
|
||||
..layout(minWidth: constraints.minWidth, maxWidth: _adjustMaxWidth(constraints.maxWidth));
|
||||
return _textIntrinsics.computeDistanceToActualBaseline(TextBaseline.alphabetic);
|
||||
}
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
final BoxConstraints constraints = this.constraints;
|
||||
_placeholderDimensions = layoutInlineChildren(constraints.maxWidth, ChildLayoutHelper.layoutChild);
|
||||
_placeholderDimensions = layoutInlineChildren(constraints.maxWidth, ChildLayoutHelper.layoutChild, ChildLayoutHelper.getBaseline);
|
||||
_layoutTextWithConstraints(constraints);
|
||||
positionInlineChildren(_textPainter.inlinePlaceholderBoxes!);
|
||||
|
||||
|
@ -94,6 +94,12 @@ mixin RenderProxyBoxMixin<T extends RenderBox> on RenderBox, RenderObjectWithChi
|
||||
?? super.computeDistanceToActualBaseline(baseline);
|
||||
}
|
||||
|
||||
@override
|
||||
@protected
|
||||
double? computeDryBaseline(covariant BoxConstraints constraints, TextBaseline baseline) {
|
||||
return child?.getDryBaseline(constraints, baseline);
|
||||
}
|
||||
|
||||
@override
|
||||
@protected
|
||||
Size computeDryLayout(covariant BoxConstraints constraints) {
|
||||
@ -292,11 +298,8 @@ class RenderConstrainedBox extends RenderProxyBox {
|
||||
@override
|
||||
@protected
|
||||
Size computeDryLayout(covariant BoxConstraints constraints) {
|
||||
if (child != null) {
|
||||
return child!.getDryLayout(_additionalConstraints.enforce(constraints));
|
||||
} else {
|
||||
return _additionalConstraints.enforce(constraints).constrain(Size.zero);
|
||||
}
|
||||
return child?.getDryLayout(_additionalConstraints.enforce(constraints))
|
||||
?? _additionalConstraints.enforce(constraints).constrain(Size.zero);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -566,6 +569,11 @@ class RenderAspectRatio extends RenderProxyBox {
|
||||
return _applyAspectRatio(constraints);
|
||||
}
|
||||
|
||||
@override
|
||||
double? computeDryBaseline(BoxConstraints constraints, TextBaseline baseline) {
|
||||
return super.computeDryBaseline(BoxConstraints.tight(getDryLayout(constraints)), baseline);
|
||||
}
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
size = getDryLayout(constraints);
|
||||
@ -702,22 +710,16 @@ class RenderIntrinsicWidth extends RenderProxyBox {
|
||||
return _applyStep(height, _stepHeight);
|
||||
}
|
||||
|
||||
BoxConstraints _childConstraints(RenderBox child, BoxConstraints constraints) {
|
||||
return constraints.tighten(
|
||||
width: constraints.hasTightWidth ? null : _applyStep(child.getMaxIntrinsicWidth(constraints.maxHeight), _stepWidth),
|
||||
height: stepHeight == null ? null : _applyStep(child.getMaxIntrinsicHeight(constraints.maxWidth), _stepHeight),
|
||||
);
|
||||
}
|
||||
|
||||
Size _computeSize({required ChildLayouter layoutChild, required BoxConstraints constraints}) {
|
||||
if (child != null) {
|
||||
if (!constraints.hasTightWidth) {
|
||||
final double width = child!.getMaxIntrinsicWidth(constraints.maxHeight);
|
||||
assert(width.isFinite);
|
||||
constraints = constraints.tighten(width: _applyStep(width, _stepWidth));
|
||||
}
|
||||
if (_stepHeight != null) {
|
||||
final double height = child!.getMaxIntrinsicHeight(constraints.maxWidth);
|
||||
assert(height.isFinite);
|
||||
constraints = constraints.tighten(height: _applyStep(height, _stepHeight));
|
||||
}
|
||||
return layoutChild(child!, constraints);
|
||||
} else {
|
||||
return constraints.smallest;
|
||||
}
|
||||
final RenderBox? child = this.child;
|
||||
return child == null ? constraints.smallest : layoutChild(child, _childConstraints(child, constraints));
|
||||
}
|
||||
|
||||
@override
|
||||
@ -729,6 +731,12 @@ class RenderIntrinsicWidth extends RenderProxyBox {
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
double? computeDryBaseline(BoxConstraints constraints, TextBaseline baseline) {
|
||||
final RenderBox? child = this.child;
|
||||
return child?.getDryBaseline(_childConstraints(child, constraints), baseline);
|
||||
}
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
size = _computeSize(
|
||||
@ -808,17 +816,15 @@ class RenderIntrinsicHeight extends RenderProxyBox {
|
||||
return getMaxIntrinsicHeight(width);
|
||||
}
|
||||
|
||||
BoxConstraints _childConstraints(RenderBox child, BoxConstraints constraints) {
|
||||
return constraints.hasTightHeight
|
||||
? constraints
|
||||
: constraints.tighten(height: child.getMaxIntrinsicHeight(constraints.maxWidth));
|
||||
}
|
||||
|
||||
Size _computeSize({required ChildLayouter layoutChild, required BoxConstraints constraints}) {
|
||||
if (child != null) {
|
||||
if (!constraints.hasTightHeight) {
|
||||
final double height = child!.getMaxIntrinsicHeight(constraints.maxWidth);
|
||||
assert(height.isFinite);
|
||||
constraints = constraints.tighten(height: height);
|
||||
}
|
||||
return layoutChild(child!, constraints);
|
||||
} else {
|
||||
return constraints.smallest;
|
||||
}
|
||||
final RenderBox? child = this.child;
|
||||
return child == null ? constraints.smallest : layoutChild(child, _childConstraints(child, constraints));
|
||||
}
|
||||
|
||||
@override
|
||||
@ -830,6 +836,12 @@ class RenderIntrinsicHeight extends RenderProxyBox {
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
double? computeDryBaseline(BoxConstraints constraints, TextBaseline baseline) {
|
||||
final RenderBox? child = this.child;
|
||||
return child?.getDryBaseline(_childConstraints(child, constraints), baseline);
|
||||
}
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
size = _computeSize(
|
||||
@ -2596,15 +2608,9 @@ class RenderFittedBox extends RenderProxyBox {
|
||||
_clipBehavior = clipBehavior,
|
||||
super(child);
|
||||
|
||||
Alignment _resolve() => _resolvedAlignment ??= alignment.resolve(textDirection);
|
||||
Alignment? _resolvedAlignment;
|
||||
|
||||
void _resolve() {
|
||||
if (_resolvedAlignment != null) {
|
||||
return;
|
||||
}
|
||||
_resolvedAlignment = alignment.resolve(textDirection);
|
||||
}
|
||||
|
||||
void _markNeedResolution() {
|
||||
_resolvedAlignment = null;
|
||||
markNeedsPaint();
|
||||
@ -2772,13 +2778,13 @@ class RenderFittedBox extends RenderProxyBox {
|
||||
_hasVisualOverflow = false;
|
||||
_transform = Matrix4.identity();
|
||||
} else {
|
||||
_resolve();
|
||||
final Alignment resolvedAlignment = _resolve();
|
||||
final Size childSize = child!.size;
|
||||
final FittedSizes sizes = applyBoxFit(_fit, childSize, size);
|
||||
final double scaleX = sizes.destination.width / sizes.source.width;
|
||||
final double scaleY = sizes.destination.height / sizes.source.height;
|
||||
final Rect sourceRect = _resolvedAlignment!.inscribe(sizes.source, Offset.zero & childSize);
|
||||
final Rect destinationRect = _resolvedAlignment!.inscribe(sizes.destination, Offset.zero & size);
|
||||
final Rect sourceRect = resolvedAlignment.inscribe(sizes.source, Offset.zero & childSize);
|
||||
final Rect destinationRect = resolvedAlignment.inscribe(sizes.destination, Offset.zero & size);
|
||||
_hasVisualOverflow = sourceRect.width < childSize.width || sourceRect.height < childSize.height;
|
||||
assert(scaleX.isFinite && scaleY.isFinite);
|
||||
_transform = Matrix4.translationValues(destinationRect.left, destinationRect.top, 0.0)
|
||||
@ -3699,6 +3705,11 @@ class RenderOffstage extends RenderProxyBox {
|
||||
@override
|
||||
bool get sizedByParent => offstage;
|
||||
|
||||
@override
|
||||
double? computeDryBaseline(BoxConstraints constraints, TextBaseline baseline) {
|
||||
return offstage ? null : super.computeDryBaseline(constraints, baseline);
|
||||
}
|
||||
|
||||
@override
|
||||
@protected
|
||||
Size computeDryLayout(covariant BoxConstraints constraints) {
|
||||
|
@ -114,18 +114,15 @@ class RenderPadding extends RenderShiftedBox {
|
||||
_padding = padding,
|
||||
super(child);
|
||||
|
||||
EdgeInsets? _resolvedPadding;
|
||||
|
||||
void _resolve() {
|
||||
if (_resolvedPadding != null) {
|
||||
return;
|
||||
}
|
||||
_resolvedPadding = padding.resolve(textDirection);
|
||||
assert(_resolvedPadding!.isNonNegative);
|
||||
EdgeInsets? _resolvedPaddingCache;
|
||||
EdgeInsets get _resolvedPadding {
|
||||
final EdgeInsets returnValue = _resolvedPaddingCache ??= padding.resolve(textDirection);
|
||||
assert(returnValue.isNonNegative);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
void _markNeedResolution() {
|
||||
_resolvedPadding = null;
|
||||
_resolvedPaddingCache = null;
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
@ -160,90 +157,86 @@ class RenderPadding extends RenderShiftedBox {
|
||||
|
||||
@override
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
_resolve();
|
||||
final double totalHorizontalPadding = _resolvedPadding!.left + _resolvedPadding!.right;
|
||||
final double totalVerticalPadding = _resolvedPadding!.top + _resolvedPadding!.bottom;
|
||||
final EdgeInsets padding = _resolvedPadding;
|
||||
if (child != null) {
|
||||
// Relies on double.infinity absorption.
|
||||
return child!.getMinIntrinsicWidth(math.max(0.0, height - totalVerticalPadding)) + totalHorizontalPadding;
|
||||
return child!.getMinIntrinsicWidth(math.max(0.0, height - padding.vertical)) + padding.horizontal;
|
||||
}
|
||||
return totalHorizontalPadding;
|
||||
return padding.horizontal;
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
_resolve();
|
||||
final double totalHorizontalPadding = _resolvedPadding!.left + _resolvedPadding!.right;
|
||||
final double totalVerticalPadding = _resolvedPadding!.top + _resolvedPadding!.bottom;
|
||||
final EdgeInsets padding = _resolvedPadding;
|
||||
if (child != null) {
|
||||
// Relies on double.infinity absorption.
|
||||
return child!.getMaxIntrinsicWidth(math.max(0.0, height - totalVerticalPadding)) + totalHorizontalPadding;
|
||||
return child!.getMaxIntrinsicWidth(math.max(0.0, height - padding.vertical)) + padding.horizontal;
|
||||
}
|
||||
return totalHorizontalPadding;
|
||||
return padding.horizontal;
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
_resolve();
|
||||
final double totalHorizontalPadding = _resolvedPadding!.left + _resolvedPadding!.right;
|
||||
final double totalVerticalPadding = _resolvedPadding!.top + _resolvedPadding!.bottom;
|
||||
final EdgeInsets padding = _resolvedPadding;
|
||||
if (child != null) {
|
||||
// Relies on double.infinity absorption.
|
||||
return child!.getMinIntrinsicHeight(math.max(0.0, width - totalHorizontalPadding)) + totalVerticalPadding;
|
||||
return child!.getMinIntrinsicHeight(math.max(0.0, width - padding.horizontal)) + padding.vertical;
|
||||
}
|
||||
return totalVerticalPadding;
|
||||
return padding.vertical;
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
_resolve();
|
||||
final double totalHorizontalPadding = _resolvedPadding!.left + _resolvedPadding!.right;
|
||||
final double totalVerticalPadding = _resolvedPadding!.top + _resolvedPadding!.bottom;
|
||||
final EdgeInsets padding = _resolvedPadding;
|
||||
if (child != null) {
|
||||
// Relies on double.infinity absorption.
|
||||
return child!.getMaxIntrinsicHeight(math.max(0.0, width - totalHorizontalPadding)) + totalVerticalPadding;
|
||||
return child!.getMaxIntrinsicHeight(math.max(0.0, width - padding.horizontal)) + padding.vertical;
|
||||
}
|
||||
return totalVerticalPadding;
|
||||
return padding.vertical;
|
||||
}
|
||||
|
||||
@override
|
||||
@protected
|
||||
Size computeDryLayout(covariant BoxConstraints constraints) {
|
||||
_resolve();
|
||||
assert(_resolvedPadding != null);
|
||||
final EdgeInsets padding = _resolvedPadding;
|
||||
if (child == null) {
|
||||
return constraints.constrain(Size(
|
||||
_resolvedPadding!.left + _resolvedPadding!.right,
|
||||
_resolvedPadding!.top + _resolvedPadding!.bottom,
|
||||
));
|
||||
return constraints.constrain(Size(padding.horizontal, padding.vertical));
|
||||
}
|
||||
final BoxConstraints innerConstraints = constraints.deflate(_resolvedPadding!);
|
||||
final BoxConstraints innerConstraints = constraints.deflate(padding);
|
||||
final Size childSize = child!.getDryLayout(innerConstraints);
|
||||
return constraints.constrain(Size(
|
||||
_resolvedPadding!.left + childSize.width + _resolvedPadding!.right,
|
||||
_resolvedPadding!.top + childSize.height + _resolvedPadding!.bottom,
|
||||
padding.horizontal + childSize.width,
|
||||
padding.vertical + childSize.height,
|
||||
));
|
||||
}
|
||||
|
||||
@override
|
||||
double? computeDryBaseline(covariant BoxConstraints constraints, TextBaseline baseline) {
|
||||
final RenderBox? child = this.child;
|
||||
if (child == null) {
|
||||
return null;
|
||||
}
|
||||
final EdgeInsets padding = _resolvedPadding;
|
||||
final BoxConstraints innerConstraints = constraints.deflate(padding);
|
||||
final BaselineOffset result = BaselineOffset(child.getDryBaseline(innerConstraints, baseline)) + padding.top;
|
||||
return result.offset;
|
||||
}
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
final BoxConstraints constraints = this.constraints;
|
||||
_resolve();
|
||||
assert(_resolvedPadding != null);
|
||||
final EdgeInsets padding = _resolvedPadding;
|
||||
if (child == null) {
|
||||
size = constraints.constrain(Size(
|
||||
_resolvedPadding!.left + _resolvedPadding!.right,
|
||||
_resolvedPadding!.top + _resolvedPadding!.bottom,
|
||||
));
|
||||
size = constraints.constrain(Size(padding.horizontal, padding.vertical));
|
||||
return;
|
||||
}
|
||||
final BoxConstraints innerConstraints = constraints.deflate(_resolvedPadding!);
|
||||
final BoxConstraints innerConstraints = constraints.deflate(padding);
|
||||
child!.layout(innerConstraints, parentUsesSize: true);
|
||||
final BoxParentData childParentData = child!.parentData! as BoxParentData;
|
||||
childParentData.offset = Offset(_resolvedPadding!.left, _resolvedPadding!.top);
|
||||
childParentData.offset = Offset(padding.left, padding.top);
|
||||
size = constraints.constrain(Size(
|
||||
_resolvedPadding!.left + child!.size.width + _resolvedPadding!.right,
|
||||
_resolvedPadding!.top + child!.size.height + _resolvedPadding!.bottom,
|
||||
padding.horizontal + child!.size.width,
|
||||
padding.vertical + child!.size.height,
|
||||
));
|
||||
}
|
||||
|
||||
@ -252,7 +245,7 @@ class RenderPadding extends RenderShiftedBox {
|
||||
super.debugPaintSize(context, offset);
|
||||
assert(() {
|
||||
final Rect outerRect = offset & size;
|
||||
debugPaintPadding(context.canvas, outerRect, child != null ? _resolvedPadding!.deflateRect(outerRect) : null);
|
||||
debugPaintPadding(context.canvas, outerRect, child != null ? _resolvedPaddingCache!.deflateRect(outerRect) : null);
|
||||
return true;
|
||||
}());
|
||||
}
|
||||
@ -690,6 +683,22 @@ class RenderConstrainedOverflowBox extends RenderAligningShiftedBox {
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
double? computeDryBaseline(covariant BoxConstraints constraints, TextBaseline baseline) {
|
||||
final RenderBox? child = this.child;
|
||||
if (child == null) {
|
||||
return null;
|
||||
}
|
||||
final BoxConstraints childConstraints = _getInnerConstraints(constraints);
|
||||
final double? result = child.getDryBaseline(childConstraints, baseline);
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
final Size childSize = child.getDryLayout(childConstraints);
|
||||
final Size size = getDryLayout(constraints);
|
||||
return result + resolvedAlignment.alongOffset(size - childSize as Offset).dy;
|
||||
}
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
if (child != null) {
|
||||
@ -841,6 +850,22 @@ class RenderConstraintsTransformBox extends RenderAligningShiftedBox with DebugO
|
||||
return childSize == null ? constraints.smallest : constraints.constrain(childSize);
|
||||
}
|
||||
|
||||
@override
|
||||
double? computeDryBaseline(covariant BoxConstraints constraints, TextBaseline baseline) {
|
||||
final RenderBox? child = this.child;
|
||||
if (child == null) {
|
||||
return null;
|
||||
}
|
||||
final BoxConstraints childConstraints = constraintsTransform(constraints);
|
||||
final double? result = child.getDryBaseline(childConstraints, baseline);
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
final Size childSize = child.getDryLayout(childConstraints);
|
||||
final Size size = constraints.constrain(childSize);
|
||||
return result + resolvedAlignment.alongOffset(size - childSize as Offset).dy;
|
||||
}
|
||||
|
||||
Rect _overflowContainerRect = Rect.zero;
|
||||
Rect _overflowChildRect = Rect.zero;
|
||||
bool _isOverflowing = false;
|
||||
@ -997,10 +1022,23 @@ class RenderSizedOverflowBox extends RenderAligningShiftedBox {
|
||||
|
||||
@override
|
||||
double? computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
if (child != null) {
|
||||
return child!.getDistanceToActualBaseline(baseline);
|
||||
return child?.getDistanceToActualBaseline(baseline)
|
||||
?? super.computeDistanceToActualBaseline(baseline);
|
||||
}
|
||||
|
||||
@override
|
||||
double? computeDryBaseline(covariant BoxConstraints constraints, TextBaseline baseline) {
|
||||
final RenderBox? child = this.child;
|
||||
if (child == null) {
|
||||
return null;
|
||||
}
|
||||
return super.computeDistanceToActualBaseline(baseline);
|
||||
final double? result = child.getDryBaseline(constraints, baseline);
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
final Size childSize = child.getDryLayout(constraints);
|
||||
final Size size = getDryLayout(constraints);
|
||||
return result + resolvedAlignment.alongOffset(size - childSize as Offset).dy;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -1163,6 +1201,22 @@ class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
|
||||
return constraints.constrain(_getInnerConstraints(constraints).constrain(Size.zero));
|
||||
}
|
||||
|
||||
@override
|
||||
double? computeDryBaseline(covariant BoxConstraints constraints, TextBaseline baseline) {
|
||||
final RenderBox? child = this.child;
|
||||
if (child == null) {
|
||||
return null;
|
||||
}
|
||||
final BoxConstraints childConstraints = _getInnerConstraints(constraints);
|
||||
final double? result = child.getDryBaseline(childConstraints, baseline);
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
final Size childSize = child.getDryLayout(childConstraints);
|
||||
final Size size = getDryLayout(constraints);
|
||||
return result + resolvedAlignment.alongOffset(size - childSize as Offset).dy;
|
||||
}
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
if (child != null) {
|
||||
@ -1359,6 +1413,23 @@ class RenderCustomSingleChildLayoutBox extends RenderShiftedBox {
|
||||
return _getSize(constraints);
|
||||
}
|
||||
|
||||
@override
|
||||
double? computeDryBaseline(covariant BoxConstraints constraints, TextBaseline baseline) {
|
||||
final RenderBox? child = this.child;
|
||||
if (child == null) {
|
||||
return null;
|
||||
}
|
||||
final BoxConstraints childConstraints = delegate.getConstraintsForChild(constraints);
|
||||
final double? result = child.getDryBaseline(childConstraints, baseline);
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
return result + delegate.getPositionForChild(
|
||||
_getSize(constraints),
|
||||
childConstraints.isTight ? childConstraints.smallest : child.getDryLayout(childConstraints),
|
||||
).dy;
|
||||
}
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
size = _getSize(constraints);
|
||||
|
@ -325,6 +325,15 @@ class _RenderLayoutBuilder extends RenderBox with RenderObjectWithChildMixin<Ren
|
||||
return Size.zero;
|
||||
}
|
||||
|
||||
@override
|
||||
double? computeDryBaseline(BoxConstraints constraints, TextBaseline baseline) {
|
||||
assert(debugCannotComputeDryLayout(reason:
|
||||
'Calculating the dry baseline would require running the layout callback '
|
||||
'speculatively, which might mutate the live render object tree.',
|
||||
));
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
final BoxConstraints constraints = this.constraints;
|
||||
@ -339,10 +348,8 @@ class _RenderLayoutBuilder extends RenderBox with RenderObjectWithChildMixin<Ren
|
||||
|
||||
@override
|
||||
double? computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
if (child != null) {
|
||||
return child!.getDistanceToActualBaseline(baseline);
|
||||
}
|
||||
return super.computeDistanceToActualBaseline(baseline);
|
||||
return child?.getDistanceToActualBaseline(baseline)
|
||||
?? super.computeDistanceToActualBaseline(baseline);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -410,6 +410,44 @@ class _RenderOverflowBar extends RenderBox
|
||||
return defaultComputeDistanceToHighestActualBaseline(baseline);
|
||||
}
|
||||
|
||||
@override
|
||||
double? computeDryBaseline(BoxConstraints constraints, TextBaseline baseline) {
|
||||
final BoxConstraints childConstraints = constraints.loosen();
|
||||
|
||||
final (RenderBox? Function(RenderBox) next, RenderBox? startChild) = switch (overflowDirection) {
|
||||
VerticalDirection.down => (childAfter, firstChild),
|
||||
VerticalDirection.up => (childBefore, lastChild),
|
||||
};
|
||||
|
||||
double maxChildHeight = 0.0;
|
||||
double y = 0.0;
|
||||
double childrenWidth = 0.0;
|
||||
BaselineOffset minHorizontalBaseline = BaselineOffset.noBaseline;
|
||||
BaselineOffset verticalBaseline = BaselineOffset.noBaseline;
|
||||
|
||||
for (RenderBox? child = startChild; child != null; child = next(child)) {
|
||||
final Size childSize = child.getDryLayout(childConstraints);
|
||||
final double heightDiff = childSize.height - maxChildHeight;
|
||||
if (heightDiff > 0) {
|
||||
minHorizontalBaseline += heightDiff / 2;
|
||||
maxChildHeight = childSize.height;
|
||||
}
|
||||
|
||||
final BaselineOffset baselineOffset = BaselineOffset(child.getDryBaseline(childConstraints, baseline));
|
||||
if (baselineOffset != null) {
|
||||
verticalBaseline ??= baselineOffset + y;
|
||||
minHorizontalBaseline = minHorizontalBaseline.minOf(baselineOffset + (maxChildHeight - childSize.height));
|
||||
}
|
||||
y += childSize.height + overflowSpacing;
|
||||
childrenWidth += childSize.width;
|
||||
}
|
||||
|
||||
assert((verticalBaseline == null) == (minHorizontalBaseline == null));
|
||||
return childrenWidth + spacing * (childCount - 1) > constraints.maxWidth
|
||||
? verticalBaseline.offset
|
||||
: minHorizontalBaseline.offset;
|
||||
}
|
||||
|
||||
@override
|
||||
Size computeDryLayout(BoxConstraints constraints) {
|
||||
RenderBox? child = firstChild;
|
||||
|
@ -379,6 +379,12 @@ class _RenderScaledInlineWidget extends RenderBox with RenderObjectWithChildMixi
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
double? computeDryBaseline(BoxConstraints constraints, TextBaseline baseline) {
|
||||
final double? distance = child?.getDryBaseline(BoxConstraints(maxWidth: constraints.maxWidth / scale), baseline);
|
||||
return distance == null ? null : scale * distance;
|
||||
}
|
||||
|
||||
@override
|
||||
Size computeDryLayout(BoxConstraints constraints) {
|
||||
assert(!constraints.hasBoundedHeight);
|
||||
|
@ -21,16 +21,18 @@ class TestSingleChildLayoutDelegate extends SingleChildLayoutDelegate {
|
||||
|
||||
@override
|
||||
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
|
||||
assert(!RenderObject.debugCheckingIntrinsics);
|
||||
constraintsFromGetConstraintsForChild = constraints;
|
||||
if (!RenderObject.debugCheckingIntrinsics) {
|
||||
constraintsFromGetConstraintsForChild = constraints;
|
||||
}
|
||||
return const BoxConstraints(minWidth: 100.0, maxWidth: 150.0, minHeight: 200.0, maxHeight: 400.0);
|
||||
}
|
||||
|
||||
@override
|
||||
Offset getPositionForChild(Size size, Size childSize) {
|
||||
assert(!RenderObject.debugCheckingIntrinsics);
|
||||
sizeFromGetPositionForChild = size;
|
||||
childSizeFromGetPositionForChild = childSize;
|
||||
if (!RenderObject.debugCheckingIntrinsics) {
|
||||
sizeFromGetPositionForChild = size;
|
||||
childSizeFromGetPositionForChild = childSize;
|
||||
}
|
||||
return Offset.zero;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user