From 7ff8afee08958bbc08bd3f0dcc2c5cba086fbe98 Mon Sep 17 00:00:00 2001 From: pba-cra Date: Fri, 29 Jul 2022 11:22:03 +0800 Subject: [PATCH 1/4] feat(oveflowlayout): support flex and flow use overflowLayout --- webf/lib/src/css/transform.dart | 4 +- webf/lib/src/rendering/box_model.dart | 43 ++++++++++++++++ webf/lib/src/rendering/box_overflow.dart | 62 ++++++++++++++++++++++++ webf/lib/src/rendering/flex.dart | 8 +++ webf/lib/src/rendering/flow.dart | 8 +++ 5 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 webf/lib/src/rendering/box_overflow.dart diff --git a/webf/lib/src/css/transform.dart b/webf/lib/src/css/transform.dart index 447d907864..fc98865719 100644 --- a/webf/lib/src/css/transform.dart +++ b/webf/lib/src/css/transform.dart @@ -100,8 +100,8 @@ mixin CSSTransformMixin on RenderStyle { Offset? get effectiveTransformOffset { // Make sure it is used after renderBoxModel been created. assert(renderBoxModel != null); - Offset? offset = MatrixUtils.getAsTranslation(effectiveTransformMatrix); - return offset; + Vector3 translation = effectiveTransformMatrix.getTranslation(); + return Offset(translation[0],translation[1]); } Offset get transformOffset => _transformOffset; diff --git a/webf/lib/src/rendering/box_model.dart b/webf/lib/src/rendering/box_model.dart index 246e2c3ba0..9adccdb551 100644 --- a/webf/lib/src/rendering/box_model.dart +++ b/webf/lib/src/rendering/box_model.dart @@ -3,6 +3,7 @@ */ import 'dart:async'; import 'dart:math' as math; +import 'dart:math'; import 'dart:ui'; import 'package:flutter/foundation.dart'; @@ -14,6 +15,7 @@ import 'package:kraken/gesture.dart'; import 'package:kraken/kraken.dart'; import 'package:kraken/rendering.dart'; +import 'box_overflow.dart'; import 'debug_overlay.dart'; // The hashCode of all the renderBox which is in layout. @@ -221,6 +223,45 @@ class RenderLayoutBox extends RenderBoxModel _paintingOrder = null; } + + // iterate add child to overflowLayout + void addOverflowLayoutFromChildren(List children) { + children.forEach((child) { + addOverflowLayoutFromChild(child); + }); + } + + void addOverflowLayoutFromChild(RenderBox child) { + final RenderLayoutParentData childParentData = child.parentData as RenderLayoutParentData; + if (child is RenderTextBox || child is RenderPositionPlaceholder || !child.hasSize) { + return; + } + CSSRenderStyle style = (child as RenderBoxModel).renderStyle; + Rect overflowRect = Rect.fromLTWH(childParentData.offset.dx, childParentData.offset.dy, child.boxSize!.width, child.boxSize!.height); + + if (style.effectiveTransformOffset != null) { + overflowRect = overflowRect.shift(style.effectiveTransformOffset!); + } + // child overflowLayout effect parent overflowLayout when child effectiveOverflow is visible or auto + if (child.renderStyle.effectiveOverflowX == CSSOverflowType.visible || + child.renderStyle.effectiveOverflowX == CSSOverflowType.auto || + child.renderStyle.effectiveOverflowY == CSSOverflowType.auto || + child.renderStyle.effectiveOverflowY == CSSOverflowType.visible) { + Rect childOverflowLayoutRect = child.overflowRect!.shift(Offset.zero); + + // child overflowLayout rect need transform for parent`s cartesian coordinates + final Matrix4 transform = Matrix4.identity(); + applyLayoutTransform(child, transform, false); + Offset tlOffset = MatrixUtils.transformPoint(transform,Offset(childOverflowLayoutRect.left,childOverflowLayoutRect.top)); + overflowRect = Rect.fromLTRB(min(overflowRect.left, tlOffset.dx), + min(overflowRect.top, tlOffset.dy), + max(overflowRect.right, tlOffset.dx + childOverflowLayoutRect.width), + max(overflowRect.bottom,tlOffset.dy + childOverflowLayoutRect.height)); + } + + addLayoutOverflow(overflowRect); + } + // Sort children by zIndex, used for paint and hitTest. List? _paintingOrder; List get paintingOrder { @@ -626,6 +667,7 @@ class RenderBoxModel extends RenderBox with RenderBoxModelBase, RenderBoxDecorationMixin, + RenderBoxOverflowLayout, RenderTransformMixin, RenderOverflowMixin, RenderOpacityMixin, @@ -1060,6 +1102,7 @@ class RenderBoxModel extends RenderBox // Deflate padding constraints. contentConstraints = renderStyle.deflatePaddingConstraints(contentConstraints); _contentConstraints = contentConstraints; + clearOverflowLayout(); } /// Find scroll container diff --git a/webf/lib/src/rendering/box_overflow.dart b/webf/lib/src/rendering/box_overflow.dart new file mode 100644 index 0000000000..f1d6252323 --- /dev/null +++ b/webf/lib/src/rendering/box_overflow.dart @@ -0,0 +1,62 @@ +import 'dart:math'; +import 'dart:ui'; + +import 'package:kraken/rendering.dart'; + +/// OverflowLayout is a class for tracking content that spills out of a box +/// This class is used by RenderBox +mixin RenderBoxOverflowLayout on RenderBoxModelBase { + Rect? _layoutOverflowRect; + Rect? _visualOverflowRect; + + void initOverflowLayout(Rect layoutRect, Rect visualRect) { + _layoutOverflowRect = layoutRect; + _visualOverflowRect = visualRect; + } + + Rect? get overflowRect { + return _layoutOverflowRect; + } + + Rect? get visualOverflowRect { + return _visualOverflowRect; + } + + void addLayoutOverflow(Rect rect) { + assert(_layoutOverflowRect != null, 'add overflow rect failed, _layoutOverflowRect not init'); + _layoutOverflowRect = Rect.fromLTRB( + min(_layoutOverflowRect!.left, rect.left), + min(_layoutOverflowRect!.top, rect.top), + max(_layoutOverflowRect!.right, rect.right), + max(_layoutOverflowRect!.bottom, rect.bottom)); + } + + void addVisualOverflow(Rect rect) { + assert(_visualOverflowRect != null, 'add overflow rect failed, _visualOverflowRect not init'); + _visualOverflowRect = Rect.fromLTWH( + min(_visualOverflowRect!.left, rect.left), + min(_visualOverflowRect!.top, rect.top), + max(_visualOverflowRect!.right, rect.right), + max(_visualOverflowRect!.bottom, rect.bottom)); + } + + void moveOverflowLayout(Offset offset) { + assert(_layoutOverflowRect != null, 'add overflow rect failed, _layoutOverflowRect not init'); + _layoutOverflowRect = _layoutOverflowRect!.shift(offset); + assert(_visualOverflowRect != null, 'add overflow rect failed, _visualOverflowRect not init'); + _visualOverflowRect = _visualOverflowRect!.shift(offset); + } + + void setLayoutOverflow(Rect rect) { + _layoutOverflowRect = rect; + } + + void setVisualOverflow(Rect rect) { + _layoutOverflowRect = rect; + } + + void clearOverflowLayout() { + _layoutOverflowRect = null; + _visualOverflowRect = null; + } +} diff --git a/webf/lib/src/rendering/flex.dart b/webf/lib/src/rendering/flex.dart index 44324117ae..d364b1b7f8 100644 --- a/webf/lib/src/rendering/flex.dart +++ b/webf/lib/src/rendering/flex.dart @@ -643,6 +643,12 @@ class RenderFlexLayout extends RenderLayoutBox { // placeholder of positioned element). _layoutFlexItems(_flexItemChildren); + // init overflowLayout size + initOverflowLayout(Rect.fromLTRB(0, 0, size.width, size.height), Rect.fromLTRB(0, 0, size.width, size.height)); + + // calculate all flexItem child overflow size + addOverflowLayoutFromChildren(_flexItemChildren); + // Every placeholder of positioned element should be layouted in a separated layer in flex layout // which is different from the placeholder in flow layout which layout in the same flow as // other elements in normal flow. @@ -655,6 +661,7 @@ class RenderFlexLayout extends RenderLayoutBox { CSSPositionedLayout.applyPositionedChildOffset(this, child); // Position of positioned element affect the scroll size of container. extendMaxScrollableSize(child); + addOverflowLayoutFromChild(child); } // Set offset of sticky element on each layout. @@ -723,6 +730,7 @@ class RenderFlexLayout extends RenderLayoutBox { _setChildrenOffset(_runMetrics); } + // Layout children in normal flow order to calculate metrics of flex lines according to its constraints // and flex-wrap property. List<_RunMetrics> _computeRunMetrics( diff --git a/webf/lib/src/rendering/flow.dart b/webf/lib/src/rendering/flow.dart index 61dcd27148..2d161f82ca 100644 --- a/webf/lib/src/rendering/flow.dart +++ b/webf/lib/src/rendering/flow.dart @@ -191,11 +191,19 @@ class RenderFlowLayout extends RenderLayoutBox { // placeholder of positioned element). _layoutChildren(_nonPositionedChildren); + // init overflowLayout size + initOverflowLayout(Rect.fromLTRB(0, 0, size.width, size.height), Rect.fromLTRB(0, 0, size.width, size.height)); + + // calculate all flexItem child overflow size + addOverflowLayoutFromChildren(_nonPositionedChildren); + + // Set offset of positioned element after flex box size is set. for (RenderBoxModel child in _positionedChildren) { CSSPositionedLayout.applyPositionedChildOffset(this, child); // Position of positioned element affect the scroll size of container. extendMaxScrollableSize(child); + addOverflowLayoutFromChild(child); } // Set offset of sticky element on each layout. From 6fba21ef6191e3ece0cd54a381088bb8686b657c Mon Sep 17 00:00:00 2001 From: pba-cra Date: Tue, 16 Aug 2022 10:21:47 +0800 Subject: [PATCH 2/4] fix(overflowLayout): fix placeholder element overflowlayout error --- webf/lib/src/rendering/box_model.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webf/lib/src/rendering/box_model.dart b/webf/lib/src/rendering/box_model.dart index 39fdbb4ca5..be73cd7909 100644 --- a/webf/lib/src/rendering/box_model.dart +++ b/webf/lib/src/rendering/box_model.dart @@ -229,7 +229,7 @@ class RenderLayoutBox extends RenderBoxModel void addOverflowLayoutFromChild(RenderBox child) { final RenderLayoutParentData childParentData = child.parentData as RenderLayoutParentData; - if (child is RenderTextBox || child is RenderPositionPlaceholder || !child.hasSize) { + if (child is RenderTextBox || child is RenderPositionPlaceholder || !child.hasSize || child is RenderConstrainedBox) { return; } CSSRenderStyle style = (child as RenderBoxModel).renderStyle; From 97626abbfce3471ae5df660f31554104ed9a6daa Mon Sep 17 00:00:00 2001 From: pba-cra Date: Tue, 16 Aug 2022 10:27:10 +0800 Subject: [PATCH 3/4] fix(merge): fix merge error --- webf/lib/src/rendering/box_model.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/webf/lib/src/rendering/box_model.dart b/webf/lib/src/rendering/box_model.dart index be73cd7909..ff6c92e201 100644 --- a/webf/lib/src/rendering/box_model.dart +++ b/webf/lib/src/rendering/box_model.dart @@ -249,10 +249,10 @@ class RenderLayoutBox extends RenderBoxModel final Matrix4 transform = Matrix4.identity(); applyLayoutTransform(child, transform, false); Offset tlOffset = MatrixUtils.transformPoint(transform,Offset(childOverflowLayoutRect.left,childOverflowLayoutRect.top)); - overflowRect = Rect.fromLTRB(min(overflowRect.left, tlOffset.dx), - min(overflowRect.top, tlOffset.dy), - max(overflowRect.right, tlOffset.dx + childOverflowLayoutRect.width), - max(overflowRect.bottom,tlOffset.dy + childOverflowLayoutRect.height)); + overflowRect = Rect.fromLTRB(math.min(overflowRect.left, tlOffset.dx), + math.min(overflowRect.top, tlOffset.dy), + math.max(overflowRect.right, tlOffset.dx + childOverflowLayoutRect.width), + math.max(overflowRect.bottom,tlOffset.dy + childOverflowLayoutRect.height)); } addLayoutOverflow(overflowRect); From 4a25d36d8cf99814ca5fc889a888cc1a0d700440 Mon Sep 17 00:00:00 2001 From: pba-cra Date: Tue, 16 Aug 2022 11:27:15 +0800 Subject: [PATCH 4/4] fix(merge): fix import error --- webf/lib/src/css/transform.dart | 1 + webf/lib/src/rendering/box_overflow.dart | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/webf/lib/src/css/transform.dart b/webf/lib/src/css/transform.dart index 0d4b1e2cfa..2937d23780 100644 --- a/webf/lib/src/css/transform.dart +++ b/webf/lib/src/css/transform.dart @@ -6,6 +6,7 @@ import 'package:flutter/rendering.dart'; import 'package:webf/css.dart'; import 'package:webf/rendering.dart'; +import 'package:vector_math/vector_math_64.dart' show Vector3; const Offset _DEFAULT_TRANSFORM_OFFSET = Offset.zero; const Alignment _DEFAULT_TRANSFORM_ALIGNMENT = Alignment.center; diff --git a/webf/lib/src/rendering/box_overflow.dart b/webf/lib/src/rendering/box_overflow.dart index f1d6252323..316a203264 100644 --- a/webf/lib/src/rendering/box_overflow.dart +++ b/webf/lib/src/rendering/box_overflow.dart @@ -1,7 +1,8 @@ import 'dart:math'; import 'dart:ui'; -import 'package:kraken/rendering.dart'; +import '../../rendering.dart'; + /// OverflowLayout is a class for tracking content that spills out of a box /// This class is used by RenderBox