Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 7a937eb

Browse files
author
nturgut
committed
compute bounding matrix
1 parent e1ab408 commit 7a937eb

File tree

2 files changed

+104
-28
lines changed

2 files changed

+104
-28
lines changed

lib/web_ui/lib/src/engine/semantics/semantics.dart

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -851,13 +851,25 @@ class SemanticsObject {
851851
hasIdentityTransform &&
852852
verticalContainerAdjustment == 0.0 &&
853853
horizontalContainerAdjustment == 0.0) {
854-
element.style
854+
if (isDesktop) {
855+
element.style
856+
..removeProperty('transform-origin')
857+
..removeProperty('transform');
858+
} else {
859+
element.style
855860
..removeProperty('top')
856861
..removeProperty('left');
862+
}
857863
if (containerElement != null) {
858-
containerElement.style
859-
..removeProperty('top')
860-
..removeProperty('left');
864+
if (isDesktop) {
865+
containerElement.style
866+
..removeProperty('transform-origin')
867+
..removeProperty('transform');
868+
} else {
869+
containerElement.style
870+
..removeProperty('top')
871+
..removeProperty('left');
872+
}
861873
}
862874
return;
863875
}
@@ -882,14 +894,34 @@ class SemanticsObject {
882894
}
883895

884896
if (!effectiveTransformIsIdentity) {
885-
final Vector3 translation = effectiveTransform.getTranslation();
886-
element.style
887-
..top = '${translation.y}px'
888-
..left = '${translation.x}px';
897+
if (isDesktop) {
898+
element.style
899+
..transformOrigin = '0 0 0'
900+
..transform = matrix4ToCssTransform(effectiveTransform);
901+
} else {
902+
// Mobile screen readers observed have errors reading the semantics
903+
// borders when css `transform` properties are used.
904+
// See: https://github.com/flutter/flutter/issues/68225
905+
final ui.Rect rect =
906+
computeBoundingRectangleFromMatrix(effectiveTransform, _rect!);
907+
element.style
908+
..top = '${rect.top}px'
909+
..left = '${rect.left}px'
910+
..width = '${rect.width}px'
911+
..height = '${rect.height}px';
912+
print(
913+
'** rectangle: ${rect.top}, ${rect.left}, ${rect.width}, ${rect.height}');
914+
}
889915
} else {
890-
element.style
891-
..removeProperty('top')
892-
..removeProperty('left');
916+
if (isDesktop) {
917+
element.style
918+
..removeProperty('transform-origin')
919+
..removeProperty('transform');
920+
} else {
921+
element.style
922+
..removeProperty('top')
923+
..removeProperty('left');
924+
}
893925
}
894926

895927
if (containerElement != null) {
@@ -898,13 +930,25 @@ class SemanticsObject {
898930
horizontalContainerAdjustment != 0.0) {
899931
final double translateX = -_rect!.left + horizontalContainerAdjustment;
900932
final double translateY = -_rect!.top + verticalContainerAdjustment;
901-
containerElement.style
902-
..top = '${translateY}px'
903-
..left = '${translateX}px';
933+
if (isDesktop) {
934+
containerElement.style
935+
..transformOrigin = '0 0 0'
936+
..transform = 'translate(${translateX}px, ${translateY}px)';
937+
} else {
938+
containerElement.style
939+
..top = '${translateY}px'
940+
..left = '${translateX}px';
941+
}
904942
} else {
905-
containerElement.style
906-
..removeProperty('top')
907-
..removeProperty('left');
943+
if (isDesktop) {
944+
containerElement.style
945+
..removeProperty('transform-origin')
946+
..removeProperty('transform');
947+
} else {
948+
containerElement.style
949+
..removeProperty('top')
950+
..removeProperty('left');
951+
}
908952
}
909953
}
910954
}

lib/web_ui/lib/src/engine/util.dart

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -574,14 +574,46 @@ int clampInt(int value, int min, int max) {
574574
}
575575
}
576576

577-
/// Position of a node in 2 dimensional space.
578-
class Position2D {
579-
/// The position on y-axis.
580-
final String top;
581-
582-
/// The position on x-axis.
583-
final String left;
584-
585-
/// Position2D default constructor.
586-
Position2D(this.top, this.left);
587-
}
577+
ui.Rect computeBoundingRectangleFromMatrix(Matrix4 transform, ui.Rect rect) {
578+
final Float32List m = transform.storage;
579+
// Apply perspective transform to all 4 corners. Can't use left,top, bottom,
580+
// right since for example rotating 45 degrees would yield inaccurate size.
581+
double x = rect.left;
582+
double y = rect.top;
583+
double wp = 1.0 / ((m[3] * x) + (m[7] * y) + m[15]);
584+
double xp = ((m[0] * x) + (m[4] * y) + m[12]) * wp;
585+
double yp = ((m[1] * x) + (m[5] * y) + m[13]) * wp;
586+
double minX = xp, maxX = xp;
587+
double minY =yp, maxY = yp;
588+
x = rect.right;
589+
y = rect.bottom;
590+
wp = 1.0 / ((m[3] * x) + (m[7] * y) + m[15]);
591+
xp = ((m[0] * x) + (m[4] * y) + m[12]) * wp;
592+
yp = ((m[1] * x) + (m[5] * y) + m[13]) * wp;
593+
594+
minX = math.min(minX, xp);
595+
maxX = math.max(maxX, xp);
596+
minY = math.min(minY, yp);
597+
maxY = math.max(maxY, yp);
598+
599+
x = rect.left;
600+
y = rect.bottom;
601+
wp = 1.0 / ((m[3] * x) + (m[7] * y) + m[15]);
602+
xp = ((m[0] * x) + (m[4] * y) + m[12]) * wp;
603+
yp = ((m[1] * x) + (m[5] * y) + m[13]) * wp;
604+
minX = math.min(minX, xp);
605+
maxX = math.max(maxX, xp);
606+
minY = math.min(minY, yp);
607+
maxY = math.max(maxY, yp);
608+
609+
x = rect.right;
610+
y = rect.top;
611+
wp = 1.0 / ((m[3] * x) + (m[7] * y) + m[15]);
612+
xp = ((m[0] * x) + (m[4] * y) + m[12]) * wp;
613+
yp = ((m[1] * x) + (m[5] * y) + m[13]) * wp;
614+
minX = math.min(minX, xp);
615+
maxX = math.max(maxX, xp);
616+
minY = math.min(minY, yp);
617+
maxY = math.max(maxY, yp);
618+
return ui.Rect.fromLTWH(minX, minY, maxX-minX, maxY-minY);
619+
}

0 commit comments

Comments
 (0)