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

Migrate SVG to JS types #40401

Merged
merged 2 commits into from
Mar 22, 2023
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
13 changes: 7 additions & 6 deletions lib/web_ui/lib/src/engine/canvaskit/image_web_codecs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import 'dart:async';
import 'dart:convert' show base64;
import 'dart:js_interop';
import 'dart:math' as math;
import 'dart:typed_data';

Expand Down Expand Up @@ -147,18 +148,18 @@ class CkBrowserImageDecoder implements ui.Codec {
_cacheExpirationClock.callback = null;
try {
final ImageDecoder webDecoder = ImageDecoder(ImageDecoderOptions(
type: contentType,
data: data,
type: contentType.toJS,
data: data.toJS,

// Flutter always uses premultiplied alpha when decoding.
premultiplyAlpha: 'premultiply',
premultiplyAlpha: 'premultiply'.toJS,
// "default" gives the browser the liberty to convert to display-appropriate
// color space, typically SRGB, which is what we want.
colorSpaceConversion: 'default',
colorSpaceConversion: 'default'.toJS,

// Flutter doesn't give the developer a way to customize this, so if this
// is an animated image we should prefer the animated track.
preferAnimation: true,
preferAnimation: true.toJS,
));

await promiseToFuture<void>(webDecoder.tracks.ready);
Expand Down Expand Up @@ -217,7 +218,7 @@ class CkBrowserImageDecoder implements ui.Codec {
_debugCheckNotDisposed();
final ImageDecoder webDecoder = await _getOrCreateWebDecoder();
final DecodeResult result = await promiseToFuture<DecodeResult>(
webDecoder.decode(DecodeOptions(frameIndex: _nextFrameIndex.toDouble())),
webDecoder.decode(DecodeOptions(frameIndex: _nextFrameIndex.toJS)),
);
final VideoFrame frame = result.image;
_nextFrameIndex = (_nextFrameIndex + 1) % frameCount;
Expand Down
34 changes: 27 additions & 7 deletions lib/web_ui/lib/src/engine/configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
@JS()
library configuration;

import 'dart:js_interop';
import 'package:js/js.dart';
import 'package:meta/meta.dart';
import 'canvaskit/renderer.dart';
Expand Down Expand Up @@ -266,16 +267,35 @@ external JsFlutterConfiguration? get _jsConfiguration;
class JsFlutterConfiguration {}

extension JsFlutterConfigurationExtension on JsFlutterConfiguration {
external String? get canvasKitBaseUrl;
external String? get canvasKitVariant;
external bool? get canvasKitForceCpuOnly;
external double? get canvasKitMaximumSurfaces;
external bool? get debugShowSemanticsNodes;
@JS('canvasKitBaseUrl')
external JSString? get _canvasKitBaseUrl;
String? get canvasKitBaseUrl => _canvasKitBaseUrl?.toDart;

@JS('canvasKitVariant')
external JSString? get _canvasKitVariant;
String? get canvasKitVariant => _canvasKitVariant?.toDart;

@JS('canvasKitForceCpuOnly')
external JSBoolean? get _canvasKitForceCpuOnly;
bool? get canvasKitForceCpuOnly => _canvasKitForceCpuOnly?.toDart;

@JS('canvasKitMaximumSurfaces')
external JSNumber? get _canvasKitMaximumSurfaces;
double? get canvasKitMaximumSurfaces => _canvasKitMaximumSurfaces?.toDart;

@JS('debugShowSemanticsNodes')
external JSBoolean? get _debugShowSemanticsNodes;
bool? get debugShowSemanticsNodes => _debugShowSemanticsNodes?.toDart;

external DomElement? get hostElement;
external String? get renderer;

@JS('renderer')
external JSString? get _renderer;
String? get renderer => _renderer?.toDart;
}

/// A JavaScript entrypoint that allows developer to set rendering backend
/// at runtime before launching the application.
@JS('window.flutterWebRenderer')
external String? get _requestedRendererType;
external JSString? get __requestedRendererType;
String? get _requestedRendererType => __requestedRendererType?.toDart;
7 changes: 2 additions & 5 deletions lib/web_ui/lib/src/engine/dom.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2260,13 +2260,10 @@ extension DomMediaQueryListExtension on DomMediaQueryList {
bool get matches => _matches.toDart;

@JS('addListener')
external JSVoid _addListener(JSFunction? listener);
void addListener(DomEventListener? listener) => _addListener(listener?.toJS);
external JSVoid addListener(JSFunction? listener);

@JS('removeListener')
external JSVoid _removeListener(JSFunction? listener);
void removeListener(DomEventListener? listener) =>
_removeListener(listener?.toJS);
external JSVoid removeListener(JSFunction? listener);
}

@JS()
Expand Down
12 changes: 6 additions & 6 deletions lib/web_ui/lib/src/engine/platform_dispatcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ class HighContrastSupport {

/// Reference to css media query that indicates whether high contrast is on.
final DomMediaQueryList _highContrastMediaQuery = domWindow.matchMedia(_highContrastMediaQueryString);
late final DomEventListener _onHighContrastChangeListener =
allowInterop(_onHighContrastChange);
late final JSFunction _onHighContrastChangeListener =
_onHighContrastChange.toJS;

bool get isHighContrastEnabled => _highContrastMediaQuery.matches;

Expand All @@ -64,7 +64,7 @@ class HighContrastSupport {
}
}

void _onHighContrastChange(DomEvent event) {
JSVoid _onHighContrastChange(DomEvent event) {
final DomMediaQueryListEvent mqEvent = event as DomMediaQueryListEvent;
final bool isHighContrastEnabled = mqEvent.matches!;
for (final HighContrastListener listener in _listeners) {
Expand Down Expand Up @@ -1031,20 +1031,20 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
/// A callback that is invoked whenever [_brightnessMediaQuery] changes value.
///
/// Updates the [_platformBrightness] with the new user preference.
DomEventListener? _brightnessMediaQueryListener;
JSFunction? _brightnessMediaQueryListener;

/// Set the callback function for listening changes in [_brightnessMediaQuery] value.
void _addBrightnessMediaQueryListener() {
_updatePlatformBrightness(_brightnessMediaQuery.matches
? ui.Brightness.dark
: ui.Brightness.light);

_brightnessMediaQueryListener = allowInterop((DomEvent event) {
_brightnessMediaQueryListener = (DomEvent event) {
final DomMediaQueryListEvent mqEvent =
event as DomMediaQueryListEvent;
_updatePlatformBrightness(
mqEvent.matches! ? ui.Brightness.dark : ui.Brightness.light);
});
}.toJS;
_brightnessMediaQuery.addListener(_brightnessMediaQueryListener);
}

Expand Down
4 changes: 3 additions & 1 deletion lib/web_ui/lib/src/engine/profiler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// found in the LICENSE file.

import 'dart:async';
import 'dart:js_interop';

import 'package:js/js.dart';
import 'package:ui/ui.dart' as ui;
Expand All @@ -12,7 +13,8 @@ import 'platform_dispatcher.dart';
import 'safe_browser_api.dart';

@JS('window._flutter_internal_on_benchmark')
external Object? get onBenchmark;
external JSAny? get _onBenchmark;
Object? get onBenchmark => _onBenchmark?.toObjectShallow;

/// A function that computes a value of type [R].
///
Expand Down
85 changes: 62 additions & 23 deletions lib/web_ui/lib/src/engine/safe_browser_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
library browser_api;

import 'dart:async';
import 'dart:js_interop';
import 'dart:js_util' as js_util;
import 'dart:math' as math;
import 'dart:typed_data';
Expand Down Expand Up @@ -201,7 +202,9 @@ DomCanvasElement? tryCreateCanvasElement(int width, int height) {
}

@JS('window.ImageDecoder')
external Object? get _imageDecoderConstructor;
external JSAny? get __imageDecoderConstructor;
Object? get _imageDecoderConstructor =>
__imageDecoderConstructor?.toObjectShallow;

/// Environment variable that allows the developer to opt out of using browser's
/// `ImageDecoder` API, and use the WASM codecs bundled with CanvasKit.
Expand Down Expand Up @@ -265,9 +268,13 @@ class ImageDecoder {

extension ImageDecoderExtension on ImageDecoder {
external ImageTrackList get tracks;
external bool get complete;

@JS('complete')
external JSBoolean get _complete;
bool get complete => _complete.toDart;

external JsPromise decode(DecodeOptions options);
external void close();
external JSVoid close();
}

/// Options passed to the `ImageDecoder` constructor.
Expand All @@ -280,13 +287,13 @@ extension ImageDecoderExtension on ImageDecoder {
@staticInterop
class ImageDecoderOptions {
external factory ImageDecoderOptions({
required String type,
required Uint8List data,
required String premultiplyAlpha,
int? desiredWidth,
int? desiredHeight,
required String colorSpaceConversion,
required bool preferAnimation,
required JSString type,
required JSUint8Array data,
required JSString premultiplyAlpha,
JSNumber? desiredWidth,
JSNumber? desiredHeight,
required JSString colorSpaceConversion,
required JSBoolean preferAnimation,
});
}

Expand All @@ -302,7 +309,10 @@ class DecodeResult {}

extension DecodeResultExtension on DecodeResult {
external VideoFrame get image;
external bool get complete;

@JS('complete')
external JSBoolean get _complete;
bool get complete => _complete.toDart;
}

/// Options passed to [ImageDecoder.decode].
Expand All @@ -315,7 +325,7 @@ extension DecodeResultExtension on DecodeResult {
@staticInterop
class DecodeOptions {
external factory DecodeOptions({
required double frameIndex,
required JSNumber frameIndex,
});
}

Expand All @@ -332,16 +342,40 @@ class DecodeOptions {
class VideoFrame implements DomCanvasImageSource {}

extension VideoFrameExtension on VideoFrame {
external double allocationSize();
external JsPromise copyTo(Object destination);
external String? get format;
external double get codedWidth;
external double get codedHeight;
external double get displayWidth;
external double get displayHeight;
external double? get duration;
@JS('allocationSize')
external JSNumber _allocationSize();
double allocationSize() => _allocationSize().toDart;

@JS('copyTo')
external JsPromise _copyTo(JSAny destination);
JsPromise copyTo(Object destination) => _copyTo(destination.toJSAnyShallow);

@JS('format')
external JSString? get _format;
String? get format => _format?.toDart;

@JS('codedWidth')
external JSNumber get _codedWidth;
double get codedWidth => _codedWidth.toDart;

@JS('codedHeight')
external JSNumber get _codedHeight;
double get codedHeight => _codedHeight.toDart;

@JS('displayWidth')
external JSNumber get _displayWidth;
double get displayWidth => _displayWidth.toDart;

@JS('displayHeight')
external JSNumber get _displayHeight;
double get displayHeight => _displayHeight.toDart;

@JS('duration')
external JSNumber? get _duration;
double? get duration => _duration?.toDart;

external VideoFrame clone();
external void close();
external JSVoid close();
}

/// Corresponds to the browser's `ImageTrackList` type.
Expand Down Expand Up @@ -370,8 +404,13 @@ extension ImageTrackListExtension on ImageTrackList {
class ImageTrack {}

extension ImageTrackExtension on ImageTrack {
external double get repetitionCount;
external double get frameCount;
@JS('repetitionCount')
external JSNumber get _repetitionCount;
double get repetitionCount => _repetitionCount.toDart;

@JS('frameCount')
external JSNumber get _frameCount;
double get frameCount => _frameCount.toDart;
}

void scaleCanvas2D(Object context2d, num x, num y) {
Expand Down
27 changes: 21 additions & 6 deletions lib/web_ui/lib/src/engine/svg.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:js_interop';
import 'package:js/js.dart';

import 'dom.dart';
Expand Down Expand Up @@ -91,8 +92,14 @@ extension SVGAnimatedLengthExtension on SVGAnimatedLength {
class SVGLength {}

extension SVGLengthExtension on SVGLength {
external set valueAsString(String? value);
external void newValueSpecifiedUnits(int unitType, num valueInSpecifiedUnits);
@JS('valueAsString')
external set _valueAsString(JSString? value);
set valueAsString(String? value) => _valueAsString = value?.toJS;

@JS('newValueSpecifiedUnits')
external JSVoid _newValueSpecifiedUnits(JSNumber unitType, JSNumber valueInSpecifiedUnits);
void newValueSpecifiedUnits(int unitType, num valueInSpecifiedUnits) =>
_newValueSpecifiedUnits(unitType.toJS, valueInSpecifiedUnits.toJS);
}

const int svgLengthTypeNumber = 1;
Expand All @@ -102,7 +109,9 @@ const int svgLengthTypeNumber = 1;
class SVGAnimatedEnumeration {}

extension SVGAnimatedEnumerationExtenson on SVGAnimatedEnumeration {
external set baseVal(int? value);
@JS('baseVal')
external set _baseVal(JSNumber? value);
set baseVal(int? value) => _baseVal = value?.toJS;
}

@JS()
Expand Down Expand Up @@ -186,15 +195,19 @@ extension SVGFEBlendCompositeExtension on SVGFECompositeElement {
class SVGAnimatedString {}

extension SVGAnimatedStringExtension on SVGAnimatedString {
external set baseVal(String? value);
@JS('baseVal')
external set _baseVal(JSString? value);
set baseVal(String? value) => _baseVal = value?.toJS;
}

@JS()
@staticInterop
class SVGAnimatedNumber {}

extension SVGAnimatedNumberExtension on SVGAnimatedNumber {
external set baseVal(num? value);
@JS('baseVal')
external set _baseVal(JSNumber? value);
set baseVal(num? value) => _baseVal = value?.toJS;
}

@JS()
Expand All @@ -218,5 +231,7 @@ extension SVGNumberListExtension on SVGNumberList {
class SVGNumber {}

extension SVGNumberExtension on SVGNumber {
external set value(num? value);
@JS('value')
external set _value(JSNumber? value);
set value(num? v) => _value = v?.toJS;
}
Loading