Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
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
2 changes: 1 addition & 1 deletion lib/web_ui/lib/src/engine/canvaskit/embedded_views.dart
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ class HtmlViewEmbedder {
if (_svgPathDefs != null) {
return;
}
_svgPathDefs = kSvgResourceHeader.clone(false) as SVGElement;
_svgPathDefs = kSvgResourceHeader.cloneNode(false) as SVGElement;
_svgPathDefs!.append(createSVGDefsElement()..id = 'sk_path_defs');
skiaSceneHost!.append(_svgPathDefs!);
}
Expand Down
17 changes: 17 additions & 0 deletions lib/web_ui/lib/src/engine/dom.dart
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,11 @@ extension DomElementExtension on DomElement {
external void click();
external bool hasAttribute(String name);
external DomNodeList get childNodes;
void clearChildren() {
while (firstChild != null) {
removeChild(firstChild!);
}
}
}

@JS()
Expand Down Expand Up @@ -421,8 +426,12 @@ extension DomHTMLMetaElementExtension on DomHTMLMetaElement {
external String get name;
external set name(String value);
external String get content;
external set content(String value);
}

DomHTMLMetaElement createDomHTMLMetaElement() =>
domDocument.createElement('meta') as DomHTMLMetaElement;

@JS()
@staticInterop
class DomHTMLHeadElement extends DomHTMLElement {}
Expand Down Expand Up @@ -507,6 +516,7 @@ extension DomPerformanceExtension on DomPerformance {
external DomPerformanceEntry? mark(String markName);
external DomPerformanceMeasure? measure(
String measureName, String? startMark, String? endMark);
external double now();
}

@JS()
Expand Down Expand Up @@ -1107,6 +1117,13 @@ extension DomHTMLFormElementExtension on DomHTMLFormElement {
DomHTMLFormElement createDomHTMLFormElement() =>
domDocument.createElement('form') as DomHTMLFormElement;

@JS()
@staticInterop
class DomHTMLLabelElement extends DomHTMLElement {}

DomHTMLLabelElement createDomHTMLLabelElement() =>
domDocument.createElement('label') as DomHTMLLabelElement;

@JS()
@staticInterop
class DomNodeList {}
Expand Down
8 changes: 4 additions & 4 deletions lib/web_ui/lib/src/engine/html/bitmap_canvas.dart
Original file line number Diff line number Diff line change
Expand Up @@ -851,8 +851,8 @@ class BitmapCanvas extends EngineCanvas {
SurfacePaintData paint) {
// For srcIn blendMode, we use an svg filter to apply to image element.
final SvgFilter svgFilter = svgFilterFromBlendMode(filterColor, colorFilterBlendMode);
rootElement.append(svgFilter.element as DomElement);
_children.add(svgFilter.element as DomElement);
rootElement.append(svgFilter.element);
_children.add(svgFilter.element);
final DomHTMLElement imgElement = _reuseOrCreateImage(image);
imgElement.style.filter = 'url(#${svgFilter.id})';
if (colorFilterBlendMode == ui.BlendMode.saturation) {
Expand All @@ -866,8 +866,8 @@ class BitmapCanvas extends EngineCanvas {
HtmlImage image, List<double> matrix, SurfacePaintData paint) {
// For srcIn blendMode, we use an svg filter to apply to image element.
final SvgFilter svgFilter = svgFilterFromColorMatrix(matrix);
rootElement.append(svgFilter.element as DomElement);
_children.add(svgFilter.element as DomElement);
rootElement.append(svgFilter.element);
_children.add(svgFilter.element);
final DomHTMLElement imgElement = _reuseOrCreateImage(image);
imgElement.style.filter = 'url(#${svgFilter.id})';
return imgElement;
Expand Down
9 changes: 3 additions & 6 deletions lib/web_ui/lib/src/engine/html/clip.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:svg' as svg;

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

import '../dom.dart';
Expand Down Expand Up @@ -344,7 +342,7 @@ class PersistedPhysicalShape extends PersistedContainerSurface
/// we size the inner container to cover full pathBounds instead of sizing
/// to clipping rect bounds (which is the case for elevation == 0.0 where
/// we shift outer/inner clip area instead to position clip-path).
final svg.SvgSvgElement svgClipPath = elevation == 0.0
final SVGSVGElement svgClipPath = elevation == 0.0
? pathToSvgClipPath(path,
offsetX: -pathBounds.left,
offsetY: -pathBounds.top,
Expand All @@ -360,7 +358,7 @@ class PersistedPhysicalShape extends PersistedContainerSurface
/// svg clip and render elements.
_clipElement?.remove();
_svgElement?.remove();
_clipElement = svgClipPath as DomElement;
_clipElement = svgClipPath;
rootElement!.append(_clipElement!);
if (elevation == 0.0) {
setClipPath(rootElement!, createSvgClipUrl());
Expand Down Expand Up @@ -517,8 +515,7 @@ class PersistedClipPath extends PersistedContainerSurface
SVGSVGElement createSvgClipDef(DomElement element, ui.Path clipPath) {
final ui.Rect pathBounds = clipPath.getBounds();
final SVGSVGElement svgClipPath = pathToSvgClipPath(clipPath,
scaleX: 1.0 / pathBounds.right, scaleY: 1.0 / pathBounds.bottom) as
SVGSVGElement;
scaleX: 1.0 / pathBounds.right, scaleY: 1.0 / pathBounds.bottom);
setClipPath(element, createSvgClipUrl());
// We need to set width and height for the clipElement to cover the
// bounds of the path since browsers such as Safari and Edge
Expand Down
41 changes: 21 additions & 20 deletions lib/web_ui/lib/src/engine/html/color_filter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// found in the LICENSE file.

import 'dart:html' as html;
import 'dart:svg' as svg;

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

Expand All @@ -12,6 +11,7 @@ import '../canvaskit/color_filter.dart';
import '../color_filter.dart';
import '../dom.dart';
import '../embedder.dart';
import '../svg.dart';
import '../util.dart';
import 'bitmap_canvas.dart';
import 'path_to_svg_clip.dart';
Expand All @@ -33,7 +33,7 @@ class PersistedColorFilter extends PersistedContainerSurface

/// Color filter to apply to this surface.
final ui.ColorFilter filter;
html.Element? _filterElement;
DomElement? _filterElement;
bool containerVisible = true;

@override
Expand All @@ -54,7 +54,7 @@ class PersistedColorFilter extends PersistedContainerSurface
@override
void discard() {
super.discard();
flutterViewEmbedder.removeResource(_filterElement);
flutterViewEmbedder.removeResource(_filterElement as html.Element?);
// Do not detach the child container from the root. It is permanently
// attached. The elements are reused together and are detached from the DOM
// together.
Expand All @@ -73,7 +73,7 @@ class PersistedColorFilter extends PersistedContainerSurface

@override
void apply() {
flutterViewEmbedder.removeResource(_filterElement);
flutterViewEmbedder.removeResource(_filterElement as html.Element?);
_filterElement = null;
final EngineColorFilter? engineValue = filter as EngineColorFilter?;
if (engineValue == null) {
Expand Down Expand Up @@ -139,7 +139,7 @@ class PersistedColorFilter extends PersistedContainerSurface
// Use SVG filter for blend mode.
final SvgFilter svgFilter = svgFilterFromBlendMode(filterColor, colorFilterBlendMode);
_filterElement = svgFilter.element;
flutterViewEmbedder.addResource(_filterElement!);
flutterViewEmbedder.addResource(_filterElement! as html.Element);
style.filter = 'url(#${svgFilter.id})';
if (colorFilterBlendMode == ui.BlendMode.saturation ||
colorFilterBlendMode == ui.BlendMode.multiply ||
Expand All @@ -151,7 +151,7 @@ class PersistedColorFilter extends PersistedContainerSurface
void _applyMatrixColorFilter(CkMatrixColorFilter colorFilter) {
final SvgFilter svgFilter = svgFilterFromColorMatrix(colorFilter.matrix);
_filterElement = svgFilter.element;
flutterViewEmbedder.addResource(_filterElement!);
flutterViewEmbedder.addResource(_filterElement! as html.Element);
childContainer!.style.filter = 'url(#${svgFilter.id})';
}

Expand Down Expand Up @@ -272,20 +272,21 @@ class SvgFilterBuilder {
}

final String id;
final svg.SvgSvgElement root = kSvgResourceHeader.clone(false) as svg.SvgSvgElement;
final svg.FilterElement filter = svg.FilterElement();
final SVGSVGElement root = kSvgResourceHeader.cloneNode(false) as
SVGSVGElement;
final SVGFilterElement filter = createSVGFilterElement();

set colorInterpolationFilters(String filters) {
filter.setAttribute('color-interpolation-filters', filters);
}

void setFeColorMatrix(List<double> matrix, { required String result }) {
final svg.FEColorMatrixElement element = svg.FEColorMatrixElement();
final SVGFEColorMatrixElement element = createSVGFEColorMatrixElement();
element.type!.baseVal = kMatrixType;
element.result!.baseVal = result;
final svg.NumberList value = element.values!.baseVal!;
final SVGNumberList value = element.values!.baseVal!;
for (int i = 0; i < matrix.length; i++) {
value.appendItem(root.createSvgNumber()..value = matrix[i]);
value.appendItem(root.createSVGNumber()..value = matrix[i]);
}
filter.append(element);
}
Expand All @@ -295,7 +296,7 @@ class SvgFilterBuilder {
required String floodOpacity,
required String result,
}) {
final svg.FEFloodElement element = svg.FEFloodElement();
final SVGFEFloodElement element = createSVGFEFloodElement();
element.setAttribute('flood-color', floodColor);
element.setAttribute('flood-opacity', floodOpacity);
element.result!.baseVal = result;
Expand All @@ -307,7 +308,7 @@ class SvgFilterBuilder {
required String in2,
required int mode,
}) {
final svg.FEBlendElement element = svg.FEBlendElement();
final SVGFEBlendElement element = createSVGFEBlendElement();
element.in1!.baseVal = in1;
element.in2!.baseVal = in2;
element.mode!.baseVal = mode;
Expand All @@ -324,7 +325,7 @@ class SvgFilterBuilder {
num? k4,
required String result,
}) {
final svg.FECompositeElement element = svg.SvgElement.tag('feComposite') as svg.FECompositeElement;
final SVGFECompositeElement element = createSVGFECompositeElement();
element.in1!.baseVal = in1;
element.in2!.baseVal = in2;
element.operator!.baseVal = operator;
Expand All @@ -350,17 +351,17 @@ class SvgFilterBuilder {
required double width,
required double height,
}) {
final svg.FEImageElement element = svg.FEImageElement();
final SVGFEImageElement element = createSVGFEImageElement();
element.href!.baseVal = href;
element.result!.baseVal = result;

// WebKit will not render if x/y/width/height is specified. So we return
// explicit size here unless running on WebKit.
if (browserEngine != BrowserEngine.webkit) {
element.x!.baseVal!.newValueSpecifiedUnits(svg.Length.SVG_LENGTHTYPE_NUMBER, 0);
element.y!.baseVal!.newValueSpecifiedUnits(svg.Length.SVG_LENGTHTYPE_NUMBER, 0);
element.width!.baseVal!.newValueSpecifiedUnits(svg.Length.SVG_LENGTHTYPE_NUMBER, width);
element.height!.baseVal!.newValueSpecifiedUnits(svg.Length.SVG_LENGTHTYPE_NUMBER, height);
element.x!.baseVal!.newValueSpecifiedUnits(svgLengthTypeNumber, 0);
element.y!.baseVal!.newValueSpecifiedUnits(svgLengthTypeNumber, 0);
element.width!.baseVal!.newValueSpecifiedUnits(svgLengthTypeNumber, width);
element.height!.baseVal!.newValueSpecifiedUnits(svgLengthTypeNumber, height);
}
filter.append(element);
}
Expand All @@ -375,7 +376,7 @@ class SvgFilter {
SvgFilter._(this.id, this.element);

final String id;
final svg.SvgSvgElement element;
final SVGSVGElement element;
}

SvgFilter svgFilterFromColorMatrix(List<double> matrix) {
Expand Down
16 changes: 8 additions & 8 deletions lib/web_ui/lib/src/engine/html/path_to_svg_clip.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:svg' as svg;

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

import '../browser_detection.dart';
import '../dom.dart';
import '../svg.dart';
import 'path/path.dart';
import 'path/path_to_svg.dart';

Expand All @@ -17,7 +17,7 @@ int _clipIdCounter = 0;
///
/// Position needs to be absolute since these svgs are sandwiched between
/// canvas elements and can cause layout shifts otherwise.
final svg.SvgSvgElement kSvgResourceHeader = svg.SvgSvgElement()
final SVGSVGElement kSvgResourceHeader = createSVGSVGElement()
..setAttribute('width', 0)
..setAttribute('height', 0)
..style.position = 'absolute';
Expand All @@ -26,22 +26,22 @@ final svg.SvgSvgElement kSvgResourceHeader = svg.SvgSvgElement()
///
/// Calling this method updates [_clipIdCounter]. The HTML id of the generated
/// clip is set to "svgClip${_clipIdCounter}", e.g. "svgClip123".
svg.SvgSvgElement pathToSvgClipPath(ui.Path path,
SVGSVGElement pathToSvgClipPath(ui.Path path,
{double offsetX = 0,
double offsetY = 0,
double scaleX = 1.0,
double scaleY = 1.0}) {
_clipIdCounter += 1;
final svg.SvgSvgElement root = kSvgResourceHeader.clone(false) as svg.SvgSvgElement;
final svg.DefsElement defs = svg.DefsElement();
final SVGSVGElement root = kSvgResourceHeader.cloneNode(false) as SVGSVGElement;
final SVGDefsElement defs = createSVGDefsElement();
root.append(defs);

final String clipId = 'svgClip$_clipIdCounter';
final svg.ClipPathElement clipPath = svg.ClipPathElement();
final SVGClipPathElement clipPath = createSVGClipPathElement();
defs.append(clipPath);
clipPath.id = clipId;

final svg.PathElement svgPath = svg.PathElement();
final SVGPathElement svgPath = createSVGPathElement();
clipPath.append(svgPath);
svgPath.setAttribute('fill', '#FFFFFF');

Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/lib/src/engine/html/shader_mask.dart
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class PersistedShaderMask extends PersistedContainerSurface

final SvgFilter svgFilter = svgMaskFilterFromImageAndBlendMode(
imageUrl, blendModeTemp, maskRect.width, maskRect.height);
_shaderElement = svgFilter.element;
_shaderElement = svgFilter.element as html.Element;
if (isWebKit) {
_childContainer!.style.filter = 'url(#${svgFilter.id})';
} else {
Expand Down
6 changes: 3 additions & 3 deletions lib/web_ui/lib/src/engine/profiler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
// found in the LICENSE file.

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

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

import 'dom.dart';
import 'platform_dispatcher.dart';
import 'safe_browser_api.dart';

Expand Down Expand Up @@ -107,7 +107,7 @@ class Profiler {
// out at certain optimization levels in dart2js, leading to obscure errors
// later on.
final Object? onBenchmark = getJsProperty<Object?>(
html.window,
domWindow,
'_flutter_internal_on_benchmark',
);
onBenchmark as OnBenchmark?;
Expand Down Expand Up @@ -224,7 +224,7 @@ void frameTimingsOnRasterFinish() {
/// particularly notes about Firefox rounding to 1ms for security reasons,
/// which can be bypassed in tests by setting certain browser options.
int _nowMicros() {
return (html.window.performance.now() * 1000).toInt();
return (domWindow.performance.now() * 1000).toInt();
}

/// Counts various events that take place while the app is running.
Expand Down
12 changes: 6 additions & 6 deletions lib/web_ui/lib/src/engine/semantics/accessibility.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
// found in the LICENSE file.

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

import '../../engine.dart' show registerHotRestartListener;
import '../dom.dart';
import '../services.dart';
import '../util.dart';

Expand Down Expand Up @@ -52,9 +52,9 @@ class AccessibilityAnnouncements {
/// This element has aria-live attribute.
///
/// It also has id 'accessibility-element' for testing purposes.
html.HtmlElement? _element;
DomHTMLElement? _element;

html.HtmlElement get _domElement => _element ??= _createElement();
DomHTMLElement get _domElement => _element ??= _createElement();

/// Decodes the message coming from the 'flutter/accessibility' channel.
void handleMessage(StandardMessageCodec codec, ByteData? data) {
Expand All @@ -73,11 +73,11 @@ class AccessibilityAnnouncements {
void _initLiveRegion(String message) {
_domElement.setAttribute('aria-live', 'polite');
_domElement.text = message;
html.document.body!.append(_domElement);
domDocument.body!.append(_domElement);
}

html.LabelElement _createElement() {
final html.LabelElement liveRegion = html.LabelElement();
DomHTMLLabelElement _createElement() {
final DomHTMLLabelElement liveRegion = createDomHTMLLabelElement();
liveRegion.setAttribute('id', 'accessibility-element');
liveRegion.style
..position = 'fixed'
Expand Down
Loading