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

[web] Migrate Flutter Web DOM usage to JS static interop - 28. #33356

Merged
merged 2 commits into from
Jun 13, 2022
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
87 changes: 41 additions & 46 deletions lib/web_ui/lib/src/engine/canvas_pool.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +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 'dart:math' as math;
import 'dart:typed_data';

Expand Down Expand Up @@ -46,17 +45,17 @@ import 'window.dart';
/// can be reused, [CanvasPool] will move canvas(s) from pool to reusablePool
/// to prevent reallocation.
class CanvasPool extends _SaveStackTracking {
html.CanvasRenderingContext2D? _context;
DomCanvasRenderingContext2D? _context;
ContextStateHandle? _contextHandle;
final int _widthInBitmapPixels, _heightInBitmapPixels;
// List of canvases that have been allocated and used in this paint cycle.
List<html.CanvasElement>? _activeCanvasList;
List<DomCanvasElement>? _activeCanvasList;
// List of canvases available to reuse from prior paint cycle.
List<html.CanvasElement>? _reusablePool;
List<DomCanvasElement>? _reusablePool;
// Current canvas element or null if marked for lazy allocation.
html.CanvasElement? _canvas;
DomCanvasElement? _canvas;

html.HtmlElement? _rootElement;
DomHTMLElement? _rootElement;
int _saveContextCount = 0;
final double _density;

Expand All @@ -65,7 +64,7 @@ class CanvasPool extends _SaveStackTracking {
this._density);

/// Initializes canvas pool to be hosted on a surface.
void mount(html.HtmlElement rootElement) {
void mount(DomHTMLElement rootElement) {
_rootElement = rootElement;
}

Expand All @@ -78,8 +77,8 @@ class CanvasPool extends _SaveStackTracking {
}

/// Returns [CanvasRenderingContext2D] api to draw into this canvas.
html.CanvasRenderingContext2D get context {
html.CanvasRenderingContext2D? ctx = _context;
DomCanvasRenderingContext2D get context {
DomCanvasRenderingContext2D? ctx = _context;
if (ctx == null) {
_createCanvas();
ctx = _context!;
Expand Down Expand Up @@ -128,7 +127,7 @@ class CanvasPool extends _SaveStackTracking {
if (_canvas != null) {
_restoreContextSave();
_contextHandle!.reset();
_activeCanvasList ??= <html.CanvasElement>[];
_activeCanvasList ??= <DomCanvasElement>[];
_activeCanvasList!.add(_canvas!);
_canvas = null;
_context = null;
Expand All @@ -139,7 +138,7 @@ class CanvasPool extends _SaveStackTracking {
void _createCanvas() {
bool requiresClearRect = false;
bool reused = false;
html.CanvasElement? canvas;
DomCanvasElement? canvas;
if (_canvas != null) {
_canvas!.width = 0;
_canvas!.height = 0;
Expand Down Expand Up @@ -214,13 +213,13 @@ class CanvasPool extends _SaveStackTracking {
_replayClipStack();
}

html.CanvasElement? _allocCanvas(int width, int height) {
DomCanvasElement? _allocCanvas(int width, int height) {
// The dartdocs for `tryCreateCanvasElement` on why we don't use the
// `html.CanvasElement` constructor.
// `DomCanvasElement` constructor.
return tryCreateCanvasElement(
(width * _density).ceil(),
(height * _density).ceil(),
);
) as DomCanvasElement?;
}

@override
Expand All @@ -229,7 +228,7 @@ class CanvasPool extends _SaveStackTracking {

if (_canvas != null) {
// Restore to the state where we have only applied the scaling.
final html.CanvasRenderingContext2D? ctx = _context;
final DomCanvasRenderingContext2D? ctx = _context;
if (ctx != null) {
try {
ctx.font = '';
Expand All @@ -247,7 +246,7 @@ class CanvasPool extends _SaveStackTracking {

int _replaySingleSaveEntry(int clipDepth, Matrix4 prevTransform,
Matrix4 transform, List<SaveClipEntry>? clipStack) {
final html.CanvasRenderingContext2D ctx = context;
final DomCanvasRenderingContext2D ctx = context;
if (clipStack != null) {
for (final int clipCount = clipStack.length;
clipDepth < clipCount;
Expand Down Expand Up @@ -306,7 +305,7 @@ class CanvasPool extends _SaveStackTracking {

void _replayClipStack() {
// Replay save/clip stack on this canvas now.
final html.CanvasRenderingContext2D ctx = context;
final DomCanvasRenderingContext2D ctx = context;
int clipDepth = 0;
Matrix4 prevTransform = Matrix4.identity();
final int len = _saveStack.length;
Expand All @@ -327,7 +326,7 @@ class CanvasPool extends _SaveStackTracking {
if (_canvas != null) {
_restoreContextSave();
_contextHandle!.reset();
_activeCanvasList ??= <html.CanvasElement>[];
_activeCanvasList ??= <DomCanvasElement>[];
_activeCanvasList!.add(_canvas!);
_context = null;
_contextHandle = null;
Expand All @@ -344,7 +343,7 @@ class CanvasPool extends _SaveStackTracking {
/// that are reused from last instance can be cleanup.
void endOfPaint() {
if (_reusablePool != null) {
for (final html.CanvasElement e in _reusablePool!) {
for (final DomCanvasElement e in _reusablePool!) {
if (browserEngine == BrowserEngine.webkit) {
e.width = e.height = 0;
}
Expand All @@ -366,7 +365,7 @@ class CanvasPool extends _SaveStackTracking {
/// coordinate system, and the pixel ratio is applied such that CSS pixels are
/// translated to bitmap pixels.
void _initializeViewport(bool clearCanvas) {
final html.CanvasRenderingContext2D ctx = context;
final DomCanvasRenderingContext2D ctx = context;
// Save the canvas state with top-level transforms so we can undo
// any clips later when we reuse the canvas.
ctx.save();
Expand All @@ -390,7 +389,7 @@ class CanvasPool extends _SaveStackTracking {
EnginePlatformDispatcher.browserDevicePixelRatio * _density;

void _resetTransform() {
final html.CanvasElement? canvas = _canvas;
final DomCanvasElement? canvas = _canvas;
if (canvas != null) {
canvas.style.transformOrigin = '';
canvas.style.transform = '';
Expand All @@ -399,7 +398,7 @@ class CanvasPool extends _SaveStackTracking {

/// Returns a "data://" URI containing a representation of the image in this
/// canvas in PNG format.
String toDataUrl() => _canvas?.toDataUrl() ?? '';
String toDataUrl() => _canvas?.toDataURL('image/png') ?? '';

@override
void save() {
Expand Down Expand Up @@ -498,7 +497,7 @@ class CanvasPool extends _SaveStackTracking {
}
}

void _clipRect(html.CanvasRenderingContext2D ctx, ui.Rect rect) {
void _clipRect(DomCanvasRenderingContext2D ctx, ui.Rect rect) {
ctx.beginPath();
ctx.rect(rect.left, rect.top, rect.width, rect.height);
ctx.clip();
Expand All @@ -512,7 +511,7 @@ class CanvasPool extends _SaveStackTracking {
}
}

void _clipRRect(html.CanvasRenderingContext2D ctx, ui.RRect rrect) {
void _clipRRect(DomCanvasRenderingContext2D ctx, ui.RRect rrect) {
final ui.Path path = ui.Path()..addRRect(rrect);
_runPath(ctx, path as SurfacePath);
ctx.clip();
Expand All @@ -522,7 +521,7 @@ class CanvasPool extends _SaveStackTracking {
void clipPath(ui.Path path) {
super.clipPath(path);
if (_canvas != null) {
final html.CanvasRenderingContext2D ctx = context;
final DomCanvasRenderingContext2D ctx = context;
_runPath(ctx, path as SurfacePath);
if (path.fillType == ui.PathFillType.nonZero) {
ctx.clip();
Expand All @@ -534,7 +533,7 @@ class CanvasPool extends _SaveStackTracking {

/// Fill a virtually infinite rect with a color and optional blendMode.
void drawColor(ui.Color color, ui.BlendMode blendMode) {
final html.CanvasRenderingContext2D ctx = context;
final DomCanvasRenderingContext2D ctx = context;
contextHandle.blendMode = blendMode;
contextHandle.fillStyle = colorToCssString(color);
contextHandle.strokeStyle = '';
Expand All @@ -548,7 +547,7 @@ class CanvasPool extends _SaveStackTracking {

/// Fill a virtually infinite rect with the color.
void fill() {
final html.CanvasRenderingContext2D ctx = context;
final DomCanvasRenderingContext2D ctx = context;
ctx.beginPath();
// We can't use (0, 0, width, height) because the current transform can
// cause it to not fill the entire clip.
Expand All @@ -557,7 +556,7 @@ class CanvasPool extends _SaveStackTracking {

/// Draws a line from [p1] to [p2].
void strokeLine(ui.Offset p1, ui.Offset p2) {
final html.CanvasRenderingContext2D ctx = context;
final DomCanvasRenderingContext2D ctx = context;
ctx.beginPath();
final ui.Rect? shaderBounds = contextHandle._shaderBounds;
if (shaderBounds == null) {
Expand All @@ -573,7 +572,7 @@ class CanvasPool extends _SaveStackTracking {
/// Draws a set of points with given radius, lines between points or
/// a polygon.
void drawPoints(ui.PointMode pointMode, Float32List points, double radius) {
final html.CanvasRenderingContext2D ctx = context;
final DomCanvasRenderingContext2D ctx = context;
final int len = points.length;
final ui.Rect? shaderBounds = contextHandle._shaderBounds;
final double offsetX = shaderBounds == null ? 0 : -shaderBounds.left;
Expand Down Expand Up @@ -611,7 +610,7 @@ class CanvasPool extends _SaveStackTracking {
static Float32List _runBuffer = Float32List(PathRefIterator.kMaxBufferSize);

/// 'Runs' the given [path] by applying all of its commands to the canvas.
void _runPath(html.CanvasRenderingContext2D ctx, SurfacePath path) {
void _runPath(DomCanvasRenderingContext2D ctx, SurfacePath path) {
ctx.beginPath();
final Float32List p = _runBuffer;
final PathRefIterator iter = PathRefIterator(path.pathRef);
Expand Down Expand Up @@ -668,7 +667,7 @@ class CanvasPool extends _SaveStackTracking {
/// Applies path to drawing context, preparing for fill and other operations.
///
/// WARNING: Don't refactor _runPath/_runPathWithOffset. Latency sensitive
void _runPathWithOffset(html.CanvasRenderingContext2D ctx, SurfacePath path,
void _runPathWithOffset(DomCanvasRenderingContext2D ctx, SurfacePath path,
double offsetX, double offsetY) {
ctx.beginPath();
final Float32List p = _runBuffer;
Expand Down Expand Up @@ -857,7 +856,7 @@ class CanvasPool extends _SaveStackTracking {

void _clearActiveCanvasList() {
if (_activeCanvasList != null) {
for (final html.CanvasElement c in _activeCanvasList!) {
for (final DomCanvasElement c in _activeCanvasList!) {
if (browserEngine == BrowserEngine.webkit) {
c.width = c.height = 0;
}
Expand All @@ -874,7 +873,7 @@ class CanvasPool extends _SaveStackTracking {
/// to initialize current values.
class ContextStateHandle {
/// Associated canvas element context tracked by this context state.
final html.CanvasRenderingContext2D context;
final DomCanvasRenderingContext2D context;
final CanvasPool _canvasPool;
/// Dpi of context.
final double density;
Expand All @@ -890,7 +889,7 @@ class ContextStateHandle {
Object? _currentStrokeStyle;
double _currentLineWidth = 1.0;

/// See [html.CanvasRenderingContext2D].
/// See [DomCanvasRenderingContext2D].
set blendMode(ui.BlendMode? blendMode) {
if (blendMode != _currentBlendMode) {
_currentBlendMode = blendMode;
Expand All @@ -899,7 +898,7 @@ class ContextStateHandle {
}
}

/// See [html.CanvasRenderingContext2D].
/// See [DomCanvasRenderingContext2D].
set strokeCap(ui.StrokeCap? strokeCap) {
strokeCap ??= ui.StrokeCap.butt;
if (strokeCap != _currentStrokeCap) {
Expand All @@ -908,15 +907,15 @@ class ContextStateHandle {
}
}

/// See [html.CanvasRenderingContext2D].
/// See [DomCanvasRenderingContext2D].
set lineWidth(double lineWidth) {
if (lineWidth != _currentLineWidth) {
_currentLineWidth = lineWidth;
context.lineWidth = lineWidth;
}
}

/// See [html.CanvasRenderingContext2D].
/// See [DomCanvasRenderingContext2D].
set strokeJoin(ui.StrokeJoin? strokeJoin) {
strokeJoin ??= ui.StrokeJoin.miter;
if (strokeJoin != _currentStrokeJoin) {
Expand All @@ -925,15 +924,15 @@ class ContextStateHandle {
}
}

/// See [html.CanvasRenderingContext2D].
/// See [DomCanvasRenderingContext2D].
set fillStyle(Object? colorOrGradient) {
if (!identical(colorOrGradient, _currentFillStyle)) {
_currentFillStyle = colorOrGradient;
context.fillStyle = colorOrGradient;
}
}

/// See [html.CanvasRenderingContext2D].
/// See [DomCanvasRenderingContext2D].
set strokeStyle(Object? colorOrGradient) {
if (!identical(colorOrGradient, _currentStrokeStyle)) {
_currentStrokeStyle = colorOrGradient;
Expand Down Expand Up @@ -984,9 +983,7 @@ class ContextStateHandle {
if (paint.shader is EngineGradient) {
final EngineGradient engineShader = paint.shader! as EngineGradient;
final Object paintStyle =
engineShader.createPaintStyle(_canvasPool.context as
DomCanvasRenderingContext2D, shaderBounds,
density);
engineShader.createPaintStyle(_canvasPool.context, shaderBounds, density);
fillStyle = paintStyle;
strokeStyle = paintStyle;
_shaderBounds = shaderBounds;
Expand All @@ -995,9 +992,7 @@ class ContextStateHandle {
} else if (paint.shader is EngineImageShader) {
final EngineImageShader imageShader = paint.shader! as EngineImageShader;
final Object paintStyle =
imageShader.createPaintStyle(_canvasPool.context as
DomCanvasRenderingContext2D, shaderBounds,
density);
imageShader.createPaintStyle(_canvasPool.context, shaderBounds, density);
fillStyle = paintStyle;
strokeStyle = paintStyle;
if (imageShader.requiresTileOffset) {
Expand Down Expand Up @@ -1117,7 +1112,7 @@ class ContextStateHandle {
}

/// Resets drawing context state to defaults for
/// [html.CanvasRenderingContext2D].
/// [DomCanvasRenderingContext2D].
void reset() {
context.fillStyle = '';
// Read back fillStyle/strokeStyle values from context so that input such
Expand Down
Loading