Skip to content

Commit

Permalink
[web] Migrate Flutter Web DOM usage to JS static interop - 5 (flutter…
Browse files Browse the repository at this point in the history
  • Loading branch information
joshualitt authored May 6, 2022
1 parent 5be13de commit 41e45ca
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 62 deletions.
73 changes: 36 additions & 37 deletions lib/web_ui/lib/src/engine/canvaskit/embedded_views.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:ui/ui.dart' as ui;

import '../../engine.dart' show platformViewManager;
import '../configuration.dart';
import '../dom.dart';
import '../html/path_to_svg_clip.dart';
import '../platform_views/slots.dart';
import '../util.dart';
Expand Down Expand Up @@ -212,10 +213,10 @@ class HtmlViewEmbedder {
void _compositeWithParams(int viewId, EmbeddedViewParams params) {
// If we haven't seen this viewId yet, cache it for clips/transforms.
final ViewClipChain clipChain = _viewClipChains.putIfAbsent(viewId, () {
return ViewClipChain(view: createPlatformViewSlot(viewId));
return ViewClipChain(view: createPlatformViewSlot(viewId) as DomElement);
});

final html.Element slot = clipChain.slot;
final DomElement slot = clipChain.slot;

// See `apply()` in the PersistedPlatformView class for the HTML version
// of this code.
Expand All @@ -228,8 +229,8 @@ class HtmlViewEmbedder {
final int currentClippingCount = _countClips(params.mutators);
final int previousClippingCount = clipChain.clipCount;
if (currentClippingCount != previousClippingCount) {
final html.Element oldPlatformViewRoot = clipChain.root;
final html.Element newPlatformViewRoot = _reconstructClipViewsChain(
final DomElement oldPlatformViewRoot = clipChain.root;
final DomElement newPlatformViewRoot = _reconstructClipViewsChain(
currentClippingCount,
slot,
oldPlatformViewRoot,
Expand All @@ -255,26 +256,26 @@ class HtmlViewEmbedder {
return clipCount;
}

html.Element _reconstructClipViewsChain(
DomElement _reconstructClipViewsChain(
int numClips,
html.Element platformView,
html.Element headClipView,
DomElement platformView,
DomElement headClipView,
) {
int indexInFlutterView = -1;
if (headClipView.parent != null) {
if (headClipView.parentElement != null) {
indexInFlutterView = skiaSceneHost!.children.indexOf(headClipView);
headClipView.remove();
}
html.Element head = platformView;
DomElement head = platformView;
int clipIndex = 0;
// Re-use as much existing clip views as needed.
while (head != headClipView && clipIndex < numClips) {
head = head.parent!;
head = head.parentElement!;
clipIndex++;
}
// If there weren't enough existing clip views, add more.
while (clipIndex < numClips) {
final html.Element clippingView = html.Element.tag('flt-clip');
final DomElement clippingView = createDomElement('flt-clip');
clippingView.append(head);
head = clippingView;
clipIndex++;
Expand Down Expand Up @@ -309,9 +310,9 @@ class HtmlViewEmbedder {
}

void _applyMutators(
EmbeddedViewParams params, html.Element embeddedView, int viewId) {
EmbeddedViewParams params, DomElement embeddedView, int viewId) {
final MutatorsStack mutators = params.mutators;
html.Element head = embeddedView;
DomElement head = embeddedView;
Matrix4 headTransform = params.offset == ui.Offset.zero
? Matrix4.identity()
: Matrix4.translationValues(params.offset.dx, params.offset.dy, 0);
Expand All @@ -329,7 +330,7 @@ class HtmlViewEmbedder {
case MutatorType.clipRect:
case MutatorType.clipRRect:
case MutatorType.clipPath:
final html.Element clipView = head.parent!;
final DomElement clipView = head.parentElement!;
clipView.style.clip = '';
clipView.style.clipPath = '';
headTransform = Matrix4.identity();
Expand Down Expand Up @@ -397,14 +398,15 @@ class HtmlViewEmbedder {
final Matrix4 scaleMatrix =
Matrix4.diagonal3Values(inverseScale, inverseScale, 1);
headTransform = scaleMatrix.multiplied(headTransform);
head.style.transform = float64ListToCssTransform(headTransform.storage);
head.style.transform =
float64ListToCssTransform(headTransform.storage);
}

/// Sets the transform origin to the top-left corner of the element.
///
/// By default, the transform origin is the center of the element, but
/// Flutter assumes the transform origin is the top-left point.
void _resetAnchor(html.Element element) {
void _resetAnchor(DomElement element) {
element.style.transformOrigin = '0 0 0';
element.style.position = 'absolute';
}
Expand All @@ -424,7 +426,7 @@ class HtmlViewEmbedder {
}
_svgPathDefs = kSvgResourceHeader.clone(false) as svg.SvgSvgElement;
_svgPathDefs!.append(svg.DefsElement()..id = 'sk_path_defs');
skiaSceneHost!.append(_svgPathDefs!);
skiaSceneHost!.append(_svgPathDefs! as DomElement);
}

void submitFrame() {
Expand Down Expand Up @@ -489,7 +491,7 @@ class HtmlViewEmbedder {
_activeCompositionOrder.addAll(_compositionOrder);
unusedViews.removeAll(_compositionOrder);

html.Element? elementToInsertBefore;
DomElement? elementToInsertBefore;
if (diffResult.addToBeginning) {
elementToInsertBefore =
_viewClipChains[diffResult.viewToInsertBefore!]!.root;
Expand All @@ -504,27 +506,26 @@ class HtmlViewEmbedder {
}
}
if (diffResult.addToBeginning) {
final html.Element platformViewRoot = _viewClipChains[viewId]!.root;
final DomElement platformViewRoot = _viewClipChains[viewId]!.root;
skiaSceneHost!.insertBefore(platformViewRoot, elementToInsertBefore);
final Surface? overlay = _overlays[viewId];
if (overlay != null) {
skiaSceneHost!
.insertBefore(overlay.htmlElement as html.Element, elementToInsertBefore);
.insertBefore(overlay.htmlElement, elementToInsertBefore);
}
} else {
final html.Element platformViewRoot = _viewClipChains[viewId]!.root;
final DomElement platformViewRoot = _viewClipChains[viewId]!.root;
skiaSceneHost!.append(platformViewRoot);
final Surface? overlay = _overlays[viewId];
if (overlay != null) {
skiaSceneHost!.append(overlay.htmlElement as html.Element);
skiaSceneHost!.append(overlay.htmlElement);
}
}
}
insertBeforeMap?.forEach((int viewId, int viewIdToInsertBefore) {
final html.Element overlay = _overlays[viewId]!.htmlElement as
html.Element;
final DomElement overlay = _overlays[viewId]!.htmlElement;
if (viewIdToInsertBefore != -1) {
final html.Element nextSibling =
final DomElement nextSibling =
_viewClipChains[viewIdToInsertBefore]!.root;
skiaSceneHost!.insertBefore(overlay, nextSibling);
} else {
Expand All @@ -533,8 +534,7 @@ class HtmlViewEmbedder {
});
if (_didPaintBackupSurface) {
skiaSceneHost!
.append(SurfaceFactory.instance.backupSurface.htmlElement as
html.Element);
.append(SurfaceFactory.instance.backupSurface.htmlElement);
}
} else {
SurfaceFactory.instance.removeSurfacesFromDom();
Expand All @@ -549,19 +549,18 @@ class HtmlViewEmbedder {
}
}

final html.Element platformViewRoot = _viewClipChains[viewId]!.root;
final DomElement platformViewRoot = _viewClipChains[viewId]!.root;
final Surface? overlay = _overlays[viewId];
skiaSceneHost!.append(platformViewRoot);
if (overlay != null) {
skiaSceneHost!.append(overlay.htmlElement as html.Element);
skiaSceneHost!.append(overlay.htmlElement);
}
_activeCompositionOrder.add(viewId);
unusedViews.remove(viewId);
}
if (_didPaintBackupSurface) {
skiaSceneHost!
.append(SurfaceFactory.instance.backupSurface.htmlElement as
html.Element);
.append(SurfaceFactory.instance.backupSurface.htmlElement);
}
}

Expand Down Expand Up @@ -770,19 +769,19 @@ class HtmlViewEmbedder {
/// * The slot view in the stack (the actual contents of the platform view).
/// * The number of clipping elements used last time the view was composited.
class ViewClipChain {
html.Element _root;
html.Element _slot;
DomElement _root;
DomElement _slot;
int _clipCount = -1;

ViewClipChain({required html.Element view})
ViewClipChain({required DomElement view})
: _root = view,
_slot = view;

html.Element get root => _root;
html.Element get slot => _slot;
DomElement get root => _root;
DomElement get slot => _slot;
int get clipCount => _clipCount;

void updateClipChain({required html.Element root, required int clipCount}) {
void updateClipChain({required DomElement root, required int clipCount}) {
_root = root;
_clipCount = clipCount;
}
Expand Down
3 changes: 1 addition & 2 deletions lib/web_ui/lib/src/engine/canvaskit/initialization.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
library canvaskit_initialization;

import 'dart:async';
import 'dart:html' as html;

import '../../engine.dart' show kProfileMode;
import '../browser_detection.dart';
Expand Down Expand Up @@ -119,4 +118,4 @@ void ensureSkiaFontCollectionInitialized() {
}

/// The scene host, where the root canvas and overlay canvases are added to.
html.Element? skiaSceneHost;
DomElement? skiaSceneHost;
12 changes: 5 additions & 7 deletions lib/web_ui/lib/src/engine/canvaskit/surface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:html' as html;

import 'package:ui/ui.dart' as ui;

import '../browser_detection.dart';
Expand Down Expand Up @@ -133,7 +131,7 @@ class Surface {

void addToScene() {
if (!_addedToScene) {
skiaSceneHost!.children.insert(0, htmlElement as html.Element);
skiaSceneHost!.prepend(htmlElement);
}
_addedToScene = true;
}
Expand Down Expand Up @@ -210,8 +208,8 @@ class Surface {
final double logicalWidth = _pixelWidth / window.devicePixelRatio;
final double logicalHeight = _pixelHeight / window.devicePixelRatio;
final DomCSSStyleDeclaration style = htmlCanvas!.style;
style.setProperty('width', '${logicalWidth}px');
style.setProperty('height', '${logicalHeight}px');
style.width = '${logicalWidth}px';
style.height = '${logicalHeight}px';
}

/// Translate the canvas so the surface covers the visible portion of the
Expand All @@ -226,7 +224,7 @@ class Surface {
final int surfaceHeight = _currentSurfaceSize!.height.ceil();
final double offset =
(_pixelHeight - surfaceHeight) / window.devicePixelRatio;
htmlCanvas!.style.setProperty('transform', 'translate(0, -${offset}px)');
htmlCanvas!.style.transform = 'translate(0, -${offset}px)';
}

void _contextRestoredListener(DomEvent event) {
Expand Down Expand Up @@ -296,7 +294,7 @@ class Surface {
// accessible.
htmlCanvas.setAttribute('aria-hidden', 'true');

htmlCanvas.style.setProperty('position', 'absolute');
htmlCanvas.style.position = 'absolute';
_updateLogicalHtmlCanvasSize();

// When the browser tab using WebGL goes dormant the browser and/or OS may
Expand Down
18 changes: 18 additions & 0 deletions lib/web_ui/lib/src/engine/dom.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ extension DomElementExtension on DomElement {
external /* List<DomElement> */ List<Object?> get children;
external DomCSSStyleDeclaration get style;
external void append(DomNode node);
external void prepend(DomNode node);
external void setAttribute(String name, Object value);
}

Expand All @@ -120,6 +121,23 @@ extension DomElementExtension on DomElement {
class DomCSSStyleDeclaration {}

extension DomCSSStyleDeclarationExtension on DomCSSStyleDeclaration {
set width(String value) => setProperty('width', value);
set height(String value) => setProperty('height', value);
set position(String value) => setProperty('position', value);
set clip(String value) => setProperty('clip', value);
set clipPath(String value) => setProperty('clip-path', value);
set transform(String value) => setProperty('transform', value);
set transformOrigin(String value) => setProperty('transform-origin', value);
set opacity(String value) => setProperty('opacity', value);
String get width => getPropertyValue('width');
String get height => getPropertyValue('height');
String get position => getPropertyValue('position');
String get clip => getPropertyValue('clip');
String get clipPath => getPropertyValue('clip-path');
String get transform => getPropertyValue('transform');
String get transformOrigin => getPropertyValue('transform-origin');
String get opacity => getPropertyValue('opacity');

external String getPropertyValue(String property);
external void setProperty(String propertyName, String value, [String
priority]);
Expand Down
5 changes: 3 additions & 2 deletions lib/web_ui/lib/src/engine/embedder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import '../engine.dart' show buildMode, registerHotRestartListener;
import 'browser_detection.dart';
import 'canvaskit/initialization.dart';
import 'configuration.dart';
import 'dom.dart';
import 'host_node.dart';
import 'keyboard_binding.dart';
import 'platform_dispatcher.dart';
Expand Down Expand Up @@ -295,8 +296,8 @@ class FlutterViewEmbedder {
/// added eagerly during initialization here and never touched, unless the
/// system is reset due to hot restart or in a test.
if (useCanvasKit) {
skiaSceneHost = html.Element.tag('flt-scene');
addSceneToSceneHost(skiaSceneHost);
skiaSceneHost = createDomElement('flt-scene');
addSceneToSceneHost(skiaSceneHost as html.Element?);
}

final html.Element semanticsHostElement =
Expand Down
Loading

0 comments on commit 41e45ca

Please sign in to comment.