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 3 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
4 changes: 1 addition & 3 deletions lib/web_ui/lib/src/engine/browser_detection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,4 @@ int _detectWebGLVersion() {
}

/// Whether the current browser supports the Chromium variant of CanvasKit.
const bool browserSupportsCanvaskitChromium = false;
// TODO(mdebbar): Uncomment this to enable real detection of browser support.
// final bool browserSupportsCanvaskitChromium = domIntl.v8BreakIterator != null;
final bool browserSupportsCanvaskitChromium = domIntl.v8BreakIterator != null;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If canvaskit_chromium also removes the wasm image codecs, then this should also add && browserSupportsImageDecoder. Although in practice, I'm not aware of any Chromium-based browser not supporting image decoders.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

90 changes: 35 additions & 55 deletions lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,9 @@ import 'renderer.dart';
/// Entrypoint into the CanvasKit API.
late CanvasKit canvasKit;

late CanvasKitVariant _canvasKitVariant;

/// Which variant of CanvasKit we are using.
CanvasKitVariant get canvasKitVariant => _canvasKitVariant;
set canvasKitVariant(CanvasKitVariant value) {
if (value == CanvasKitVariant.auto) {
throw ArgumentError.value(
value,
'value',
'CanvasKitVariant.auto is not a valid value for canvasKitVariant',
);
}
_canvasKitVariant = value;
}

/// TODO(mdebbar): Turn this on when CanvasKit Chromium is ready.
/// https://github.com/flutter/flutter/issues/122329
const bool _enableCanvasKitChromiumInAutoMode = false;

/// Sets the [CanvasKit] object on `window` so we can use `@JS()` to bind to
/// static APIs.
Expand Down Expand Up @@ -1884,6 +1872,13 @@ extension SkParagraphBuilderNamespaceExtension on SkParagraphBuilderNamespace {
SkParagraphStyle paragraphStyle,
TypefaceFontProvider? fontManager,
);

bool RequiresClientICU() {
if (!js_util.hasProperty(this, 'RequiresClientICU')) {
return false;
}
return js_util.callMethod(this, 'RequiresClientICU', const <Object>[],) as bool;
}
}

@JS()
Expand Down Expand Up @@ -2699,47 +2694,26 @@ void patchCanvasKitModule(DomHTMLScriptElement canvasKitScript) {
}
}

String get _canvasKitBaseUrl => configuration.canvasKitBaseUrl;

const String _kFullCanvasKitJsFileName = 'canvaskit.js';
const String _kChromiumCanvasKitJsFileName = 'chromium/canvaskit.js';

// TODO(mdebbar): Replace this with a Record once it's supported in Dart.
class _CanvasKitVariantUrl {
const _CanvasKitVariantUrl(this.url, this.variant)
: assert(
variant != CanvasKitVariant.auto,
'CanvasKitVariant.auto cannot have a url',
);

final String url;
final CanvasKitVariant variant;

static _CanvasKitVariantUrl chromium = _CanvasKitVariantUrl(
'$_canvasKitBaseUrl$_kChromiumCanvasKitJsFileName',
CanvasKitVariant.chromium,
);

static _CanvasKitVariantUrl full = _CanvasKitVariantUrl(
'$_canvasKitBaseUrl$_kFullCanvasKitJsFileName',
CanvasKitVariant.full,
);
}

List<_CanvasKitVariantUrl> get _canvasKitUrls {
String get _canvasKitBaseUrl => configuration.canvasKitBaseUrl;
List<String> get _canvasKitJsFileNames {
switch (configuration.canvasKitVariant) {
case CanvasKitVariant.auto:
return <_CanvasKitVariantUrl>[
if (browserSupportsCanvaskitChromium) _CanvasKitVariantUrl.chromium,
_CanvasKitVariantUrl.full,
return <String>[
if (_enableCanvasKitChromiumInAutoMode) _kChromiumCanvasKitJsFileName,
_kFullCanvasKitJsFileName,
];
case CanvasKitVariant.full:
return <_CanvasKitVariantUrl>[_CanvasKitVariantUrl.full];
return <String>[_kFullCanvasKitJsFileName];
case CanvasKitVariant.chromium:
return <_CanvasKitVariantUrl>[_CanvasKitVariantUrl.chromium];
return <String>[_kChromiumCanvasKitJsFileName];
}
}

Iterable<String> get _canvasKitJsUrls {
return _canvasKitJsFileNames.map((String filename) => '$_canvasKitBaseUrl$filename');
}
@visibleForTesting
String canvasKitWasmModuleUrl(String file, String canvasKitBase) =>
canvasKitBase + file;
Expand All @@ -2749,23 +2723,29 @@ String canvasKitWasmModuleUrl(String file, String canvasKitBase) =>
/// Downloads the CanvasKit JavaScript, then calls `CanvasKitInit` to download
/// and intialize the CanvasKit wasm.
Future<CanvasKit> downloadCanvasKit() async {
await _downloadOneOf(_canvasKitUrls);
await _downloadOneOf(_canvasKitJsUrls);

return CanvasKitInit(CanvasKitInitOptions(
final CanvasKit canvasKit = await CanvasKitInit(CanvasKitInitOptions(
locateFile: allowInterop(canvasKitWasmModuleUrl),
));

if (canvasKit.ParagraphBuilder.RequiresClientICU() && !browserSupportsCanvaskitChromium) {
throw Exception(
'The CanvasKit variant you are using only works on Chromium browsers. '
'Please use a different CanvasKit variant, or use a Chromium browser.',
);
}

return canvasKit;
}

/// Finds the first entry in [urls] that can be downloaded successfully, and
/// Finds the first URL in [urls] that can be downloaded successfully, and
/// downloads it.
///
/// If none of the URLs can be downloaded, throws an [Exception].
///
/// Also sets [canvasKitVariant] to the variant of CanvasKit that was downloaded.
Future<void> _downloadOneOf(Iterable<_CanvasKitVariantUrl> urls) async {
for (final _CanvasKitVariantUrl entry in urls) {
if (await _downloadCanvasKitJs(entry.url)) {
canvasKitVariant = entry.variant;
Future<void> _downloadOneOf(Iterable<String> urls) async {
for (final String url in urls) {
if (await _downloadCanvasKitJs(url)) {
return;
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/web_ui/lib/src/engine/canvaskit/text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,7 @@ class CkParagraphBuilder implements ui.ParagraphBuilder {

/// Builds the CkParagraph with the builder and deletes the builder.
SkParagraph _buildSkParagraph() {
if (canvasKitVariant == CanvasKitVariant.chromium) {
if (canvasKit.ParagraphBuilder.RequiresClientICU()) {
injectClientICU(_paragraphBuilder);
}
final SkParagraph result = _paragraphBuilder.build();
Expand Down
3 changes: 1 addition & 2 deletions lib/web_ui/lib/src/engine/canvaskit/text_fragmenter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ import 'dart:typed_data';
import '../dom.dart';
import '../text/line_breaker.dart';
import 'canvaskit_api.dart';
import 'renderer.dart';

/// Injects required ICU data into the [builder].
///
/// This should only be used with the CanvasKit Chromium variant that's compiled
/// without ICU data.
void injectClientICU(SkParagraphBuilder builder) {
assert(
canvasKitVariant == CanvasKitVariant.chromium,
canvasKit.ParagraphBuilder.RequiresClientICU(),
'This method should only be used with the CanvasKit Chromium variant.',
);

Expand Down
4 changes: 2 additions & 2 deletions lib/web_ui/test/canvaskit/canvaskit_api_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1624,7 +1624,7 @@ void _paragraphTests() {
builder.pushStyle(
canvasKit.TextStyle(SkTextStyleProperties()..halfLeading = true));
builder.pop();
if (canvasKitVariant == CanvasKitVariant.chromium) {
if (canvasKit.ParagraphBuilder.RequiresClientICU()) {
injectClientICU(builder);
}
final SkParagraph paragraph = builder.build();
Expand Down Expand Up @@ -1742,7 +1742,7 @@ void _paragraphTests() {
);
builder.addText('hello');

if (canvasKitVariant == CanvasKitVariant.chromium) {
if (canvasKit.ParagraphBuilder.RequiresClientICU()) {
injectClientICU(builder);
}

Expand Down