From c257cf7c708a9d52d8fe6e867fb1bd0aeabd901e Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Wed, 5 Feb 2020 13:31:50 -0800 Subject: [PATCH 1/4] - Enable dynamically loaded fonts - Fix addOval - Fix getBoxesForRange for negative ranges --- lib/web_ui/lib/src/engine/compositor/fonts.dart | 11 +++++++++++ .../lib/src/engine/compositor/initialization.dart | 2 +- lib/web_ui/lib/src/engine/compositor/path.dart | 2 +- lib/web_ui/lib/src/engine/compositor/text.dart | 6 +++++- lib/web_ui/lib/src/ui/text.dart | 12 +++++++++--- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/lib/web_ui/lib/src/engine/compositor/fonts.dart b/lib/web_ui/lib/src/engine/compositor/fonts.dart index b079f4c86ab66..cfb1dce1e49fa 100644 --- a/lib/web_ui/lib/src/engine/compositor/fonts.dart +++ b/lib/web_ui/lib/src/engine/compositor/fonts.dart @@ -7,8 +7,10 @@ part of engine; const String _robotoUrl = 'https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Me5WZLCzYlKw.ttf'; +/// Manages the fonts used in the Skia-based backend. class SkiaFontCollection { final List> _loadingFontBuffers = >[]; + final List _dynamicallyLoadedFonts = []; final Set registeredFamilies = {}; @@ -17,9 +19,18 @@ class SkiaFontCollection { (await Future.wait(_loadingFontBuffers)) .map((ByteBuffer buffer) => buffer.asUint8List()) .toList(); + fontBuffers.addAll(_dynamicallyLoadedFonts); skFontMgr = canvasKit['SkFontMgr'].callMethod('FromData', fontBuffers); } + Future loadFontFromList(Uint8List list, {String fontFamily}) async { + _dynamicallyLoadedFonts.add(list); + if (fontFamily != null) { + registeredFamilies.add(fontFamily); + } + await ensureFontsLoaded(); + } + Future registerFonts(AssetManager assetManager) async { ByteData byteData; diff --git a/lib/web_ui/lib/src/engine/compositor/initialization.dart b/lib/web_ui/lib/src/engine/compositor/initialization.dart index 6d54273ebabfc..a510bdf29a4a9 100644 --- a/lib/web_ui/lib/src/engine/compositor/initialization.dart +++ b/lib/web_ui/lib/src/engine/compositor/initialization.dart @@ -9,7 +9,7 @@ const bool experimentalUseSkia = bool.fromEnvironment('FLUTTER_WEB_USE_SKIA', defaultValue: false); /// The URL to use when downloading the CanvasKit script and associated wasm. -const String canvasKitBaseUrl = 'https://unpkg.com/canvaskit-wasm@0.11.0/bin/'; +const String canvasKitBaseUrl = 'https://unpkg.com/canvaskit-wasm@0.12.0/bin/'; /// Initialize the Skia backend. /// diff --git a/lib/web_ui/lib/src/engine/compositor/path.dart b/lib/web_ui/lib/src/engine/compositor/path.dart index b8b17190cf2a8..4c3d89d90ea96 100644 --- a/lib/web_ui/lib/src/engine/compositor/path.dart +++ b/lib/web_ui/lib/src/engine/compositor/path.dart @@ -56,7 +56,7 @@ class SkPath implements ui.Path { @override void addOval(ui.Rect oval) { - _skPath.callMethod('addOval', [makeSkRect(oval), true, 0]); + _skPath.callMethod('addOval', [makeSkRect(oval), false, 1]); } @override diff --git a/lib/web_ui/lib/src/engine/compositor/text.dart b/lib/web_ui/lib/src/engine/compositor/text.dart index a9cf6578f5c96..bb3b0a79899ca 100644 --- a/lib/web_ui/lib/src/engine/compositor/text.dart +++ b/lib/web_ui/lib/src/engine/compositor/text.dart @@ -218,7 +218,7 @@ class SkTextStyle implements ui.TextStyle { } List fontFamilies = [fontFamily]; if (fontFamilyFallback != null) { - fontFamilies.addAll(fontFamilies); + fontFamilies.addAll(fontFamilyFallback); } style['fontFamilies'] = fontFamilies; @@ -343,6 +343,10 @@ class SkParagraph implements ui.Paragraph { ui.BoxHeightStyle boxHeightStyle: ui.BoxHeightStyle.tight, ui.BoxWidthStyle boxWidthStyle: ui.BoxWidthStyle.tight, }) { + if (start < 0 || end < 0) { + return const []; + } + js.JsObject heightStyle; switch (boxHeightStyle) { case ui.BoxHeightStyle.tight: diff --git a/lib/web_ui/lib/src/ui/text.dart b/lib/web_ui/lib/src/ui/text.dart index b479db85c51c7..592b163616b0a 100644 --- a/lib/web_ui/lib/src/ui/text.dart +++ b/lib/web_ui/lib/src/ui/text.dart @@ -1587,9 +1587,15 @@ abstract class ParagraphBuilder { /// * `fontFamily`: The family name used to identify the font in text styles. /// If this is not provided, then the family name will be extracted from the font file. Future loadFontFromList(Uint8List list, {String fontFamily}) { - return _fontCollection.loadFontFromList(list, fontFamily: fontFamily).then( - (_) => _sendFontChangeMessage() - ); + if (engine.experimentalUseSkia) { + return engine.skiaFontCollection.loadFontFromList(list, fontFamily: fontFamily).then( + (_) => _sendFontChangeMessage() + ); + } else { + return _fontCollection.loadFontFromList(list, fontFamily: fontFamily).then( + (_) => _sendFontChangeMessage() + ); + } } final ByteData _fontChangeMessage = engine.JSONMessageCodec().encodeMessage({'type': 'fontsChange'}); From 7ebce14f2ab81866b2fd0ff547b97767614a82ac Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Wed, 5 Feb 2020 15:57:29 -0800 Subject: [PATCH 2/4] Work around bug with infinite width layout --- lib/web_ui/lib/src/engine/compositor/painting.dart | 1 + lib/web_ui/lib/src/engine/compositor/text.dart | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/web_ui/lib/src/engine/compositor/painting.dart b/lib/web_ui/lib/src/engine/compositor/painting.dart index 883ab2f9e6c62..b1eb01b460727 100644 --- a/lib/web_ui/lib/src/engine/compositor/painting.dart +++ b/lib/web_ui/lib/src/engine/compositor/painting.dart @@ -30,6 +30,7 @@ class SkPaint extends SkiaObject implements ui.Paint { @override ui.PaintingStyle get style => _style; + @override set style(ui.PaintingStyle value) { _style = value; diff --git a/lib/web_ui/lib/src/engine/compositor/text.dart b/lib/web_ui/lib/src/engine/compositor/text.dart index bb3b0a79899ca..46aee8f25d931 100644 --- a/lib/web_ui/lib/src/engine/compositor/text.dart +++ b/lib/web_ui/lib/src/engine/compositor/text.dart @@ -417,10 +417,20 @@ class SkParagraph implements ui.Paragraph { @override void layout(ui.ParagraphConstraints constraints) { assert(constraints.width != null); + + // Infinite width breaks layout, just use a very large number instead. + // TODO(het): Remove this once https://bugs.chromium.org/p/skia/issues/detail?id=9874 + // is fixed. + double width; + if (constraints.width.isInfinite) { + width = 1000000; + } else { + width = constraints.width; + } // TODO(het): CanvasKit throws an exception when laid out with // a font that wasn't registered. try { - skParagraph.callMethod('layout', [constraints.width]); + skParagraph.callMethod('layout', [width]); } catch (e) { html.window.console.warn('CanvasKit threw an exception while laying ' 'out the paragraph. The font was "$_fontFamily". Exception:\n$e'); From 3d3490285ddcfc253fc2212bb2290470176d3bb2 Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Wed, 5 Feb 2020 16:33:09 -0800 Subject: [PATCH 3/4] Respond to review comments --- lib/web_ui/lib/src/engine/compositor/fonts.dart | 5 +++++ lib/web_ui/lib/src/engine/compositor/initialization.dart | 4 ++++ lib/web_ui/lib/src/engine/compositor/text.dart | 3 ++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/web_ui/lib/src/engine/compositor/fonts.dart b/lib/web_ui/lib/src/engine/compositor/fonts.dart index cfb1dce1e49fa..c98e28e453aa2 100644 --- a/lib/web_ui/lib/src/engine/compositor/fonts.dart +++ b/lib/web_ui/lib/src/engine/compositor/fonts.dart @@ -4,6 +4,11 @@ part of engine; +// This URL was found by using the Google Fonts Developer API to find the URL +// for Roboto. The API warns that this URL is not stable. In order to update +// this, list out all of the fonts and find the URL for the regular +// Roboto font. The API reference is here: +// https://developers.google.com/fonts/docs/developer_api const String _robotoUrl = 'https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Me5WZLCzYlKw.ttf'; diff --git a/lib/web_ui/lib/src/engine/compositor/initialization.dart b/lib/web_ui/lib/src/engine/compositor/initialization.dart index a510bdf29a4a9..a99c164403a0a 100644 --- a/lib/web_ui/lib/src/engine/compositor/initialization.dart +++ b/lib/web_ui/lib/src/engine/compositor/initialization.dart @@ -9,6 +9,10 @@ const bool experimentalUseSkia = bool.fromEnvironment('FLUTTER_WEB_USE_SKIA', defaultValue: false); /// The URL to use when downloading the CanvasKit script and associated wasm. +/// +/// When CanvasKit pushes a new release to NPM, update this URL to reflect the +/// most recent version. For example, if CanvasKit releases version 0.34.0 to +/// NPM, update this URL to `https://unpkg.com/canvaskit-wasm@0.35.0/bin/`. const String canvasKitBaseUrl = 'https://unpkg.com/canvaskit-wasm@0.12.0/bin/'; /// Initialize the Skia backend. diff --git a/lib/web_ui/lib/src/engine/compositor/text.dart b/lib/web_ui/lib/src/engine/compositor/text.dart index 46aee8f25d931..99713e0807622 100644 --- a/lib/web_ui/lib/src/engine/compositor/text.dart +++ b/lib/web_ui/lib/src/engine/compositor/text.dart @@ -422,8 +422,9 @@ class SkParagraph implements ui.Paragraph { // TODO(het): Remove this once https://bugs.chromium.org/p/skia/issues/detail?id=9874 // is fixed. double width; + const double largeFiniteWidth = 1000000; if (constraints.width.isInfinite) { - width = 1000000; + width = largeFiniteWidth; } else { width = constraints.width; } From 2efb5229ca7cc62c59502fb32cf297a3a2f0632d Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Thu, 6 Feb 2020 11:16:02 -0800 Subject: [PATCH 4/4] Fix comment --- lib/web_ui/lib/src/engine/compositor/initialization.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web_ui/lib/src/engine/compositor/initialization.dart b/lib/web_ui/lib/src/engine/compositor/initialization.dart index a99c164403a0a..feed32db9cc47 100644 --- a/lib/web_ui/lib/src/engine/compositor/initialization.dart +++ b/lib/web_ui/lib/src/engine/compositor/initialization.dart @@ -12,7 +12,7 @@ const bool experimentalUseSkia = /// /// When CanvasKit pushes a new release to NPM, update this URL to reflect the /// most recent version. For example, if CanvasKit releases version 0.34.0 to -/// NPM, update this URL to `https://unpkg.com/canvaskit-wasm@0.35.0/bin/`. +/// NPM, update this URL to `https://unpkg.com/canvaskit-wasm@0.34.0/bin/`. const String canvasKitBaseUrl = 'https://unpkg.com/canvaskit-wasm@0.12.0/bin/'; /// Initialize the Skia backend.