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
3 changes: 1 addition & 2 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/viewport_metrics.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/clipboard.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/color_filter.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/configuration.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/dom_renderer.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/embedder.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/engine_canvas.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/font_change_util.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/frame_reference.dart
Expand Down Expand Up @@ -638,7 +638,6 @@ FILE: ../../../flutter/lib/web_ui/lib/src/ui/path_metrics.dart
FILE: ../../../flutter/lib/web_ui/lib/src/ui/platform_dispatcher.dart
FILE: ../../../flutter/lib/web_ui/lib/src/ui/pointer.dart
FILE: ../../../flutter/lib/web_ui/lib/src/ui/semantics.dart
FILE: ../../../flutter/lib/web_ui/lib/src/ui/test_embedding.dart
FILE: ../../../flutter/lib/web_ui/lib/src/ui/text.dart
FILE: ../../../flutter/lib/web_ui/lib/src/ui/tile_mode.dart
FILE: ../../../flutter/lib/web_ui/lib/src/ui/window.dart
Expand Down
8 changes: 4 additions & 4 deletions lib/web_ui/lib/src/engine.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import '../ui.dart' as ui;

// ignore: unused_import
import 'engine/configuration.dart';
import 'engine/dom_renderer.dart';
import 'engine/embedder.dart';
import 'engine/keyboard.dart';
import 'engine/mouse_cursor.dart';
import 'engine/navigation/js_url_strategy.dart';
Expand Down Expand Up @@ -130,7 +130,7 @@ export 'engine/color_filter.dart';

export 'engine/configuration.dart';

export 'engine/dom_renderer.dart';
export 'engine/embedder.dart';

export 'engine/engine_canvas.dart';

Expand Down Expand Up @@ -413,8 +413,8 @@ void initializeEngine() {

_engineInitialized = true;

// Initialize the DomRenderer before initializing framework bindings.
ensureDomRendererInitialized();
// Initialize the FlutterViewEmbedder before initializing framework bindings.
ensureFlutterViewEmbedderInitialized();

WebExperiments.ensureInitialized();

Expand Down
5 changes: 2 additions & 3 deletions lib/web_ui/lib/src/engine/canvas_pool.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import 'package:meta/meta.dart';
import 'package:ui/ui.dart' as ui;

import 'browser_detection.dart';
import 'dom_renderer.dart';
import 'engine_canvas.dart';
import 'html/bitmap_canvas.dart';
import 'html/painting.dart';
Expand Down Expand Up @@ -751,7 +750,7 @@ class CanvasPool extends _SaveStackTracking {
rect.center.dx - shaderBounds.left;
final double cy = shaderBounds == null ? rect.center.dy :
rect.center.dy - shaderBounds.top;
DomRenderer.ellipse(context, cx, cy, rect.width / 2,
drawEllipse(context, cx, cy, rect.width / 2,
rect.height / 2, 0, 0, 2.0 * math.pi, false);
contextHandle.paint(style);
}
Expand All @@ -762,7 +761,7 @@ class CanvasPool extends _SaveStackTracking {
final ui.Rect? shaderBounds = contextHandle._shaderBounds;
final double cx = shaderBounds == null ? c.dx : c.dx - shaderBounds.left;
final double cy = shaderBounds == null ? c.dy : c.dy - shaderBounds.top;
DomRenderer.ellipse(context, cx, cy, radius, radius, 0, 0, 2.0 * math.pi, false);
drawEllipse(context, cx, cy, radius, radius, 0, 0, 2.0 * math.pi, false);
contextHandle.paint(style);
}

Expand Down
4 changes: 2 additions & 2 deletions lib/web_ui/lib/src/engine/canvaskit/initialization.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import 'package:js/js.dart';
import '../../engine.dart' show kProfileMode;
import '../browser_detection.dart';
import '../configuration.dart';
import '../dom_renderer.dart';
import '../embedder.dart';
import 'canvaskit_api.dart';
import 'fonts.dart';

Expand Down Expand Up @@ -78,7 +78,7 @@ Future<void> initializeCanvasKit({String? canvasKitBase}) {

/// Add a Skia scene host.
skiaSceneHost = html.Element.tag('flt-scene');
domRenderer.renderScene(skiaSceneHost);
flutterViewEmbedder.renderScene(skiaSceneHost);
return canvasKitCompleter.future;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,29 @@ import 'text_editing/text_editing.dart';
import 'util.dart';
import 'window.dart';

class DomRenderer {
DomRenderer() {
if (assertionsEnabled) {
_debugFrameStatistics = DebugDomRendererFrameStatistics();
}

/// Controls the placement and lifecycle of a Flutter view on the web page.
///
/// Manages several top-level elements that host Flutter-generated content,
/// including:
///
/// - [glassPaneElement], the root element of a Flutter view.
/// - [glassPaneShadow], the shadow root used to isolate Flutter-rendered
/// content from the surrounding page content, including from the platform
/// views.
/// - [sceneElement], the element that hosts Flutter layers and pictures, and
/// projects platform views.
/// - [sceneHostElement], the anchor that provides a stable location in the DOM
/// tree for the [sceneElement].
/// - [semanticsHostElement], hosts the ARIA-annotated semantics tree.
class FlutterViewEmbedder {
FlutterViewEmbedder() {
reset();

assert(() {
_setupHotRestart();
return true;
}());
}

static const int vibrateLongPress = 50;
static const int vibrateLightImpact = 10;
static const int vibrateMediumImpact = 20;
static const int vibrateHeavyImpact = 30;
static const int vibrateSelectionClick = 10;

// The tag name for the root view of the flutter app (glass-pane)
static const String _glassPaneTagName = 'flt-glass-pane';

Expand Down Expand Up @@ -175,52 +178,6 @@ class DomRenderer {

final html.Element rootElement = html.document.body!;

html.Element createElement(String tagName, {html.Element? parent}) {
final html.Element element = html.document.createElement(tagName);
parent?.append(element);
return element;
}

void appendText(html.Element parent, String text) {
parent.appendText(text);
}

static void setElementStyle(
html.Element element, String name, String? value) {
if (value == null) {
element.style.removeProperty(name);
} else {
element.style.setProperty(name, value);
}
}

static void setClipPath(html.Element element, String? value) {
if (browserEngine == BrowserEngine.webkit) {
if (value == null) {
element.style.removeProperty('-webkit-clip-path');
} else {
element.style.setProperty('-webkit-clip-path', value);
}
}
if (value == null) {
element.style.removeProperty('clip-path');
} else {
element.style.setProperty('clip-path', value);
}
}

void setThemeColor(ui.Color color) {
html.MetaElement? theme =
html.document.querySelector('#flutterweb-theme') as html.MetaElement?;
if (theme == null) {
theme = html.MetaElement()
..id = 'flutterweb-theme'
..name = 'theme-color';
html.document.head!.append(theme);
}
theme.content = colorToCssString(color)!;
}

static const String defaultFontStyle = 'normal';
static const String defaultFontWeight = 'normal';
static const double defaultFontSize = 14;
Expand Down Expand Up @@ -313,7 +270,7 @@ class DomRenderer {
// IMPORTANT: the glass pane element must come after the scene element in the DOM node list so
// it can intercept input events.
_glassPaneElement?.remove();
final html.Element glassPaneElement = createElement(_glassPaneTagName);
final html.Element glassPaneElement = html.document.createElement(_glassPaneTagName);
_glassPaneElement = glassPaneElement;
glassPaneElement.style
..position = 'absolute'
Expand All @@ -331,11 +288,11 @@ class DomRenderer {
_glassPaneShadow = glassPaneElementHostNode;

// Don't allow the scene to receive pointer events.
_sceneHostElement = createElement('flt-scene-host')
_sceneHostElement = html.document.createElement('flt-scene-host')
..style.pointerEvents = 'none';

final html.Element semanticsHostElement =
createElement('flt-semantics-host');
html.document.createElement('flt-semantics-host');
semanticsHostElement.style
..position = 'absolute'
..transformOrigin = '0 0 0';
Expand Down Expand Up @@ -456,41 +413,6 @@ class DomRenderer {
}
}

/// Removes all children of a DOM node.
void removeAllChildren(html.Node node) {
while (node.lastChild != null) {
node.lastChild!.remove();
}
}

static bool? _ellipseFeatureDetected;

/// Draws CanvasElement ellipse with fallback.
static void ellipse(
html.CanvasRenderingContext2D context,
double centerX,
double centerY,
double radiusX,
double radiusY,
double rotation,
double startAngle,
double endAngle,
bool antiClockwise) {
// ignore: implicit_dynamic_function
_ellipseFeatureDetected ??= js_util.getProperty(context, 'ellipse') != null;
if (_ellipseFeatureDetected!) {
context.ellipse(centerX, centerY, radiusX, radiusY, rotation, startAngle,
endAngle, antiClockwise);
} else {
context.save();
context.translate(centerX, centerY);
context.rotate(rotation);
context.scale(radiusX, radiusY);
context.arc(0, 0, 1, startAngle, endAngle, antiClockwise);
context.restore();
}
}

static const String orientationLockTypeAny = 'any';
static const String orientationLockTypeNatural = 'natural';
static const String orientationLockTypeLandscape = 'landscape';
Expand Down Expand Up @@ -596,44 +518,22 @@ class DomRenderer {

/// Removes a global resource element.
void removeResource(html.Element? element) {
element?.remove();
}

/// Provides haptic feedback.
void vibrate(int durationMs) {
final html.Navigator navigator = html.window.navigator;
if (js_util.hasProperty(navigator, 'vibrate')) {
// ignore: implicit_dynamic_function
js_util.callMethod(navigator, 'vibrate', <num>[durationMs]);
if (element == null) {
return;
}
assert(element.parent == _resourcesHost);
element.remove();
}

String get currentHtml => _rootApplicationElement?.outerHtml ?? '';

DebugDomRendererFrameStatistics? _debugFrameStatistics;

DebugDomRendererFrameStatistics? debugFlushFrameStatistics() {
if (!assertionsEnabled) {
throw Exception('This code should not be reachable in production.');
}
final DebugDomRendererFrameStatistics? current = _debugFrameStatistics;
_debugFrameStatistics = DebugDomRendererFrameStatistics();
return current;
}

void debugRulerCacheHit() => _debugFrameStatistics!.paragraphRulerCacheHits++;
void debugRulerCacheMiss() =>
_debugFrameStatistics!.paragraphRulerCacheMisses++;
void debugRichTextLayout() => _debugFrameStatistics!.richTextLayouts++;
void debugPlainTextLayout() => _debugFrameStatistics!.plainTextLayouts++;
}

// Applies the required global CSS to an incoming [html.CssStyleSheet] `sheet`.
void applyGlobalCssRulesToSheet(
html.CssStyleSheet sheet, {
required BrowserEngine browserEngine,
required bool hasAutofillOverlay,
String glassPaneTagName = DomRenderer._glassPaneTagName,
String glassPaneTagName = FlutterViewEmbedder._glassPaneTagName,
}) {
final bool isWebKit = browserEngine == BrowserEngine.webkit;
final bool isFirefox = browserEngine == BrowserEngine.firefox;
Expand Down Expand Up @@ -752,48 +652,9 @@ void applyGlobalCssRulesToSheet(
}
}

/// Miscellaneous statistics collecting during a single frame's execution.
///
/// This is useful when profiling the app. This class should only be used when
/// assertions are enabled and therefore is not suitable for collecting any
/// time measurements. It is mostly useful for counting certain events.
class DebugDomRendererFrameStatistics {
/// The number of times we reused a previously initialized paragraph ruler to
/// measure a paragraph of text.
int paragraphRulerCacheHits = 0;

/// The number of times we had to create a new paragraph ruler to measure a
/// paragraph of text.
int paragraphRulerCacheMisses = 0;

/// The number of times we used a paragraph ruler to measure a paragraph of
/// text.
int get totalParagraphRulerAccesses =>
paragraphRulerCacheHits + paragraphRulerCacheMisses;

/// The number of times a paragraph of rich text was laid out this frame.
int richTextLayouts = 0;

/// The number of times a paragraph of plain text was laid out this frame.
int plainTextLayouts = 0;

@override
String toString() {
return '''
Frame statistics:
Paragraph ruler cache hits: $paragraphRulerCacheHits
Paragraph ruler cache misses: $paragraphRulerCacheMisses
Paragraph ruler accesses: $totalParagraphRulerAccesses
Rich text layouts: $richTextLayouts
Plain text layouts: $plainTextLayouts
'''
.trim();
}
}

/// Singleton DOM renderer.
DomRenderer get domRenderer => ensureDomRendererInitialized();
/// The embedder singleton.
FlutterViewEmbedder get flutterViewEmbedder => ensureFlutterViewEmbedderInitialized();

/// Initializes the [DomRenderer], if it's not already initialized.
DomRenderer ensureDomRendererInitialized() => _domRenderer ??= DomRenderer();
DomRenderer? _domRenderer;
/// Initializes the [FlutterViewEmbedder], if it's not already initialized.
FlutterViewEmbedder ensureFlutterViewEmbedderInitialized() => _flutterViewEmbedder ??= FlutterViewEmbedder();
FlutterViewEmbedder? _flutterViewEmbedder;
2 changes: 1 addition & 1 deletion lib/web_ui/lib/src/engine/host_node.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import 'dart:html' as html;

import 'browser_detection.dart';
import 'dom_renderer.dart';
import 'embedder.dart';
import 'text_editing/text_editing.dart';

/// The interface required to host a flutter app in the DOM, and its tests.
Expand Down
5 changes: 2 additions & 3 deletions lib/web_ui/lib/src/engine/html/backdrop_filter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import 'dart:html' as html;
import 'package:ui/ui.dart' as ui;

import '../browser_detection.dart';
import '../dom_renderer.dart';
import '../util.dart';
import '../vector_math.dart';
import 'shaders/shader.dart';
Expand Down Expand Up @@ -122,10 +121,10 @@ class PersistedBackdropFilter extends PersistedContainerSurface
// Gaussian blur with standard deviation (normal distribution),
// the blur will fall within 2 * sigma pixels.
if (browserEngine == BrowserEngine.webkit) {
DomRenderer.setElementStyle(_filterElement!, '-webkit-backdrop-filter',
setElementStyle(_filterElement!, '-webkit-backdrop-filter',
filter.filterAttribute);
}
DomRenderer.setElementStyle(_filterElement!, 'backdrop-filter', filter.filterAttribute);
setElementStyle(_filterElement!, 'backdrop-filter', filter.filterAttribute);
}
}

Expand Down
Loading