Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions webf/lib/src/css/transform.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -99,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;
Expand Down
62 changes: 52 additions & 10 deletions webf/lib/src/rendering/box_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import 'package:webf/gesture.dart';
import 'package:webf/webf.dart';
import 'package:webf/rendering.dart';

import 'box_overflow.dart';
import 'debug_overlay.dart';

// The hashCode of all the renderBox which is in layout.
Expand Down Expand Up @@ -218,6 +219,45 @@ class RenderLayoutBox extends RenderBoxModel
_paintingOrder = null;
}


// iterate add child to overflowLayout
void addOverflowLayoutFromChildren(List<RenderBox> 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 || child is RenderConstrainedBox) {
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(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);
}

// Sort children by zIndex, used for paint and hitTest.
List<RenderBox>? _paintingOrder;
List<RenderBox> get paintingOrder {
Expand Down Expand Up @@ -608,16 +648,17 @@ mixin RenderBoxModelBase on RenderBox {
}

class RenderBoxModel extends RenderBox
with
RenderBoxModelBase,
RenderBoxDecorationMixin,
RenderTransformMixin,
RenderOverflowMixin,
RenderOpacityMixin,
RenderIntersectionObserverMixin,
RenderContentVisibilityMixin,
RenderEventListenerMixin,
RenderObjectWithControllerMixin {
with
RenderBoxModelBase,
RenderBoxDecorationMixin,
RenderBoxOverflowLayout,
RenderTransformMixin,
RenderOverflowMixin,
RenderOpacityMixin,
RenderIntersectionObserverMixin,
RenderContentVisibilityMixin,
RenderEventListenerMixin,
RenderObjectWithControllerMixin {
RenderBoxModel({
required this.renderStyle,
}) : super();
Expand Down Expand Up @@ -1027,6 +1068,7 @@ class RenderBoxModel extends RenderBox
// Deflate padding constraints.
contentConstraints = renderStyle.deflatePaddingConstraints(contentConstraints);
_contentConstraints = contentConstraints;
clearOverflowLayout();
}

/// Find scroll container
Expand Down
63 changes: 63 additions & 0 deletions webf/lib/src/rendering/box_overflow.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import 'dart:math';
import 'dart:ui';

import '../../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;
}
}
8 changes: 8 additions & 0 deletions webf/lib/src/rendering/flex.dart
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,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.
Expand All @@ -642,6 +648,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.
Expand Down Expand Up @@ -709,6 +716,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(
Expand Down
8 changes: 8 additions & 0 deletions webf/lib/src/rendering/flow.dart
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,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.
Expand Down