diff --git a/lib/web_ui/build.canvaskit.yaml b/lib/web_ui/build.canvaskit.yaml index 3eee9e132401d..8be2596d000a7 100644 --- a/lib/web_ui/build.canvaskit.yaml +++ b/lib/web_ui/build.canvaskit.yaml @@ -10,6 +10,7 @@ targets: compiler: dart2js dart2js_args: - --no-minify + - --disable-inlining - --enable-asserts - --enable-experiment=non-nullable - --no-sound-null-safety diff --git a/lib/web_ui/build.html.yaml b/lib/web_ui/build.html.yaml index b469539d305da..36ea478d17df4 100644 --- a/lib/web_ui/build.html.yaml +++ b/lib/web_ui/build.html.yaml @@ -9,6 +9,7 @@ targets: compiler: dart2js dart2js_args: - --no-minify + - --disable-inlining - --enable-asserts - --enable-experiment=non-nullable - --no-sound-null-safety diff --git a/lib/web_ui/lib/src/engine.dart b/lib/web_ui/lib/src/engine.dart index 857d6acd1b76e..e1ab01db9a45f 100644 --- a/lib/web_ui/lib/src/engine.dart +++ b/lib/web_ui/lib/src/engine.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 library engine; import 'dart:async'; diff --git a/lib/web_ui/lib/src/engine/alarm_clock.dart b/lib/web_ui/lib/src/engine/alarm_clock.dart index 30a3746f4abe2..ee8e6a6be96ec 100644 --- a/lib/web_ui/lib/src/engine/alarm_clock.dart +++ b/lib/web_ui/lib/src/engine/alarm_clock.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 part of engine; /// A function that returns current system time. @@ -24,13 +23,13 @@ class AlarmClock { final TimestampFunction _timestampFunction; /// The underlying timer used to schedule the callback. - Timer _timer; + Timer? _timer; /// Current target time the [callback] is scheduled for. - DateTime _datetime; + DateTime? _datetime; /// The callback called when the alarm goes off. - ui.VoidCallback callback; + late ui.VoidCallback callback; /// The time when the alarm clock will go off. /// @@ -39,8 +38,8 @@ class AlarmClock { /// If the value is updated before an already scheduled timer goes off, the /// previous time will not call the [callback]. Think of the updating this /// value as "changing your mind" about when you want the next timer to fire. - DateTime get datetime => _datetime; - set datetime(DateTime value) { + DateTime? get datetime => _datetime; + set datetime(DateTime? value) { if (value == _datetime) { return; } @@ -72,7 +71,7 @@ class AlarmClock { } else { assert(_datetime != null, 'We can only have a timer if there is a non-null datetime'); - if (_datetime.isAfter(value)) { + if (_datetime!.isAfter(value)) { // This is the case when the value moves the target time to an earlier // point. Because there is no way to reconfigure an existing timer, we // must cancel the old timer and schedule a new one. @@ -89,7 +88,7 @@ class AlarmClock { void _cancelTimer() { if (_timer != null) { - _timer.cancel(); + _timer!.cancel(); _timer = null; } } @@ -100,12 +99,12 @@ class AlarmClock { final DateTime now = _timestampFunction(); // We use the "not before" logic instead of "is after" because we may have // zero difference between now and _datetime. - if (!now.isBefore(_datetime)) { + if (!now.isBefore(_datetime!)) { _timer = null; callback(); } else { // The timer fired before the target date. We need to reschedule. - _timer = Timer(_datetime.difference(now), _timerDidFire); + _timer = Timer(_datetime!.difference(now), _timerDidFire); } } } diff --git a/lib/web_ui/lib/src/engine/assets.dart b/lib/web_ui/lib/src/engine/assets.dart index 50127ab133bc9..60803b0d00560 100644 --- a/lib/web_ui/lib/src/engine/assets.dart +++ b/lib/web_ui/lib/src/engine/assets.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 part of engine; /// This class downloads assets over the network. @@ -17,10 +16,10 @@ class AssetManager { const AssetManager({this.assetsDir = _defaultAssetsDir}); - String get _baseUrl { + String? get _baseUrl { return html.window.document .querySelectorAll('meta') - .whereType() + .whereType() .firstWhere((dynamic e) => e.name == 'assetBase', orElse: () => null) ?.content; } @@ -58,7 +57,7 @@ class AssetManager { final ByteBuffer response = request.response; return response.asByteData(); } on html.ProgressEvent catch (e) { - final html.EventTarget target = e.target; + final html.EventTarget? target = e.target; if (target is html.HttpRequest) { if (target.status == 404 && asset == 'AssetManifest.json') { html.window.console diff --git a/lib/web_ui/lib/src/engine/bitmap_canvas.dart b/lib/web_ui/lib/src/engine/bitmap_canvas.dart index 1e200df3dd16c..b594f39ed665f 100644 --- a/lib/web_ui/lib/src/engine/bitmap_canvas.dart +++ b/lib/web_ui/lib/src/engine/bitmap_canvas.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 part of engine; /// A raw HTML canvas that is directly written to. @@ -13,7 +12,7 @@ class BitmapCanvas extends EngineCanvas { /// Painting outside these bounds will result in cropping. ui.Rect get bounds => _bounds; set bounds(ui.Rect newValue) { - assert(newValue != null); + assert(newValue != null); // ignore: unnecessary_null_comparison _bounds = newValue; final int newCanvasPositionX = _bounds.left.floor() - kPaddingPixels; final int newCanvasPositionY = _bounds.top.floor() - kPaddingPixels; @@ -26,7 +25,7 @@ class BitmapCanvas extends EngineCanvas { } ui.Rect _bounds; - CrossFrameCache _elementCache; + CrossFrameCache? _elementCache; /// The amount of padding to add around the edges of this canvas to /// ensure that anti-aliased arcs are not clipped. @@ -42,7 +41,7 @@ class BitmapCanvas extends EngineCanvas { /// The last paragraph style is cached to optimize the case where the style /// hasn't changed. - ParagraphGeometricStyle _cachedLastStyle; + ParagraphGeometricStyle? _cachedLastStyle; /// List of extra sibling elements created for paragraphs and clipping. final List _children = []; @@ -74,7 +73,7 @@ class BitmapCanvas extends EngineCanvas { final double _devicePixelRatio = EngineWindow.browserDevicePixelRatio; // Compensation for [_initializeViewport] snapping canvas position to 1 pixel. - int _canvasPositionX, _canvasPositionY; + int? _canvasPositionX, _canvasPositionY; // Indicates the instructions following drawImage or drawParagraph that // a child element was created to paint. @@ -101,7 +100,7 @@ class BitmapCanvas extends EngineCanvas { /// as the [Rect.size] of the bounds fully fit within the size used to /// initialize this canvas. BitmapCanvas(this._bounds) - : assert(_bounds != null), + : assert(_bounds != null), // ignore: unnecessary_null_comparison _widthInBitmapPixels = _widthToPhysical(_bounds.width), _heightInBitmapPixels = _heightToPhysical(_bounds.height), _canvasPool = _CanvasPool(_widthToPhysical(_bounds.width), @@ -113,7 +112,7 @@ class BitmapCanvas extends EngineCanvas { _canvasPositionX = _bounds.left.floor() - kPaddingPixels; _canvasPositionY = _bounds.top.floor() - kPaddingPixels; _updateRootElementTransform(); - _canvasPool.allocateCanvas(rootElement); + _canvasPool.allocateCanvas(rootElement as html.HtmlElement); _setupInitialTransform(); } @@ -138,9 +137,9 @@ class BitmapCanvas extends EngineCanvas { void _setupInitialTransform() { final double canvasPositionCorrectionX = _bounds.left - BitmapCanvas.kPaddingPixels - - _canvasPositionX.toDouble(); + _canvasPositionX!.toDouble(); final double canvasPositionCorrectionY = - _bounds.top - BitmapCanvas.kPaddingPixels - _canvasPositionY.toDouble(); + _bounds.top - BitmapCanvas.kPaddingPixels - _canvasPositionY!.toDouble(); // This compensates for the translate on the `rootElement`. _canvasPool.initialTransform = ui.Offset( -_bounds.left + canvasPositionCorrectionX + BitmapCanvas.kPaddingPixels, @@ -162,7 +161,7 @@ class BitmapCanvas extends EngineCanvas { // Used by picture to assess if canvas is large enough to reuse as is. bool doesFitBounds(ui.Rect newBounds) { - assert(newBounds != null); + assert(newBounds != null); // ignore: unnecessary_null_comparison return _widthInBitmapPixels >= _widthToPhysical(newBounds.width) && _heightInBitmapPixels >= _heightToPhysical(newBounds.height); } @@ -367,7 +366,7 @@ class BitmapCanvas extends EngineCanvas { html.ImageElement _reuseOrCreateImage(HtmlImage htmlImage) { final String cacheKey = htmlImage.imgElement.src; if (_elementCache != null) { - html.ImageElement imageElement = _elementCache.reuse(cacheKey); + html.ImageElement? imageElement = _elementCache!.reuse(cacheKey) as html.ImageElement?; if (imageElement != null) { return imageElement; } @@ -375,7 +374,7 @@ class BitmapCanvas extends EngineCanvas { // Can't reuse, create new instance. html.ImageElement newImageElement = htmlImage.cloneImageElement(); if (_elementCache != null) { - _elementCache.cache(cacheKey, newImageElement, _onEvictElement); + _elementCache!.cache(cacheKey, newImageElement, _onEvictElement); } return newImageElement; } @@ -386,10 +385,10 @@ class BitmapCanvas extends EngineCanvas { html.HtmlElement _drawImage( ui.Image image, ui.Offset p, SurfacePaintData paint) { - final HtmlImage htmlImage = image; - final ui.BlendMode blendMode = paint.blendMode; - final EngineColorFilter colorFilter = paint.colorFilter as EngineColorFilter; - final ui.BlendMode colorFilterBlendMode = colorFilter?._blendMode; + final HtmlImage htmlImage = image as HtmlImage; + final ui.BlendMode? blendMode = paint.blendMode; + final EngineColorFilter? colorFilter = paint.colorFilter as EngineColorFilter?; + final ui.BlendMode? colorFilterBlendMode = colorFilter?._blendMode; html.HtmlElement imgElement; if (colorFilterBlendMode == null) { // No Blending, create an image by cloning original loaded image. @@ -410,22 +409,22 @@ class BitmapCanvas extends EngineCanvas { case ui.BlendMode.luminosity: case ui.BlendMode.xor: imgElement = _createImageElementWithSvgFilter(image, - colorFilter._color, colorFilterBlendMode, paint); + colorFilter!._color, colorFilterBlendMode, paint); break; default: imgElement = _createBackgroundImageWithBlend(image, - colorFilter._color, colorFilterBlendMode, paint); + colorFilter!._color, colorFilterBlendMode, paint); break; } } - imgElement.style.mixBlendMode = _stringForBlendMode(blendMode); + imgElement.style.mixBlendMode = _stringForBlendMode(blendMode) ?? ''; if (_canvasPool.isClipped) { // Reset width/height since they may have been previously set. imgElement.style ..removeProperty('width') ..removeProperty('height'); final List clipElements = _clipContent( - _canvasPool._clipStack, imgElement, p, _canvasPool.currentTransform); + _canvasPool._clipStack!, imgElement, p, _canvasPool.currentTransform); for (html.Element clipElement in clipElements) { rootElement.append(clipElement); _children.add(clipElement); @@ -493,7 +492,7 @@ class BitmapCanvas extends EngineCanvas { targetWidth *= image.width / src.width; targetHeight *= image.height / src.height; } - _applyTargetSize(imgElement, targetWidth, targetHeight); + _applyTargetSize(imgElement as html.HtmlElement, targetWidth, targetHeight); if (requiresClipping) { restore(); } @@ -533,7 +532,7 @@ class BitmapCanvas extends EngineCanvas { // For src,srcOver it only sets background-color attribute. // For dst,dstIn , it only sets source not background color. html.HtmlElement _createBackgroundImageWithBlend(HtmlImage image, - ui.Color filterColor, ui.BlendMode colorFilterBlendMode, + ui.Color? filterColor, ui.BlendMode colorFilterBlendMode, SurfacePaintData paint) { // When blending with color we can't use an image element. // Instead use a div element with background image, color and @@ -561,7 +560,7 @@ class BitmapCanvas extends EngineCanvas { style ..position = 'absolute' ..backgroundImage = "url('${image.imgElement.src}')" - ..backgroundBlendMode = _stringForBlendMode(colorFilterBlendMode) + ..backgroundBlendMode = _stringForBlendMode(colorFilterBlendMode) ?? '' ..backgroundColor = colorToCssString(filterColor); break; } @@ -570,10 +569,10 @@ class BitmapCanvas extends EngineCanvas { // Creates an image element and an svg filter to apply on the element. html.HtmlElement _createImageElementWithSvgFilter(HtmlImage image, - ui.Color filterColor, ui.BlendMode colorFilterBlendMode, + ui.Color? filterColor, ui.BlendMode colorFilterBlendMode, SurfacePaintData paint) { // For srcIn blendMode, we use an svg filter to apply to image element. - String svgFilter; + String? svgFilter; switch (colorFilterBlendMode) { case ui.BlendMode.srcIn: case ui.BlendMode.srcATop: @@ -591,7 +590,7 @@ class BitmapCanvas extends EngineCanvas { break; case ui.BlendMode.modulate: // Porter duff source * destination but preserves alpha. - svgFilter = _modulateColorFilterToSvg(filterColor); + svgFilter = _modulateColorFilterToSvg(filterColor!); break; case ui.BlendMode.overlay: // Since overlay is the same as hard-light by swapping layers, @@ -655,11 +654,11 @@ class BitmapCanvas extends EngineCanvas { double x, double y, ) { - html.CanvasRenderingContext2D ctx = _canvasPool.context; + html.CanvasRenderingContext2D? ctx = _canvasPool.context; x += line.left; - final double letterSpacing = style.letterSpacing; + final double? letterSpacing = style.letterSpacing; if (letterSpacing == null || letterSpacing == 0.0) { - ctx.fillText(line.displayText, x, y); + ctx!.fillText(line.displayText!, x, y); } else { // When letter-spacing is set, we go through a more expensive code path // that renders each character separately with the correct spacing @@ -671,10 +670,10 @@ class BitmapCanvas extends EngineCanvas { // would put 5px before each letter and 5px after it, but on the web, we // put no spacing before the letter and 10px after it. This is how the DOM // does it. - final int len = line.displayText.length; + final int len = line.displayText!.length; for (int i = 0; i < len; i++) { - final String char = line.displayText[i]; - ctx.fillText(char, x, y); + final String char = line.displayText![i]; + ctx!.fillText(char, x, y); x += letterSpacing + ctx.measureText(char).width; } } @@ -688,9 +687,9 @@ class BitmapCanvas extends EngineCanvas { if (paragraph._drawOnCanvas && _childOverdraw == false) { // !Do not move this assignment above this if clause since, accessing // context will generate extra tags. - final List lines = paragraph._measurementResult.lines; + final List lines = paragraph._measurementResult!.lines!; - final SurfacePaintData backgroundPaint = paragraph._background?.paintData; + final SurfacePaintData? backgroundPaint = paragraph._background?.paintData; if (backgroundPaint != null) { final ui.Rect rect = ui.Rect.fromLTWH( offset.dx, offset.dy, paragraph.width, paragraph.height); @@ -702,7 +701,7 @@ class BitmapCanvas extends EngineCanvas { ctx.font = style.cssFontString; _cachedLastStyle = style; } - _setUpPaint(paragraph._paint.paintData); + _setUpPaint(paragraph._paint!.paintData); double y = offset.dy + paragraph.alphabeticBaseline; final int len = lines.length; for (int i = 0; i < len; i++) { @@ -718,8 +717,8 @@ class BitmapCanvas extends EngineCanvas { _drawParagraphElement(paragraph, offset); if (_canvasPool.isClipped) { final List clipElements = _clipContent( - _canvasPool._clipStack, - paragraphElement, + _canvasPool._clipStack!, + paragraphElement as html.HtmlElement, offset, _canvasPool.currentTransform); for (html.Element clipElement in clipElements) { @@ -743,8 +742,8 @@ class BitmapCanvas extends EngineCanvas { /// Paints the [picture] into this canvas. void drawPicture(ui.Picture picture) { - final EnginePicture enginePicture = picture; - enginePicture.recordingCanvas.apply(this, bounds); + final EnginePicture enginePicture = picture as EnginePicture; + enginePicture.recordingCanvas!.apply(this, bounds); } /// Draws vertices on a gl context. @@ -768,9 +767,9 @@ class BitmapCanvas extends EngineCanvas { // as well. assert(paint.shader == null, 'Linear/Radial/SweepGradient and ImageShader not supported yet'); - final Int32List colors = vertices._colors; + final Int32List? colors = vertices._colors; final ui.VertexMode mode = vertices._mode; - html.CanvasRenderingContext2D ctx = _canvasPool.context; + html.CanvasRenderingContext2D? ctx = _canvasPool.context; if (colors == null) { final Float32List positions = mode == ui.VertexMode.triangles ? vertices._positions @@ -781,11 +780,11 @@ class BitmapCanvas extends EngineCanvas { _canvasPool.contextHandle ..fillStyle = null ..strokeStyle = colorToCssString(color); - _glRenderer.drawHairline(ctx, positions); + _glRenderer!.drawHairline(ctx, positions); restore(); return; } - _glRenderer.drawVertices(ctx, _widthInBitmapPixels, _heightInBitmapPixels, + _glRenderer!.drawVertices(ctx, _widthInBitmapPixels, _heightInBitmapPixels, _canvasPool.currentTransform, vertices, blendMode, paint); } @@ -809,7 +808,7 @@ class BitmapCanvas extends EngineCanvas { _drawPointsPaint.maskFilter = paint.maskFilter; _setUpPaint(_drawPointsPaint); - _canvasPool.drawPoints(pointMode, points, paint.strokeWidth / 2.0); + _canvasPool.drawPoints(pointMode, points, paint.strokeWidth! / 2.0); _tearDownPaint(); } @@ -821,7 +820,7 @@ class BitmapCanvas extends EngineCanvas { } } -String _stringForBlendMode(ui.BlendMode blendMode) { +String? _stringForBlendMode(ui.BlendMode? blendMode) { if (blendMode == null) { return null; } @@ -887,7 +886,7 @@ String _stringForBlendMode(ui.BlendMode blendMode) { } } -String _stringForStrokeCap(ui.StrokeCap strokeCap) { +String? _stringForStrokeCap(ui.StrokeCap? strokeCap) { if (strokeCap == null) { return null; } @@ -903,7 +902,7 @@ String _stringForStrokeCap(ui.StrokeCap strokeCap) { } String _stringForStrokeJoin(ui.StrokeJoin strokeJoin) { - assert(strokeJoin != null); + assert(strokeJoin != null); // ignore: unnecessary_null_comparison switch (strokeJoin) { case ui.StrokeJoin.round: return 'round'; @@ -924,7 +923,7 @@ String _stringForStrokeJoin(ui.StrokeJoin strokeJoin) { /// with a list of svg elements that provide clip-paths. List _clipContent(List<_SaveClipEntry> clipStack, html.HtmlElement content, ui.Offset offset, Matrix4 currentTransform) { - html.Element root, curElement; + html.Element? root, curElement; final List clipDefs = []; final int len = clipStack.length; for (int clipIndex = 0; clipIndex < len; clipIndex++) { @@ -935,10 +934,10 @@ List _clipContent(List<_SaveClipEntry> clipStack, if (root == null) { root = newElement; } else { - domRenderer.append(curElement, newElement); + domRenderer.append(curElement!, newElement); } curElement = newElement; - final ui.Rect rect = entry.rect; + final ui.Rect? rect = entry.rect; Matrix4 newClipTransform = entry.currentTransform; if (rect != null) { final double clipOffsetX = rect.left; @@ -951,7 +950,7 @@ List _clipContent(List<_SaveClipEntry> clipStack, ..height = '${rect.bottom - clipOffsetY}px'; setElementTransform(curElement, newClipTransform.storage); } else if (entry.rrect != null) { - final ui.RRect roundRect = entry.rrect; + final ui.RRect roundRect = entry.rrect!; final String borderRadius = '${roundRect.tlRadiusX}px ${roundRect.trRadiusX}px ' '${roundRect.brRadiusX}px ${roundRect.blRadiusX}px'; @@ -967,7 +966,7 @@ List _clipContent(List<_SaveClipEntry> clipStack, setElementTransform(curElement, newClipTransform.storage); } else if (entry.path != null) { curElement.style.transform = matrix4ToCssTransform(newClipTransform); - String svgClipPath = createSvgClipDef(curElement, entry.path); + String svgClipPath = createSvgClipDef(curElement as html.HtmlElement, entry.path!); final html.Element clipElement = html.Element.html(svgClipPath, treeSanitizer: _NullTreeSanitizer()); clipDefs.add(clipElement); @@ -986,8 +985,8 @@ List _clipContent(List<_SaveClipEntry> clipStack, curElement = reverseTransformDiv; } - root.style.position = 'absolute'; - domRenderer.append(curElement, content); + root!.style.position = 'absolute'; + domRenderer.append(curElement!, content); setElementTransform( content, transformWithOffset(currentTransform, offset).storage, @@ -998,7 +997,7 @@ List _clipContent(List<_SaveClipEntry> clipStack, /// Converts a [maskFilter] to the value to be used on a ``. /// /// Only supported in non-WebKit browsers. -String _maskFilterToCanvasFilter(ui.MaskFilter maskFilter) { +String _maskFilterToCanvasFilter(ui.MaskFilter? maskFilter) { assert( browserEngine != BrowserEngine.webkit, 'WebKit (Safari) does not support `filter` canvas property.', @@ -1027,7 +1026,7 @@ int _filterIdCounter = 0; // G' = g1*R + g2*G + g3*B + g4*A + g5 // B' = b1*R + b2*G + b3*B + b4*A + b5 // A' = a1*R + a2*G + a3*B + a4*A + a5 -String _srcInColorFilterToSvg(ui.Color color) { +String _srcInColorFilterToSvg(ui.Color? color) { _filterIdCounter += 1; return '' ''; } -String _srcOutColorFilterToSvg(ui.Color color) { +String _srcOutColorFilterToSvg(ui.Color? color) { _filterIdCounter += 1; return '' ''; } -String _xorColorFilterToSvg(ui.Color color) { +String _xorColorFilterToSvg(ui.Color? color) { _filterIdCounter += 1; return '' '' '' diff --git a/lib/web_ui/lib/src/engine/browser_detection.dart b/lib/web_ui/lib/src/engine/browser_detection.dart index 5c9b990670e07..20fdb7f0fb010 100644 --- a/lib/web_ui/lib/src/engine/browser_detection.dart +++ b/lib/web_ui/lib/src/engine/browser_detection.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// The HTML engine used by the current browser. @@ -28,7 +28,7 @@ enum BrowserEngine { } /// Lazily initialized current browser engine. -BrowserEngine _browserEngine; +late final BrowserEngine _browserEngine = _detectBrowserEngine(); /// Override the value of [browserEngine]. /// @@ -36,16 +36,13 @@ BrowserEngine _browserEngine; /// app is running on. /// /// This is intended to be used for testing and debugging only. -BrowserEngine debugBrowserEngineOverride; +BrowserEngine? debugBrowserEngineOverride; /// Returns the [BrowserEngine] used by the current browser. /// /// This is used to implement browser-specific behavior. BrowserEngine get browserEngine { - if (debugBrowserEngineOverride != null) { - return debugBrowserEngineOverride; - } - return _browserEngine ??= _detectBrowserEngine(); + return debugBrowserEngineOverride ?? _browserEngine; } BrowserEngine _detectBrowserEngine() { @@ -99,17 +96,14 @@ enum OperatingSystem { } /// Lazily initialized current operating system. -OperatingSystem _operatingSystem; +late final OperatingSystem _operatingSystem = _detectOperatingSystem(); /// Returns the [OperatingSystem] the current browsers works on. /// /// This is used to implement operating system specific behavior such as /// soft keyboards. OperatingSystem get operatingSystem { - if (debugOperatingSystemOverride != null) { - return debugOperatingSystemOverride; - } - return _operatingSystem ??= _detectOperatingSystem(); + return debugOperatingSystemOverride ?? _operatingSystem; } /// Override the value of [operatingSystem]. @@ -118,7 +112,7 @@ OperatingSystem get operatingSystem { /// app is running on. /// /// This is intended to be used for testing and debugging only. -OperatingSystem debugOperatingSystemOverride; +OperatingSystem? debugOperatingSystemOverride; OperatingSystem _detectOperatingSystem() { final String platform = html.window.navigator.platform; diff --git a/lib/web_ui/lib/src/engine/browser_location.dart b/lib/web_ui/lib/src/engine/browser_location.dart index 854bf9ec6f5e0..2bbe9ec47c8d0 100644 --- a/lib/web_ui/lib/src/engine/browser_location.dart +++ b/lib/web_ui/lib/src/engine/browser_location.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; // TODO(mdebbar): add other strategies. @@ -115,7 +115,7 @@ class HashLocationStrategy extends LocationStrategy { /// `history.back` transition. Future _waitForPopState() { final Completer completer = Completer(); - ui.VoidCallback unsubscribe; + late ui.VoidCallback unsubscribe; unsubscribe = onPopState((_) { unsubscribe(); completer.complete(); @@ -141,7 +141,7 @@ abstract class PlatformLocation { String get pathname; String get search; - String get hash; + String? get hash; void pushState(dynamic state, String title, String url); void replaceState(dynamic state, String title, String url); diff --git a/lib/web_ui/lib/src/engine/canvas_pool.dart b/lib/web_ui/lib/src/engine/canvas_pool.dart index 0be145972fdb7..dee43849534d1 100644 --- a/lib/web_ui/lib/src/engine/canvas_pool.dart +++ b/lib/web_ui/lib/src/engine/canvas_pool.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Allocates and caches 0 or more canvas(s) for [BitmapCanvas]. @@ -21,17 +21,17 @@ part of engine; /// can be reused, [_CanvasPool] will move canvas(s) from pool to reusablePool /// to prevent reallocation. class _CanvasPool extends _SaveStackTracking { - html.CanvasRenderingContext2D _context; - ContextStateHandle _contextHandle; + html.CanvasRenderingContext2D? _context; + ContextStateHandle? _contextHandle; final int _widthInBitmapPixels, _heightInBitmapPixels; // List of canvases that have been allocated and used in this paint cycle. - List _activeCanvasList; + List? _activeCanvasList; // List of canvases available to reuse from prior paint cycle. - List _reusablePool; + List? _reusablePool; // Current canvas element or null if marked for lazy allocation. - html.CanvasElement _canvas; + html.CanvasElement? _canvas; - html.HtmlElement _rootElement; + html.HtmlElement? _rootElement; int _saveContextCount = 0; // Number of elements that have been added to flt-canvas. int _activeElementCount = 0; @@ -39,12 +39,14 @@ class _CanvasPool extends _SaveStackTracking { _CanvasPool(this._widthInBitmapPixels, this._heightInBitmapPixels); html.CanvasRenderingContext2D get context { - if (_canvas == null) { + html.CanvasRenderingContext2D? ctx = _context; + if (ctx == null) { _createCanvas(); + ctx = _context!; assert(_context != null); assert(_canvas != null); } - return _context; + return ctx; } ContextStateHandle get contextHandle { @@ -53,7 +55,7 @@ class _CanvasPool extends _SaveStackTracking { assert(_context != null); assert(_canvas != null); } - return _contextHandle; + return _contextHandle!; } // Prevents active canvas to be used for rendering and prepares a new @@ -67,9 +69,9 @@ class _CanvasPool extends _SaveStackTracking { // reset into pool. if (_canvas != null) { _restoreContextSave(); - _contextHandle.reset(); + _contextHandle!.reset(); _activeCanvasList ??= []; - _activeCanvasList.add(_canvas); + _activeCanvasList!.add(_canvas!); _canvas = null; _context = null; _contextHandle = null; @@ -84,8 +86,9 @@ class _CanvasPool extends _SaveStackTracking { void _createCanvas() { bool requiresClearRect = false; bool reused = false; - if (_reusablePool != null && _reusablePool.isNotEmpty) { - _canvas = _reusablePool.removeAt(0); + html.CanvasElement canvas; + if (_reusablePool != null && _reusablePool!.isNotEmpty) { + canvas = _canvas = _reusablePool!.removeAt(0); requiresClearRect = true; reused = true; } else { @@ -99,19 +102,26 @@ class _CanvasPool extends _SaveStackTracking { _widthInBitmapPixels / EngineWindow.browserDevicePixelRatio; final double cssHeight = _heightInBitmapPixels / EngineWindow.browserDevicePixelRatio; - _canvas = html.CanvasElement( + canvas = html.CanvasElement( width: _widthInBitmapPixels, height: _heightInBitmapPixels, ); + _canvas = canvas; + + // Why is this null check here, even though we just allocated a canvas element above? + // + // On iOS Safari, if you alloate too many canvases, the browser will stop allocating them + // and return null instead. If that happens, we evict canvases from the cache, giving the + // browser more memory to allocate a new canvas. if (_canvas == null) { // Evict BitmapCanvas(s) and retry. _reduceCanvasMemoryUsage(); - _canvas = html.CanvasElement( + canvas = html.CanvasElement( width: _widthInBitmapPixels, height: _heightInBitmapPixels, ); } - _canvas.style + canvas.style ..position = 'absolute' ..width = '${cssWidth}px' ..height = '${cssHeight}px'; @@ -120,22 +130,22 @@ class _CanvasPool extends _SaveStackTracking { // Before appending canvas, check if canvas is already on rootElement. This // optimization prevents DOM .append call when a PersistentSurface is // reused. Reading lastChild is faster than append call. - if (_rootElement.lastChild != _canvas) { - _rootElement.append(_canvas); + if (_rootElement!.lastChild != canvas) { + _rootElement!.append(canvas); } if (_activeElementCount == 0) { - _canvas.style.zIndex = '-1'; + canvas.style.zIndex = '-1'; } else if (reused) { // If a canvas is the first element we set z-index = -1 to workaround // blink compositing bug. To make sure this does not leak when reused // reset z-index. - _canvas.style.removeProperty('z-index'); + canvas.style.removeProperty('z-index'); } ++_activeElementCount; - _context = _canvas.context2D; - _contextHandle = ContextStateHandle(this, _context); + final html.CanvasRenderingContext2D context = _context = canvas.context2D; + _contextHandle = ContextStateHandle(this, context); _initializeViewport(requiresClearRect); _replayClipStack(); } @@ -146,7 +156,7 @@ class _CanvasPool extends _SaveStackTracking { if (_canvas != null) { // Restore to the state where we have only applied the scaling. - html.CanvasRenderingContext2D ctx = _context; + html.CanvasRenderingContext2D? ctx = _context; if (ctx != null) { try { ctx.font = ''; @@ -168,8 +178,8 @@ class _CanvasPool extends _SaveStackTracking { } int _replaySingleSaveEntry(int clipDepth, Matrix4 prevTransform, - Matrix4 transform, List<_SaveClipEntry> clipStack) { - final html.CanvasRenderingContext2D ctx = _context; + Matrix4 transform, List<_SaveClipEntry>? clipStack) { + final html.CanvasRenderingContext2D ctx = context; if (clipStack != null) { for (int clipCount = clipStack.length; clipDepth < clipCount; @@ -196,11 +206,11 @@ class _CanvasPool extends _SaveStackTracking { prevTransform = clipTimeTransform; } if (clipEntry.rect != null) { - _clipRect(ctx, clipEntry.rect); + _clipRect(ctx, clipEntry.rect!); } else if (clipEntry.rrect != null) { - _clipRRect(ctx, clipEntry.rrect); + _clipRRect(ctx, clipEntry.rrect!); } else if (clipEntry.path != null) { - _runPath(ctx, clipEntry.path); + _runPath(ctx, clipEntry.path as SurfacePath); ctx.clip(); } } @@ -223,7 +233,7 @@ class _CanvasPool extends _SaveStackTracking { void _replayClipStack() { // Replay save/clip stack on this canvas now. - html.CanvasRenderingContext2D ctx = _context; + html.CanvasRenderingContext2D ctx = context; int clipDepth = 0; Matrix4 prevTransform = Matrix4.identity(); for (int saveStackIndex = 0, len = _saveStack.length; @@ -244,9 +254,9 @@ class _CanvasPool extends _SaveStackTracking { void reuse() { if (_canvas != null) { _restoreContextSave(); - _contextHandle.reset(); + _contextHandle!.reset(); _activeCanvasList ??= []; - _activeCanvasList.add(_canvas); + _activeCanvasList!.add(_canvas!); _context = null; _contextHandle = null; } @@ -260,7 +270,7 @@ class _CanvasPool extends _SaveStackTracking { void endOfPaint() { if (_reusablePool != null) { - for (html.CanvasElement e in _reusablePool) { + for (html.CanvasElement e in _reusablePool!) { if (browserEngine == BrowserEngine.webkit) { e.width = e.height = 0; } @@ -273,7 +283,7 @@ class _CanvasPool extends _SaveStackTracking { void _restoreContextSave() { while (_saveContextCount != 0) { - _context.restore(); + _context!.restore(); --_saveContextCount; } } @@ -302,15 +312,16 @@ class _CanvasPool extends _SaveStackTracking { } void resetTransform() { - if (_canvas != null) { - _canvas.style.transformOrigin = ''; - _canvas.style.transform = ''; + final html.CanvasElement? canvas = _canvas; + if (canvas != null) { + canvas.style.transformOrigin = ''; + canvas.style.transform = ''; } } // Returns a data URI containing a representation of the image in this // canvas. - String toDataUrl() => _canvas.toDataUrl(); + String toDataUrl() => _canvas!.toDataUrl(); @override void save() { @@ -423,7 +434,7 @@ class _CanvasPool extends _SaveStackTracking { void _clipRRect(html.CanvasRenderingContext2D ctx, ui.RRect rrect) { final ui.Path path = ui.Path()..addRRect(rrect); - _runPath(ctx, path); + _runPath(ctx, path as SurfacePath); ctx.clip(); } @@ -431,7 +442,7 @@ class _CanvasPool extends _SaveStackTracking { super.clipPath(path); if (_canvas != null) { html.CanvasRenderingContext2D ctx = context; - _runPath(ctx, path); + _runPath(ctx, path as SurfacePath); ctx.clip(); } } @@ -511,7 +522,7 @@ class _CanvasPool extends _SaveStackTracking { final PathCommand command = commands[c]; switch (command.type) { case PathCommandTypes.bezierCurveTo: - final BezierCurveTo curve = command; + final BezierCurveTo curve = command as BezierCurveTo; ctx.bezierCurveTo( curve.x1, curve.y1, curve.x2, curve.y2, curve.x3, curve.y3); break; @@ -519,7 +530,7 @@ class _CanvasPool extends _SaveStackTracking { ctx.closePath(); break; case PathCommandTypes.ellipse: - final Ellipse ellipse = command; + final Ellipse ellipse = command as Ellipse; if (c == 0) { // Ellipses that start a new path need to set start point, // otherwise it incorrectly uses last point. @@ -536,25 +547,25 @@ class _CanvasPool extends _SaveStackTracking { ellipse.anticlockwise); break; case PathCommandTypes.lineTo: - final LineTo lineTo = command; + final LineTo lineTo = command as LineTo; ctx.lineTo(lineTo.x, lineTo.y); break; case PathCommandTypes.moveTo: - final MoveTo moveTo = command; + final MoveTo moveTo = command as MoveTo; ctx.moveTo(moveTo.x, moveTo.y); break; case PathCommandTypes.rRect: - final RRectCommand rrectCommand = command; + final RRectCommand rrectCommand = command as RRectCommand; _RRectToCanvasRenderer(ctx) .render(rrectCommand.rrect, startNewPath: false); break; case PathCommandTypes.rect: - final RectCommand rectCommand = command; + final RectCommand rectCommand = command as RectCommand; ctx.rect(rectCommand.x, rectCommand.y, rectCommand.width, rectCommand.height); break; case PathCommandTypes.quadraticCurveTo: - final QuadraticCurveTo quadraticCurveTo = command; + final QuadraticCurveTo quadraticCurveTo = command as QuadraticCurveTo; ctx.quadraticCurveTo(quadraticCurveTo.x1, quadraticCurveTo.y1, quadraticCurveTo.x2, quadraticCurveTo.y2); break; @@ -565,45 +576,45 @@ class _CanvasPool extends _SaveStackTracking { } } - void drawRect(ui.Rect rect, ui.PaintingStyle style) { + void drawRect(ui.Rect rect, ui.PaintingStyle? style) { context.beginPath(); context.rect(rect.left, rect.top, rect.width, rect.height); contextHandle.paint(style); } - void drawRRect(ui.RRect roundRect, ui.PaintingStyle style) { + void drawRRect(ui.RRect roundRect, ui.PaintingStyle? style) { _RRectToCanvasRenderer(context).render(roundRect); contextHandle.paint(style); } - void drawDRRect(ui.RRect outer, ui.RRect inner, ui.PaintingStyle style) { + void drawDRRect(ui.RRect outer, ui.RRect inner, ui.PaintingStyle? style) { _RRectRenderer renderer = _RRectToCanvasRenderer(context); renderer.render(outer); renderer.render(inner, startNewPath: false, reverse: true); contextHandle.paint(style); } - void drawOval(ui.Rect rect, ui.PaintingStyle style) { + void drawOval(ui.Rect rect, ui.PaintingStyle? style) { context.beginPath(); DomRenderer.ellipse(context, rect.center.dx, rect.center.dy, rect.width / 2, rect.height / 2, 0, 0, 2.0 * math.pi, false); contextHandle.paint(style); } - void drawCircle(ui.Offset c, double radius, ui.PaintingStyle style) { + void drawCircle(ui.Offset c, double radius, ui.PaintingStyle? style) { context.beginPath(); DomRenderer.ellipse(context, c.dx, c.dy, radius, radius, 0, 0, 2.0 * math.pi, false); contextHandle.paint(style); } - void drawPath(ui.Path path, ui.PaintingStyle style) { - _runPath(context, path); + void drawPath(ui.Path path, ui.PaintingStyle? style) { + _runPath(context, path as SurfacePath); contextHandle.paintPath(style, path.fillType); } void drawShadow(ui.Path path, ui.Color color, double elevation, bool transparentOccluder) { - final SurfaceShadowData shadow = computeShadow(path.getBounds(), elevation); + final SurfaceShadowData? shadow = computeShadow(path.getBounds(), elevation); if (shadow != null) { // On April 2020 Web canvas 2D did not support shadow color alpha. So // instead we apply alpha separately using globalAlpha, then paint a @@ -654,7 +665,7 @@ class _CanvasPool extends _SaveStackTracking { context.shadowOffsetX = shadow.offset.dx; context.shadowOffsetY = shadow.offset.dy; } - _runPath(context, path); + _runPath(context, path as SurfacePath); context.fill(); // This also resets globalAlpha and shadow attributes. See: @@ -671,14 +682,14 @@ class _CanvasPool extends _SaveStackTracking { // into thinking that this canvas has a zero size so it doesn't count it // towards the threshold. if (browserEngine == BrowserEngine.webkit && _canvas != null) { - _canvas.width = _canvas.height = 0; + _canvas!.width = _canvas!.height = 0; } _clearActiveCanvasList(); } void _clearActiveCanvasList() { if (_activeCanvasList != null) { - for (html.CanvasElement c in _activeCanvasList) { + for (html.CanvasElement c in _activeCanvasList!) { if (browserEngine == BrowserEngine.webkit) { c.width = c.height = 0; } @@ -699,16 +710,16 @@ class ContextStateHandle { final _CanvasPool _canvasPool; ContextStateHandle(this._canvasPool, this.context); - ui.BlendMode _currentBlendMode = ui.BlendMode.srcOver; - ui.StrokeCap _currentStrokeCap = ui.StrokeCap.butt; - ui.StrokeJoin _currentStrokeJoin = ui.StrokeJoin.miter; + ui.BlendMode? _currentBlendMode = ui.BlendMode.srcOver; + ui.StrokeCap? _currentStrokeCap = ui.StrokeCap.butt; + ui.StrokeJoin? _currentStrokeJoin = ui.StrokeJoin.miter; // Fill style and stroke style are Object since they can have a String or // shader object such as a gradient. - Object _currentFillStyle; - Object _currentStrokeStyle; + Object? _currentFillStyle; + Object? _currentStrokeStyle; double _currentLineWidth = 1.0; - set blendMode(ui.BlendMode blendMode) { + set blendMode(ui.BlendMode? blendMode) { if (blendMode != _currentBlendMode) { _currentBlendMode = blendMode; context.globalCompositeOperation = @@ -716,11 +727,11 @@ class ContextStateHandle { } } - set strokeCap(ui.StrokeCap strokeCap) { + set strokeCap(ui.StrokeCap? strokeCap) { strokeCap ??= ui.StrokeCap.butt; if (strokeCap != _currentStrokeCap) { _currentStrokeCap = strokeCap; - context.lineCap = _stringForStrokeCap(strokeCap); + context.lineCap = _stringForStrokeCap(strokeCap)!; } } @@ -731,7 +742,7 @@ class ContextStateHandle { } } - set strokeJoin(ui.StrokeJoin strokeJoin) { + set strokeJoin(ui.StrokeJoin? strokeJoin) { strokeJoin ??= ui.StrokeJoin.miter; if (strokeJoin != _currentStrokeJoin) { _currentStrokeJoin = strokeJoin; @@ -739,22 +750,22 @@ class ContextStateHandle { } } - set fillStyle(Object colorOrGradient) { + set fillStyle(Object? colorOrGradient) { if (!identical(colorOrGradient, _currentFillStyle)) { _currentFillStyle = colorOrGradient; context.fillStyle = colorOrGradient; } } - set strokeStyle(Object colorOrGradient) { + set strokeStyle(Object? colorOrGradient) { if (!identical(colorOrGradient, _currentStrokeStyle)) { _currentStrokeStyle = colorOrGradient; context.strokeStyle = colorOrGradient; } } - ui.MaskFilter _currentFilter; - SurfacePaintData _lastUsedPaint; + ui.MaskFilter? _currentFilter; + SurfacePaintData? _lastUsedPaint; /// The painting state. /// @@ -785,13 +796,13 @@ class ContextStateHandle { strokeJoin = paint.strokeJoin; if (paint.shader != null) { - final EngineGradient engineShader = paint.shader; + final EngineGradient engineShader = paint.shader as EngineGradient; final Object paintStyle = engineShader.createPaintStyle(_canvasPool.context); fillStyle = paintStyle; strokeStyle = paintStyle; } else if (paint.color != null) { - final String colorString = colorToCssString(paint.color); + final String? colorString = colorToCssString(paint.color); fillStyle = colorString; strokeStyle = colorString; } else { @@ -799,7 +810,7 @@ class ContextStateHandle { strokeStyle = ''; } - final ui.MaskFilter maskFilter = paint?.maskFilter; + final ui.MaskFilter? maskFilter = paint.maskFilter; if (!_renderMaskFilterForWebkit) { if (_currentFilter != maskFilter) { _currentFilter = maskFilter; @@ -815,11 +826,11 @@ class ContextStateHandle { if (maskFilter != null) { context.save(); context.shadowBlur = convertSigmaToRadius(maskFilter.webOnlySigma); - if (paint?.color != null) { + if (paint.color != null) { // Shadow color must be fully opaque. - context.shadowColor = colorToCssString(paint.color.withAlpha(255)); + context.shadowColor = colorToCssString(paint.color!.withAlpha(255))!; } else { - context.shadowColor = colorToCssString(const ui.Color(0xFF000000)); + context.shadowColor = colorToCssString(const ui.Color(0xFF000000))!; } // On the web a shadow must always be painted together with the shape @@ -865,7 +876,7 @@ class ContextStateHandle { _debugIsPaintSetUp = false; } - final ui.MaskFilter maskFilter = _lastUsedPaint?.maskFilter; + final ui.MaskFilter? maskFilter = _lastUsedPaint?.maskFilter; if (maskFilter != null && _renderMaskFilterForWebkit) { // On Safari (WebKit) we use a translated shadow to emulate // MaskFilter.blur. We use restore to undo the translation and @@ -874,7 +885,7 @@ class ContextStateHandle { } } - void paint(ui.PaintingStyle style) { + void paint(ui.PaintingStyle? style) { if (style == ui.PaintingStyle.stroke) { context.stroke(); } else { @@ -882,7 +893,7 @@ class ContextStateHandle { } } - void paintPath(ui.PaintingStyle style, ui.PathFillType pathFillType) { + void paintPath(ui.PaintingStyle? style, ui.PathFillType pathFillType) { if (style == ui.PaintingStyle.stroke) { context.stroke(); } else { @@ -927,7 +938,7 @@ class _SaveStackTracking { /// The stack that maintains clipping operations used when text is painted /// onto bitmap canvas but is composited as separate element. - List<_SaveClipEntry> _clipStack; + List<_SaveClipEntry>? _clipStack; /// Returns whether there are active clipping regions on the canvas. bool get isClipped => _clipStack != null; @@ -951,7 +962,7 @@ class _SaveStackTracking { _saveStack.add(_SaveStackEntry( transform: _currentTransform.clone(), clipStack: - _clipStack == null ? null : List<_SaveClipEntry>.from(_clipStack), + _clipStack == null ? null : List<_SaveClipEntry>.from(_clipStack!), )); } @@ -1004,20 +1015,20 @@ class _SaveStackTracking { @mustCallSuper void clipRect(ui.Rect rect) { _clipStack ??= <_SaveClipEntry>[]; - _clipStack.add(_SaveClipEntry.rect(rect, _currentTransform.clone())); + _clipStack!.add(_SaveClipEntry.rect(rect, _currentTransform.clone())); } /// Adds a round rectangle to clipping stack. @mustCallSuper void clipRRect(ui.RRect rrect) { _clipStack ??= <_SaveClipEntry>[]; - _clipStack.add(_SaveClipEntry.rrect(rrect, _currentTransform.clone())); + _clipStack!.add(_SaveClipEntry.rrect(rrect, _currentTransform.clone())); } /// Adds a path to clipping stack. @mustCallSuper void clipPath(ui.Path path) { _clipStack ??= <_SaveClipEntry>[]; - _clipStack.add(_SaveClipEntry.path(path, _currentTransform.clone())); + _clipStack!.add(_SaveClipEntry.path(path, _currentTransform.clone())); } } diff --git a/lib/web_ui/lib/src/engine/clipboard.dart b/lib/web_ui/lib/src/engine/clipboard.dart index cc5ed5532c96c..f9446b68a2e60 100644 --- a/lib/web_ui/lib/src/engine/clipboard.dart +++ b/lib/web_ui/lib/src/engine/clipboard.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Handles clipboard related platform messages. @@ -16,16 +16,16 @@ class ClipboardMessageHandler { /// Handles the platform message which stores the given text to the clipboard. void setDataMethodCall( - MethodCall methodCall, ui.PlatformMessageResponseCallback callback) { + MethodCall methodCall, ui.PlatformMessageResponseCallback? callback) { const MethodCodec codec = JSONMethodCodec(); bool errorEnvelopeEncoded = false; _copyToClipboardStrategy .setData(methodCall.arguments['text']) .then((bool success) { if (success) { - callback(codec.encodeSuccessEnvelope(true)); + callback!(codec.encodeSuccessEnvelope(true)); } else { - callback(codec.encodeErrorEnvelope( + callback!(codec.encodeErrorEnvelope( code: 'copy_fail', message: 'Clipboard.setData failed')); errorEnvelopeEncoded = true; } @@ -33,21 +33,21 @@ class ClipboardMessageHandler { // Don't encode a duplicate reply if we already failed and an error // was already encoded. if (!errorEnvelopeEncoded) { - callback(codec.encodeErrorEnvelope( + callback!(codec.encodeErrorEnvelope( code: 'copy_fail', message: 'Clipboard.setData failed')); } }); } /// Handles the platform message which retrieves text data from the clipboard. - void getDataMethodCall(ui.PlatformMessageResponseCallback callback) { + void getDataMethodCall(ui.PlatformMessageResponseCallback? callback) { const MethodCodec codec = JSONMethodCodec(); _pasteFromClipboardStrategy.getData().then((String data) { final Map map = {'text': data}; - callback(codec.encodeSuccessEnvelope(map)); + callback!(codec.encodeSuccessEnvelope(map)); }).catchError((dynamic error) { print('Could not get text from clipboard: $error'); - callback(codec.encodeErrorEnvelope( + callback!(codec.encodeErrorEnvelope( code: 'paste_fail', message: 'Clipboard.getData failed')); }); } @@ -62,13 +62,17 @@ class ClipboardMessageHandler { } } +bool _unsafeIsNull(dynamic object) { + return object == null; +} + /// Provides functionality for writing text to clipboard. /// /// A concrete implementation is picked at runtime based on the available /// APIs and the browser. abstract class CopyToClipboardStrategy { factory CopyToClipboardStrategy() { - return (html.window.navigator.clipboard?.writeText != null) + return !_unsafeIsNull(html.window.navigator.clipboard) ? ClipboardAPICopyStrategy() : ExecCommandCopyStrategy(); } @@ -78,7 +82,7 @@ abstract class CopyToClipboardStrategy { /// Returns `true` for a successful action. /// /// Returns `false` for an uncessful action or when there is an excaption. - Future setData(String text); + Future setData(String? text); } /// Provides functionality for reading text from clipboard. @@ -88,7 +92,7 @@ abstract class CopyToClipboardStrategy { abstract class PasteFromClipboardStrategy { factory PasteFromClipboardStrategy() { return (browserEngine == BrowserEngine.firefox || - html.window.navigator.clipboard?.readText == null) + _unsafeIsNull(html.window.navigator.clipboard)) ? ExecCommandPasteStrategy() : ClipboardAPIPasteStrategy(); } @@ -103,11 +107,11 @@ abstract class PasteFromClipboardStrategy { /// See: https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API class ClipboardAPICopyStrategy implements CopyToClipboardStrategy { @override - Future setData(String text) async { + Future setData(String? text) async { try { - await html.window.navigator.clipboard.writeText(text); - } catch (e) { - print('copy is not successful ${e.message}'); + await html.window.navigator.clipboard.writeText(text!); + } catch (error) { + print('copy is not successful $error'); return Future.value(false); } return Future.value(true); @@ -130,11 +134,11 @@ class ClipboardAPIPasteStrategy implements PasteFromClipboardStrategy { /// Provides a fallback strategy for browsers which does not support ClipboardAPI. class ExecCommandCopyStrategy implements CopyToClipboardStrategy { @override - Future setData(String text) { + Future setData(String? text) { return Future.value(_setDataSync(text)); } - bool _setDataSync(String text) { + bool _setDataSync(String? text) { // Copy content to clipboard with execCommand. // See: https://developers.google.com/web/updates/2015/04/cut-and-copy-commands final html.TextAreaElement tempTextArea = _appendTemporaryTextArea(); @@ -147,8 +151,8 @@ class ExecCommandCopyStrategy implements CopyToClipboardStrategy { if (!result) { print('copy is not successful'); } - } catch (e) { - print('copy is not successful ${e.message}'); + } catch (error) { + print('copy is not successful $error'); } finally { _removeTemporaryTextArea(tempTextArea); } @@ -167,13 +171,13 @@ class ExecCommandCopyStrategy implements CopyToClipboardStrategy { ..backgroundColor = 'transparent' ..background = 'transparent'; - html.document.body.append(tempElement); + html.document.body!.append(tempElement); return tempElement; } void _removeTemporaryTextArea(html.HtmlElement element) { - element?.remove(); + element.remove(); } } diff --git a/lib/web_ui/lib/src/engine/color_filter.dart b/lib/web_ui/lib/src/engine/color_filter.dart index c674ea807e3a6..4f8c82b77821e 100644 --- a/lib/web_ui/lib/src/engine/color_filter.dart +++ b/lib/web_ui/lib/src/engine/color_filter.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A description of a color filter to apply when drawing a shape or compositing @@ -109,9 +109,9 @@ class EngineColorFilter implements ui.ColorFilter { _matrix = null, _type = _TypeSrgbToLinearGamma; - final ui.Color _color; - final ui.BlendMode _blendMode; - final List _matrix; + final ui.Color? _color; + final ui.BlendMode? _blendMode; + final List? _matrix; final int _type; // The type of SkColorFilter class to create for Skia. @@ -137,7 +137,7 @@ class EngineColorFilter implements ui.ColorFilter { return _color == typedOther._color && _blendMode == typedOther._blendMode; } - SkColorFilter _toSkColorFilter() { + SkColorFilter? _toSkColorFilter() { switch (_type) { case _TypeMode: if (_color == null || _blendMode == null) { @@ -148,7 +148,7 @@ class EngineColorFilter implements ui.ColorFilter { if (_matrix == null) { return null; } - assert(_matrix.length == 20, 'Color Matrix must have 20 entries.'); + assert(_matrix!.length == 20, 'Color Matrix must have 20 entries.'); return SkColorFilter.matrix(this); case _TypeLinearToSrgbGamma: return SkColorFilter.linearToSrgbGamma(this); diff --git a/lib/web_ui/lib/src/engine/compositor/canvas.dart b/lib/web_ui/lib/src/engine/compositor/canvas.dart index dac20416d46dc..3377aa8a8379f 100644 --- a/lib/web_ui/lib/src/engine/compositor/canvas.dart +++ b/lib/web_ui/lib/src/engine/compositor/canvas.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A Dart wrapper around Skia's SKCanvas. @@ -11,16 +11,16 @@ class SkCanvas { SkCanvas(this.skCanvas); - int get saveCount => skCanvas.callMethod('getSaveCount'); + int? get saveCount => skCanvas.callMethod('getSaveCount'); void clear(ui.Color color) { setSharedSkColor1(color); - skCanvas.callMethod('clear', [sharedSkColor1]); + skCanvas.callMethod('clear', [sharedSkColor1]); } void clipPath(ui.Path path, bool doAntiAlias) { - final SkPath skPath = path; - final js.JsObject intersectClipOp = canvasKit['ClipOp']['Intersect']; + final SkPath skPath = path as SkPath; + final js.JsObject? intersectClipOp = canvasKit['ClipOp']['Intersect']; skCanvas.callMethod('clipPath', [ skPath._skPath, intersectClipOp, @@ -29,7 +29,7 @@ class SkCanvas { } void clipRRect(ui.RRect rrect, bool doAntiAlias) { - final js.JsObject intersectClipOp = canvasKit['ClipOp']['Intersect']; + final js.JsObject? intersectClipOp = canvasKit['ClipOp']['Intersect']; skCanvas.callMethod('clipRRect', [ makeSkRRect(rrect), intersectClipOp, @@ -38,7 +38,7 @@ class SkCanvas { } void clipRect(ui.Rect rect, ui.ClipOp clipOp, bool doAntiAlias) { - js.JsObject skClipOp; + js.JsObject? skClipOp; switch (clipOp) { case ui.ClipOp.difference: skClipOp = canvasKit['ClipOp']['Difference']; @@ -74,10 +74,10 @@ class SkCanvas { ui.Image atlas, Float32List rstTransforms, Float32List rects, - js.JsArray colors, + js.JsArray? colors, ui.BlendMode blendMode, ) { - final SkImage skAtlas = atlas; + final SkImage skAtlas = atlas as SkImage; skCanvas.callMethod('drawAtlas', [ skAtlas.skImage, rects, @@ -105,7 +105,7 @@ class SkCanvas { } void drawDRRect(ui.RRect outer, ui.RRect inner, SkPaint paint) { - skCanvas.callMethod('drawDRRect', [ + skCanvas.callMethod('drawDRRect', [ makeSkRRect(outer), makeSkRRect(inner), paint.skiaObject, @@ -113,7 +113,7 @@ class SkCanvas { } void drawImage(ui.Image image, ui.Offset offset, SkPaint paint) { - final SkImage skImage = image; + final SkImage skImage = image as SkImage; skCanvas.callMethod('drawImage', [ skImage.skImage, offset.dx, @@ -123,7 +123,7 @@ class SkCanvas { } void drawImageRect(ui.Image image, ui.Rect src, ui.Rect dst, SkPaint paint) { - final SkImage skImage = image; + final SkImage skImage = image as SkImage; skCanvas.callMethod('drawImageRect', [ skImage.skImage, makeSkRect(src), @@ -135,7 +135,7 @@ class SkCanvas { void drawImageNine( ui.Image image, ui.Rect center, ui.Rect dst, SkPaint paint) { - final SkImage skImage = image; + final SkImage skImage = image as SkImage; skCanvas.callMethod('drawImageNine', [ skImage.skImage, makeSkRect(center), @@ -155,18 +155,18 @@ class SkCanvas { } void drawOval(ui.Rect rect, SkPaint paint) { - skCanvas.callMethod('drawOval', [ + skCanvas.callMethod('drawOval', [ makeSkRect(rect), paint.skiaObject, ]); } void drawPaint(SkPaint paint) { - skCanvas.callMethod('drawPaint', [paint.skiaObject]); + skCanvas.callMethod('drawPaint', [paint.skiaObject]); } void drawParagraph(ui.Paragraph paragraph, ui.Offset offset) { - final SkParagraph skParagraph = paragraph; + final SkParagraph skParagraph = paragraph as SkParagraph; skCanvas.callMethod('drawParagraph', [ skParagraph.skParagraph, offset.dx, @@ -175,20 +175,20 @@ class SkCanvas { } void drawPath(ui.Path path, SkPaint paint) { - final js.JsObject skPaint = paint.skiaObject; - final SkPath enginePath = path; - final js.JsObject skPath = enginePath._skPath; - skCanvas.callMethod('drawPath', [skPath, skPaint]); + final js.JsObject? skPaint = paint.skiaObject; + final SkPath enginePath = path as SkPath; + final js.JsObject? skPath = enginePath._skPath; + skCanvas.callMethod('drawPath', [skPath, skPaint]); } void drawPicture(ui.Picture picture) { - final SkPicture skPicture = picture; - skCanvas.callMethod('drawPicture', [skPicture.skPicture]); + final SkPicture skPicture = picture as SkPicture; + skCanvas.callMethod('drawPicture', [skPicture.skPicture]); } // TODO(hterkelsen): https://github.com/flutter/flutter/issues/58824 void drawPoints(SkPaint paint, ui.PointMode pointMode, - js.JsArray> points) { + js.JsArray>? points) { skCanvas.callMethod('drawPoints', [ makeSkPointMode(pointMode), points, @@ -197,7 +197,7 @@ class SkCanvas { } void drawRRect(ui.RRect rrect, SkPaint paint) { - skCanvas.callMethod('drawRRect', [ + skCanvas.callMethod('drawRRect', [ makeSkRRect(rrect), paint.skiaObject, ]); @@ -205,20 +205,20 @@ class SkCanvas { void drawRect(ui.Rect rect, SkPaint paint) { final js.JsObject skRect = makeSkRect(rect); - final js.JsObject skPaint = paint.skiaObject; - skCanvas.callMethod('drawRect', [skRect, skPaint]); + final js.JsObject? skPaint = paint.skiaObject; + skCanvas.callMethod('drawRect', [skRect, skPaint]); } void drawShadow(ui.Path path, ui.Color color, double elevation, bool transparentOccluder) { - drawSkShadow(skCanvas, path, color, elevation, transparentOccluder, + drawSkShadow(skCanvas, path as SkPath, color, elevation, transparentOccluder, ui.window.devicePixelRatio); } void drawVertices( ui.Vertices vertices, ui.BlendMode blendMode, SkPaint paint) { - SkVertices skVertices = vertices; - skCanvas.callMethod('drawVertices', [ + SkVertices skVertices = vertices as SkVertices; + skCanvas.callMethod('drawVertices', [ skVertices.skVertices, makeSkBlendMode(blendMode), paint.skiaObject @@ -229,8 +229,8 @@ class SkCanvas { skCanvas.callMethod('restore'); } - void restoreToCount(int count) { - skCanvas.callMethod('restoreToCount', [count]); + void restoreToCount(int? count) { + skCanvas.callMethod('restoreToCount', [count]); } void rotate(double radians) { @@ -238,24 +238,24 @@ class SkCanvas { .callMethod('rotate', [radians * 180.0 / math.pi, 0.0, 0.0]); } - int save() { + int? save() { return skCanvas.callMethod('save'); } void saveLayer(ui.Rect bounds, SkPaint paint) { - assert(bounds != null, 'Use saveLayerWithoutBounds'); - skCanvas.callMethod('saveLayer', [ + assert(bounds != null, 'Use saveLayerWithoutBounds'); // ignore: unnecessary_null_comparison + skCanvas.callMethod('saveLayer', [ makeSkRect(bounds), paint.skiaObject, ]); } void saveLayerWithoutBounds(SkPaint paint) { - skCanvas.callMethod('saveLayer', [paint.skiaObject]); + skCanvas.callMethod('saveLayer', [paint.skiaObject]); } void saveLayerWithFilter(ui.Rect bounds, ui.ImageFilter filter) { - final SkImageFilter skImageFilter = filter; + final SkImageFilter skImageFilter = filter as SkImageFilter; return skCanvas.callMethod( 'saveLayer', [ @@ -275,7 +275,7 @@ class SkCanvas { skCanvas.callMethod('skew', [sx, sy]); } - void transform(Float32List matrix4) { + void transform(Float32List? matrix4) { skCanvas.callMethod( 'concat', >[makeSkMatrixFromFloat32(matrix4)]); } diff --git a/lib/web_ui/lib/src/engine/compositor/canvas_kit_canvas.dart b/lib/web_ui/lib/src/engine/compositor/canvas_kit_canvas.dart index fda4b67f9fde0..50e3373486402 100644 --- a/lib/web_ui/lib/src/engine/compositor/canvas_kit_canvas.dart +++ b/lib/web_ui/lib/src/engine/compositor/canvas_kit_canvas.dart @@ -2,21 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// An implementation of [ui.Canvas] that is backed by a CanvasKit canvas. class CanvasKitCanvas implements ui.Canvas { - final SkCanvas _canvas; + final SkCanvas? _canvas; - factory CanvasKitCanvas(ui.PictureRecorder recorder, [ui.Rect cullRect]) { - assert(recorder != null); + factory CanvasKitCanvas(ui.PictureRecorder recorder, [ui.Rect? cullRect]) { + assert(recorder != null); // ignore: unnecessary_null_comparison if (recorder.isRecording) { throw ArgumentError( '"recorder" must not already be associated with another Canvas.'); } cullRect ??= ui.Rect.largest; - final SkPictureRecorder skRecorder = recorder; + final SkPictureRecorder skRecorder = recorder as SkPictureRecorder; return CanvasKitCanvas._(skRecorder.beginRecording(cullRect)); } @@ -24,12 +24,12 @@ class CanvasKitCanvas implements ui.Canvas { @override void save() { - _canvas.save(); + _canvas!.save(); } @override - void saveLayer(ui.Rect bounds, ui.Paint paint) { - assert(paint != null); + void saveLayer(ui.Rect? bounds, ui.Paint paint) { + assert(paint != null); // ignore: unnecessary_null_comparison if (bounds == null) { _saveLayerWithoutBounds(paint); } else { @@ -39,48 +39,48 @@ class CanvasKitCanvas implements ui.Canvas { } void _saveLayerWithoutBounds(ui.Paint paint) { - _canvas.saveLayerWithoutBounds(paint); + _canvas!.saveLayerWithoutBounds(paint as SkPaint); } void _saveLayer(ui.Rect bounds, ui.Paint paint) { - _canvas.saveLayer(bounds, paint); + _canvas!.saveLayer(bounds, paint as SkPaint); } @override void restore() { - _canvas.restore(); + _canvas!.restore(); } @override int getSaveCount() { - return _canvas.saveCount; + return _canvas!.saveCount!; } @override void translate(double dx, double dy) { - _canvas.translate(dx, dy); + _canvas!.translate(dx, dy); } @override - void scale(double sx, [double sy]) => _scale(sx, sy ?? sx); + void scale(double sx, [double? sy]) => _scale(sx, sy ?? sx); void _scale(double sx, double sy) { - _canvas.scale(sx, sy); + _canvas!.scale(sx, sy); } @override void rotate(double radians) { - _canvas.rotate(radians); + _canvas!.rotate(radians); } @override void skew(double sx, double sy) { - _canvas.skew(sx, sy); + _canvas!.skew(sx, sy); } @override void transform(Float64List matrix4) { - assert(matrix4 != null); + assert(matrix4 != null); // ignore: unnecessary_null_comparison if (matrix4.length != 16) { throw ArgumentError('"matrix4" must have 16 entries.'); } @@ -88,234 +88,240 @@ class CanvasKitCanvas implements ui.Canvas { } void _transform(Float32List matrix4) { - _canvas.transform(matrix4); + _canvas!.transform(matrix4); } @override void clipRect(ui.Rect rect, {ui.ClipOp clipOp = ui.ClipOp.intersect, bool doAntiAlias = true}) { assert(rectIsValid(rect)); - assert(clipOp != null); - assert(doAntiAlias != null); + assert(clipOp != null); // ignore: unnecessary_null_comparison + assert(doAntiAlias != null); // ignore: unnecessary_null_comparison _clipRect(rect, clipOp, doAntiAlias); } void _clipRect(ui.Rect rect, ui.ClipOp clipOp, bool doAntiAlias) { - _canvas.clipRect(rect, clipOp, doAntiAlias); + _canvas!.clipRect(rect, clipOp, doAntiAlias); } @override void clipRRect(ui.RRect rrect, {bool doAntiAlias = true}) { assert(rrectIsValid(rrect)); - assert(doAntiAlias != null); + assert(doAntiAlias != null); // ignore: unnecessary_null_comparison _clipRRect(rrect, doAntiAlias); } void _clipRRect(ui.RRect rrect, bool doAntiAlias) { - _canvas.clipRRect(rrect, doAntiAlias); + _canvas!.clipRRect(rrect, doAntiAlias); } @override void clipPath(ui.Path path, {bool doAntiAlias = true}) { + // ignore: unnecessary_null_comparison assert(path != null); // path is checked on the engine side - assert(doAntiAlias != null); + assert(doAntiAlias != null); // ignore: unnecessary_null_comparison _clipPath(path, doAntiAlias); } void _clipPath(ui.Path path, bool doAntiAlias) { - _canvas.clipPath(path, doAntiAlias); + _canvas!.clipPath(path, doAntiAlias); } @override void drawColor(ui.Color color, ui.BlendMode blendMode) { - assert(color != null); - assert(blendMode != null); + assert(color != null); // ignore: unnecessary_null_comparison + assert(blendMode != null); // ignore: unnecessary_null_comparison _drawColor(color, blendMode); } void _drawColor(ui.Color color, ui.BlendMode blendMode) { - _canvas.drawColor(color, blendMode); + _canvas!.drawColor(color, blendMode); } @override void drawLine(ui.Offset p1, ui.Offset p2, ui.Paint paint) { assert(_offsetIsValid(p1)); assert(_offsetIsValid(p2)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawLine(p1, p2, paint); } void _drawLine(ui.Offset p1, ui.Offset p2, ui.Paint paint) { - _canvas.drawLine(p1, p2, paint); + _canvas!.drawLine(p1, p2, paint as SkPaint); } @override void drawPaint(ui.Paint paint) { - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawPaint(paint); } void _drawPaint(ui.Paint paint) { - _canvas.drawPaint(paint); + _canvas!.drawPaint(paint as SkPaint); } @override void drawRect(ui.Rect rect, ui.Paint paint) { assert(rectIsValid(rect)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawRect(rect, paint); } void _drawRect(ui.Rect rect, ui.Paint paint) { - _canvas.drawRect(rect, paint); + _canvas!.drawRect(rect, paint as SkPaint); } @override void drawRRect(ui.RRect rrect, ui.Paint paint) { assert(rrectIsValid(rrect)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawRRect(rrect, paint); } void _drawRRect(ui.RRect rrect, ui.Paint paint) { - _canvas.drawRRect(rrect, paint); + _canvas!.drawRRect(rrect, paint as SkPaint); } @override void drawDRRect(ui.RRect outer, ui.RRect inner, ui.Paint paint) { assert(rrectIsValid(outer)); assert(rrectIsValid(inner)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawDRRect(outer, inner, paint); } void _drawDRRect(ui.RRect outer, ui.RRect inner, ui.Paint paint) { - _canvas.drawDRRect(outer, inner, paint); + _canvas!.drawDRRect(outer, inner, paint as SkPaint); } @override void drawOval(ui.Rect rect, ui.Paint paint) { assert(rectIsValid(rect)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawOval(rect, paint); } void _drawOval(ui.Rect rect, ui.Paint paint) { - _canvas.drawOval(rect, paint); + _canvas!.drawOval(rect, paint as SkPaint); } @override void drawCircle(ui.Offset c, double radius, ui.Paint paint) { assert(_offsetIsValid(c)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawCircle(c, radius, paint); } void _drawCircle(ui.Offset c, double radius, ui.Paint paint) { - _canvas.drawCircle(c, radius, paint); + _canvas!.drawCircle(c, radius, paint as SkPaint); } @override void drawArc(ui.Rect rect, double startAngle, double sweepAngle, bool useCenter, ui.Paint paint) { assert(rectIsValid(rect)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawArc(rect, startAngle, sweepAngle, useCenter, paint); } void _drawArc(ui.Rect rect, double startAngle, double sweepAngle, bool useCenter, ui.Paint paint) { - _canvas.drawArc(rect, startAngle, sweepAngle, useCenter, paint); + _canvas!.drawArc(rect, startAngle, sweepAngle, useCenter, paint as SkPaint); } @override void drawPath(ui.Path path, ui.Paint paint) { + // ignore: unnecessary_null_comparison assert(path != null); // path is checked on the engine side - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawPath(path, paint); } void _drawPath(ui.Path path, ui.Paint paint) { - _canvas.drawPath(path, paint); + _canvas!.drawPath(path, paint as SkPaint); } @override void drawImage(ui.Image image, ui.Offset p, ui.Paint paint) { + // ignore: unnecessary_null_comparison assert(image != null); // image is checked on the engine side assert(_offsetIsValid(p)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawImage(image, p, paint); } void _drawImage(ui.Image image, ui.Offset p, ui.Paint paint) { - _canvas.drawImage(image, p, paint); + _canvas!.drawImage(image, p, paint as SkPaint); } @override void drawImageRect(ui.Image image, ui.Rect src, ui.Rect dst, ui.Paint paint) { + // ignore: unnecessary_null_comparison assert(image != null); // image is checked on the engine side assert(rectIsValid(src)); assert(rectIsValid(dst)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawImageRect(image, src, dst, paint); } void _drawImageRect( ui.Image image, ui.Rect src, ui.Rect dst, ui.Paint paint) { - _canvas.drawImageRect(image, src, dst, paint); + _canvas!.drawImageRect(image, src, dst, paint as SkPaint); } @override void drawImageNine( ui.Image image, ui.Rect center, ui.Rect dst, ui.Paint paint) { + // ignore: unnecessary_null_comparison assert(image != null); // image is checked on the engine side assert(rectIsValid(center)); assert(rectIsValid(dst)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawImageNine(image, center, dst, paint); } void _drawImageNine( ui.Image image, ui.Rect center, ui.Rect dst, ui.Paint paint) { - _canvas.drawImageNine(image, center, dst, paint); + _canvas!.drawImageNine(image, center, dst, paint as SkPaint); } @override void drawPicture(ui.Picture picture) { + // ignore: unnecessary_null_comparison assert(picture != null); // picture is checked on the engine side _drawPicture(picture); } void _drawPicture(ui.Picture picture) { - _canvas.drawPicture(picture); + _canvas!.drawPicture(picture); } @override void drawParagraph(ui.Paragraph paragraph, ui.Offset offset) { - assert(paragraph != null); + assert(paragraph != null); // ignore: unnecessary_null_comparison assert(_offsetIsValid(offset)); _drawParagraph(paragraph, offset); } void _drawParagraph(ui.Paragraph paragraph, ui.Offset offset) { - _canvas.drawParagraph(paragraph, offset); + _canvas!.drawParagraph(paragraph, offset); } @override void drawPoints( ui.PointMode pointMode, List points, ui.Paint paint) { - assert(pointMode != null); - assert(points != null); - assert(paint != null); + assert(pointMode != null); // ignore: unnecessary_null_comparison + assert(points != null); // ignore: unnecessary_null_comparison + assert(paint != null); // ignore: unnecessary_null_comparison _drawPoints(paint, pointMode, encodePointList(points)); } @override void drawRawPoints( ui.PointMode pointMode, Float32List points, ui.Paint paint) { - assert(pointMode != null); - assert(points != null); - assert(paint != null); + assert(pointMode != null); // ignore: unnecessary_null_comparison + assert(points != null); // ignore: unnecessary_null_comparison + assert(paint != null); // ignore: unnecessary_null_comparison if (points.length % 2 != 0) { throw ArgumentError('"points" must have an even number of values.'); } @@ -323,22 +329,23 @@ class CanvasKitCanvas implements ui.Canvas { } void _drawPoints( - ui.Paint paint, ui.PointMode pointMode, List> points) { - _canvas.drawPoints(paint, pointMode, points); + ui.Paint paint, ui.PointMode pointMode, List>? points) { + _canvas!.drawPoints(paint as SkPaint, pointMode, points as js.JsArray>?); } @override void drawVertices( ui.Vertices vertices, ui.BlendMode blendMode, ui.Paint paint) { + // ignore: unnecessary_null_comparison assert(vertices != null); // vertices is checked on the engine side - assert(paint != null); - assert(blendMode != null); + assert(paint != null); // ignore: unnecessary_null_comparison + assert(blendMode != null); // ignore: unnecessary_null_comparison _drawVertices(vertices, blendMode, paint); } void _drawVertices( ui.Vertices vertices, ui.BlendMode blendMode, ui.Paint paint) { - _canvas.drawVertices(vertices, blendMode, paint); + _canvas!.drawVertices(vertices, blendMode, paint as SkPaint); } @override @@ -348,14 +355,15 @@ class CanvasKitCanvas implements ui.Canvas { List rects, List colors, ui.BlendMode blendMode, - ui.Rect cullRect, + ui.Rect? cullRect, ui.Paint paint) { + // ignore: unnecessary_null_comparison assert(atlas != null); // atlas is checked on the engine side - assert(transforms != null); - assert(rects != null); - assert(colors != null); - assert(blendMode != null); - assert(paint != null); + assert(transforms != null); // ignore: unnecessary_null_comparison + assert(rects != null); // ignore: unnecessary_null_comparison + assert(colors != null); // ignore: unnecessary_null_comparison + assert(blendMode != null); // ignore: unnecessary_null_comparison + assert(paint != null); // ignore: unnecessary_null_comparison final int rectCount = rects.length; if (transforms.length != rectCount) { @@ -387,7 +395,7 @@ class CanvasKitCanvas implements ui.Canvas { rectBuffer[index3] = rect.bottom; } - final js.JsArray colorBuffer = + final js.JsArray? colorBuffer = colors.isEmpty ? null : makeColorList(colors); _drawAtlas( @@ -401,14 +409,15 @@ class CanvasKitCanvas implements ui.Canvas { Float32List rects, Int32List colors, ui.BlendMode blendMode, - ui.Rect cullRect, + ui.Rect? cullRect, ui.Paint paint) { + // ignore: unnecessary_null_comparison assert(atlas != null); // atlas is checked on the engine side - assert(rstTransforms != null); - assert(rects != null); - assert(colors != null); - assert(blendMode != null); - assert(paint != null); + assert(rstTransforms != null); // ignore: unnecessary_null_comparison + assert(rects != null); // ignore: unnecessary_null_comparison + assert(colors != null); // ignore: unnecessary_null_comparison + assert(blendMode != null); // ignore: unnecessary_null_comparison + assert(paint != null); // ignore: unnecessary_null_comparison final int rectCount = rects.length; if (rstTransforms.length != rectCount) @@ -416,7 +425,7 @@ class CanvasKitCanvas implements ui.Canvas { if (rectCount % 4 != 0) throw ArgumentError( '"rstTransforms" and "rects" lengths must be a multiple of four.'); - if (colors != null && colors.length * 4 != rectCount) + if (colors.length * 4 != rectCount) throw ArgumentError( 'If non-null, "colors" length must be one fourth the length of "rstTransforms" and "rects".'); @@ -430,23 +439,24 @@ class CanvasKitCanvas implements ui.Canvas { ui.Image atlas, Float32List rstTransforms, Float32List rects, - js.JsArray colors, + js.JsArray? colors, ui.BlendMode blendMode, ) { - _canvas.drawAtlasRaw(paint, atlas, rstTransforms, rects, colors, blendMode); + _canvas!.drawAtlasRaw(paint as SkPaint, atlas, rstTransforms, rects, colors, blendMode); } @override void drawShadow(ui.Path path, ui.Color color, double elevation, bool transparentOccluder) { + // ignore: unnecessary_null_comparison assert(path != null); // path is checked on the engine side - assert(color != null); - assert(transparentOccluder != null); + assert(color != null); // ignore: unnecessary_null_comparison + assert(transparentOccluder != null); // ignore: unnecessary_null_comparison _drawShadow(path, color, elevation, transparentOccluder); } void _drawShadow(ui.Path path, ui.Color color, double elevation, bool transparentOccluder) { - _canvas.drawShadow(path, color, elevation, transparentOccluder); + _canvas!.drawShadow(path, color, elevation, transparentOccluder); } } diff --git a/lib/web_ui/lib/src/engine/compositor/color_filter.dart b/lib/web_ui/lib/src/engine/compositor/color_filter.dart index f3dae063f3075..f788bd73015fe 100644 --- a/lib/web_ui/lib/src/engine/compositor/color_filter.dart +++ b/lib/web_ui/lib/src/engine/compositor/color_filter.dart @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A [ui.ColorFilter] backed by Skia's [SkColorFilter]. class SkColorFilter { - js.JsObject skColorFilter; + js.JsObject? skColorFilter; SkColorFilter.mode(EngineColorFilter filter) { - setSharedSkColor1(filter._color); + setSharedSkColor1(filter._color!); skColorFilter = canvasKit['SkColorFilter'].callMethod('MakeBlend', [ sharedSkColor1, @@ -23,7 +23,7 @@ class SkColorFilter { final js.JsArray colorMatrix = js.JsArray(); colorMatrix.length = 20; for (int i = 0; i < 20; i++) { - colorMatrix[i] = filter._matrix[i]; + colorMatrix[i] = filter._matrix![i]; } skColorFilter = canvasKit['SkColorFilter'] .callMethod('MakeMatrix', [colorMatrix]); diff --git a/lib/web_ui/lib/src/engine/compositor/embedded_views.dart b/lib/web_ui/lib/src/engine/compositor/embedded_views.dart index d5a76e55a3c36..4725a8dce9241 100644 --- a/lib/web_ui/lib/src/engine/compositor/embedded_views.dart +++ b/lib/web_ui/lib/src/engine/compositor/embedded_views.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// This composites HTML views into the [ui.Scene]. @@ -25,10 +25,10 @@ class HtmlViewEmbedder { {}; /// The HTML element associated with the given view id. - final Map _views = {}; + final Map _views = {}; /// The root view in the stack of mutator elements for the view id. - final Map _rootViews = {}; + final Map _rootViews = {}; /// The overlay for the view id. final Map _overlays = {}; @@ -37,7 +37,7 @@ class HtmlViewEmbedder { final Set _viewsToRecomposite = {}; /// The views that need to be disposed of on the next frame. - final Set _viewsToDispose = {}; + final Set _viewsToDispose = {}; /// The list of view ids that should be composited, in order. List _compositionOrder = []; @@ -49,7 +49,7 @@ class HtmlViewEmbedder { Map _clipCount = {}; /// The size of the frame, in physical pixels. - ui.Size _frameSize; + ui.Size _frameSize = _computeFrameSize(); void set frameSize(ui.Size size) { if (_frameSize == size) { @@ -60,8 +60,8 @@ class HtmlViewEmbedder { } void handlePlatformViewCall( - ByteData data, - ui.PlatformMessageResponseCallback callback, + ByteData? data, + ui.PlatformMessageResponseCallback? callback, ) { const MethodCodec codec = StandardMethodCodec(); final MethodCall decoded = codec.decodeMethodCall(data); @@ -71,21 +71,21 @@ class HtmlViewEmbedder { _create(decoded, callback); return; case 'dispose': - _dispose(decoded, callback); + _dispose(decoded, callback!); return; } - callback(null); + callback!(null); } void _create( - MethodCall methodCall, ui.PlatformMessageResponseCallback callback) { + MethodCall methodCall, ui.PlatformMessageResponseCallback? callback) { final Map args = methodCall.arguments; - final int viewId = args['id']; - final String viewType = args['viewType']; + final int? viewId = args['id']; + final String? viewType = args['viewType']; const MethodCodec codec = StandardMethodCodec(); if (_views[viewId] != null) { - callback(codec.encodeErrorEnvelope( + callback!(codec.encodeErrorEnvelope( code: 'recreating_view', message: 'trying to create an already created view', details: 'view id: $viewId', @@ -93,10 +93,10 @@ class HtmlViewEmbedder { return; } - final ui.PlatformViewFactory factory = + final ui.PlatformViewFactory? factory = ui.platformViewRegistry.registeredFactories[viewType]; if (factory == null) { - callback(codec.encodeErrorEnvelope( + callback!(codec.encodeErrorEnvelope( code: 'unregistered_view_type', message: 'trying to create a view with an unregistered type', details: 'unregistered view type: $viewType', @@ -105,17 +105,17 @@ class HtmlViewEmbedder { } // TODO(het): Support creation parameters. - html.Element embeddedView = factory(viewId); + html.Element embeddedView = factory(viewId!); _views[viewId] = embeddedView; _rootViews[viewId] = embeddedView; - callback(codec.encodeSuccessEnvelope(null)); + callback!(codec.encodeSuccessEnvelope(null)); } void _dispose( MethodCall methodCall, ui.PlatformMessageResponseCallback callback) { - int viewId = methodCall.arguments; + int? viewId = methodCall.arguments; const MethodCodec codec = StandardMethodCodec(); if (!_views.containsKey(viewId)) { callback(codec.encodeErrorEnvelope( @@ -128,11 +128,11 @@ class HtmlViewEmbedder { callback(codec.encodeSuccessEnvelope(null)); } - List getCurrentCanvases() { - final List canvases = []; + List getCurrentCanvases() { + final List canvases = []; for (int i = 0; i < _compositionOrder.length; i++) { final int viewId = _compositionOrder[i]; - canvases.add(_pictureRecorders[viewId].recordingCanvas); + canvases.add(_pictureRecorders[viewId]!.recordingCanvas); } return canvases; } @@ -140,7 +140,7 @@ class HtmlViewEmbedder { void prerollCompositeEmbeddedView(int viewId, EmbeddedViewParams params) { final pictureRecorder = SkPictureRecorder(); pictureRecorder.beginRecording(ui.Offset.zero & _frameSize); - pictureRecorder.recordingCanvas.clear(ui.Color(0x00000000)); + pictureRecorder.recordingCanvas!.clear(ui.Color(0x00000000)); _pictureRecorders[viewId] = pictureRecorder; _compositionOrder.add(viewId); @@ -152,28 +152,28 @@ class HtmlViewEmbedder { _viewsToRecomposite.add(viewId); } - SkCanvas compositeEmbeddedView(int viewId) { + SkCanvas? compositeEmbeddedView(int viewId) { // Do nothing if this view doesn't need to be composited. if (!_viewsToRecomposite.contains(viewId)) { - return _pictureRecorders[viewId].recordingCanvas; + return _pictureRecorders[viewId]!.recordingCanvas; } - _compositeWithParams(viewId, _currentCompositionParams[viewId]); + _compositeWithParams(viewId, _currentCompositionParams[viewId]!); _viewsToRecomposite.remove(viewId); - return _pictureRecorders[viewId].recordingCanvas; + return _pictureRecorders[viewId]!.recordingCanvas; } void _compositeWithParams(int viewId, EmbeddedViewParams params) { - final html.Element platformView = _views[viewId]; + final html.Element platformView = _views[viewId]!; platformView.style.width = '${params.size.width}px'; platformView.style.height = '${params.size.height}px'; platformView.style.position = 'absolute'; final int currentClippingCount = _countClips(params.mutators); - final int previousClippingCount = _clipCount[viewId]; + final int? previousClippingCount = _clipCount[viewId]; if (currentClippingCount != previousClippingCount) { _clipCount[viewId] = currentClippingCount; - html.Element oldPlatformViewRoot = _rootViews[viewId]; - html.Element newPlatformViewRoot = _reconstructClipViewsChain( + html.Element oldPlatformViewRoot = _rootViews[viewId]!; + html.Element? newPlatformViewRoot = _reconstructClipViewsChain( currentClippingCount, platformView, oldPlatformViewRoot, @@ -193,35 +193,35 @@ class HtmlViewEmbedder { return clipCount; } - html.Element _reconstructClipViewsChain( + html.Element? _reconstructClipViewsChain( int numClips, html.Element platformView, html.Element headClipView, ) { int indexInFlutterView = -1; if (headClipView.parent != null) { - indexInFlutterView = skiaSceneHost.children.indexOf(headClipView); + indexInFlutterView = skiaSceneHost!.children.indexOf(headClipView); headClipView.remove(); } - html.Element head = platformView; + html.Element? head = platformView; int clipIndex = 0; // Re-use as much existing clip views as needed. while (head != headClipView && clipIndex < numClips) { - head = head.parent; + head = head!.parent; clipIndex++; } // If there weren't enough existing clip views, add more. while (clipIndex < numClips) { html.Element clippingView = html.Element.tag('flt-clip'); - clippingView.append(head); + clippingView.append(head!); head = clippingView; clipIndex++; } - head.remove(); + head!.remove(); // If the chain was previously attached, attach it to the same position. if (indexInFlutterView > -1) { - skiaSceneHost.children.insert(indexInFlutterView, head); + skiaSceneHost!.children.insert(indexInFlutterView, head); } return head; } @@ -235,27 +235,27 @@ class HtmlViewEmbedder { for (final Mutator mutator in mutators) { switch (mutator.type) { case MutatorType.transform: - headTransform.multiply(mutator.matrix); + headTransform.multiply(mutator.matrix!); head.style.transform = float64ListToCssTransform(headTransform.storage); break; case MutatorType.clipRect: case MutatorType.clipRRect: case MutatorType.clipPath: - html.Element clipView = head.parent; + html.Element clipView = head.parent!; clipView.style.clip = ''; clipView.style.clipPath = ''; headTransform = Matrix4.identity(); clipView.style.transform = ''; if (mutator.rect != null) { - final ui.Rect rect = mutator.rect; + final ui.Rect rect = mutator.rect!; clipView.style.clip = 'rect(${rect.top}px, ${rect.right}px, ' '${rect.bottom}px, ${rect.left}px)'; } else if (mutator.rrect != null) { final SkPath path = SkPath(); - path.addRRect(mutator.rrect); + path.addRRect(mutator.rrect!); _ensureSvgPathDefs(); - html.Element pathDefs = _svgPathDefs.querySelector('#sk_path_defs'); + html.Element pathDefs = _svgPathDefs!.querySelector('#sk_path_defs')!; _clipPathCount += 1; html.Element newClipPath = html.Element.html('' @@ -264,9 +264,9 @@ class HtmlViewEmbedder { pathDefs.append(newClipPath); clipView.style.clipPath = 'url(#svgClip$_clipPathCount)'; } else if (mutator.path != null) { - final SkPath path = mutator.path; + final SkPath path = mutator.path as SkPath; _ensureSvgPathDefs(); - html.Element pathDefs = _svgPathDefs.querySelector('#sk_path_defs'); + html.Element pathDefs = _svgPathDefs!.querySelector('#sk_path_defs')!; _clipPathCount += 1; html.Element newClipPath = html.Element.html('' @@ -309,7 +309,7 @@ class HtmlViewEmbedder { int _clipPathCount = 0; - html.Element _svgPathDefs; + html.Element? _svgPathDefs; /// Ensures we add a container of SVG path defs to the DOM so they can /// be referred to in clip-path: url(#blah). @@ -321,7 +321,7 @@ class HtmlViewEmbedder { '', treeSanitizer: _NullTreeSanitizer(), ); - skiaSceneHost.append(_svgPathDefs); + skiaSceneHost!.append(_svgPathDefs!); } void submitFrame() { @@ -331,9 +331,9 @@ class HtmlViewEmbedder { int viewId = _compositionOrder[i]; ensureOverlayInitialized(viewId); final SurfaceFrame frame = - _overlays[viewId].surface.acquireFrame(_frameSize); + _overlays[viewId]!.surface.acquireFrame(_frameSize); final SkCanvas canvas = frame.skiaCanvas; - canvas.drawPicture(_pictureRecorders[viewId].endRecording()); + canvas.drawPicture(_pictureRecorders[viewId]!.endRecording()); frame.submit(); } _pictureRecorders.clear(); @@ -345,12 +345,12 @@ class HtmlViewEmbedder { for (int i = 0; i < _compositionOrder.length; i++) { int viewId = _compositionOrder[i]; - html.Element platformViewRoot = _rootViews[viewId]; - html.Element overlay = _overlays[viewId].surface.htmlElement; + html.Element platformViewRoot = _rootViews[viewId]!; + html.Element overlay = _overlays[viewId]!.surface.htmlElement!; platformViewRoot.remove(); - skiaSceneHost.append(platformViewRoot); + skiaSceneHost!.append(platformViewRoot); overlay.remove(); - skiaSceneHost.append(overlay); + skiaSceneHost!.append(overlay); _activeCompositionOrder.add(viewId); } _compositionOrder.clear(); @@ -361,13 +361,13 @@ class HtmlViewEmbedder { return; } - for (int viewId in _viewsToDispose) { - final html.Element rootView = _rootViews[viewId]; + for (int? viewId in _viewsToDispose) { + final html.Element rootView = _rootViews[viewId]!; rootView.remove(); _views.remove(viewId); _rootViews.remove(viewId); if (_overlays[viewId] != null) { - final Overlay overlay = _overlays[viewId]; + final Overlay overlay = _overlays[viewId]!; overlay.surface.htmlElement?.remove(); } _overlays.remove(viewId); @@ -379,12 +379,12 @@ class HtmlViewEmbedder { } void ensureOverlayInitialized(int viewId) { - Overlay overlay = _overlays[viewId]; + Overlay? overlay = _overlays[viewId]; if (overlay != null) { return; } - Surface surface = Surface(); - SkSurface skSurface = surface.acquireRenderSurface(_frameSize); + Surface surface = Surface(this); + SkSurface? skSurface = surface.acquireRenderSurface(_frameSize); _overlays[viewId] = Overlay(surface, skSurface); } } @@ -435,11 +435,11 @@ class Mutator { ); final MutatorType type; - final ui.Rect rect; - final ui.RRect rrect; - final ui.Path path; - final Matrix4 matrix; - final int alpha; + final ui.Rect? rect; + final ui.RRect? rrect; + final ui.Path? path; + final Matrix4? matrix; + final int? alpha; const Mutator.clipRect(ui.Rect rect) : this._(MutatorType.clipRect, rect, null, null, null, null); @@ -457,7 +457,7 @@ class Mutator { type == MutatorType.clipRRect || type == MutatorType.clipPath; - double get alphaFloat => alpha / 255.0; + double get alphaFloat => alpha! / 255.0; bool operator ==(dynamic other) { if (identical(this, other)) { @@ -555,7 +555,7 @@ class MutatorsStack extends Iterable { /// Represents a surface overlaying a platform view. class Overlay { final Surface surface; - final SkSurface skSurface; + final SkSurface? skSurface; Overlay(this.surface, this.skSurface); } diff --git a/lib/web_ui/lib/src/engine/compositor/fonts.dart b/lib/web_ui/lib/src/engine/compositor/fonts.dart index 0d913b0de4a09..1bce459d2207e 100644 --- a/lib/web_ui/lib/src/engine/compositor/fonts.dart +++ b/lib/web_ui/lib/src/engine/compositor/fonts.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; // This URL was found by using the Google Fonts Developer API to find the URL @@ -16,11 +16,11 @@ const String _robotoUrl = /// Manages the fonts used in the Skia-based backend. class SkiaFontCollection { /// Fonts that have been registered but haven't been loaded yet. - final List> _unloadedFonts = + final List> _unloadedFonts = >[]; /// Fonts which have been registered and loaded. - final List<_RegisteredFont> _registeredFonts = <_RegisteredFont>[]; + final List<_RegisteredFont?> _registeredFonts = <_RegisteredFont?>[]; /// A mapping from the name a font was registered with, to the family name /// embedded in the font's bytes (the font's "actual" name). @@ -32,14 +32,14 @@ class SkiaFontCollection { /// must convert them to their actual family name when we pass them to Skia. final Map fontFamilyOverrides = {}; - final Set registeredFamilies = {}; + final Set registeredFamilies = {}; Future ensureFontsLoaded() async { await _loadFonts(); _computeFontFamilyOverrides(); final List fontBuffers = - _registeredFonts.map((f) => f.bytes).toList(); + _registeredFonts.map((f) => f!.bytes).toList(); skFontMgr = canvasKit['SkFontMgr'].callMethod('FromData', fontBuffers); } @@ -51,7 +51,7 @@ class SkiaFontCollection { return; } - final List<_RegisteredFont> loadedFonts = await Future.wait(_unloadedFonts); + final List<_RegisteredFont?> loadedFonts = await Future.wait(_unloadedFonts); _registeredFonts.addAll(loadedFonts.where((x) => x != null)); _unloadedFonts.clear(); } @@ -59,8 +59,8 @@ class SkiaFontCollection { void _computeFontFamilyOverrides() { fontFamilyOverrides.clear(); - for (_RegisteredFont font in _registeredFonts) { - if (fontFamilyOverrides.containsKey(font.flutterFamily)) { + for (_RegisteredFont? font in _registeredFonts) { + if (fontFamilyOverrides.containsKey(font!.flutterFamily)) { if (fontFamilyOverrides[font.flutterFamily] != font.actualFamily) { html.window.console.warn('Fonts in family ${font.flutterFamily} ' 'have different actual family names.'); @@ -74,8 +74,8 @@ class SkiaFontCollection { } } - Future loadFontFromList(Uint8List list, {String fontFamily}) async { - String actualFamily = _readActualFamilyName(list); + Future loadFontFromList(Uint8List list, {String? fontFamily}) async { + String? actualFamily = _readActualFamilyName(list); if (actualFamily == null) { if (fontFamily == null) { @@ -111,20 +111,15 @@ class SkiaFontCollection { } } - if (byteData == null) { - throw AssertionError( - 'There was a problem trying to load FontManifest.json'); - } - - final List fontManifest = + final List? fontManifest = json.decode(utf8.decode(byteData.buffer.asUint8List())); if (fontManifest == null) { throw AssertionError( 'There was a problem trying to load FontManifest.json'); } - for (Map fontFamily in fontManifest) { - final String family = fontFamily['family']; + for (Map fontFamily in fontManifest.cast>()) { + final String? family = fontFamily['family']; final List fontAssets = fontFamily['fonts']; registeredFamilies.add(family); @@ -146,10 +141,10 @@ class SkiaFontCollection { } } - Future<_RegisteredFont> _registerFont(String url, String family) async { + Future<_RegisteredFont?> _registerFont(String url, String? family) async { ByteBuffer buffer; try { - buffer = await html.window.fetch(url).then(_getArrayBuffer); + buffer = await html.window.fetch(url).then(_getArrayBuffer as FutureOr Function(dynamic)); } catch (e) { html.window.console.warn('Failed to load font $family at $url'); html.window.console.warn(e); @@ -157,7 +152,7 @@ class SkiaFontCollection { } final Uint8List bytes = buffer.asUint8List(); - String actualFamily = _readActualFamilyName(bytes); + String? actualFamily = _readActualFamilyName(bytes); if (actualFamily == null) { html.window.console.warn('Failed to determine the actual name of the ' @@ -165,25 +160,25 @@ class SkiaFontCollection { actualFamily = family; } - return _RegisteredFont(bytes, family, actualFamily); + return _RegisteredFont(bytes, family!, actualFamily!); } - String _readActualFamilyName(Uint8List bytes) { + String? _readActualFamilyName(Uint8List bytes) { final js.JsObject tmpFontMgr = canvasKit['SkFontMgr'].callMethod('FromData', [bytes]); - String actualFamily = tmpFontMgr.callMethod('getFamilyName', [0]); + String? actualFamily = tmpFontMgr.callMethod('getFamilyName', [0]); tmpFontMgr.callMethod('delete'); return actualFamily; } - Future _getArrayBuffer(dynamic fetchResult) { + Future? _getArrayBuffer(dynamic fetchResult) { // TODO(yjbanov): fetchResult.arrayBuffer is a dynamic invocation. Clean it up. return fetchResult .arrayBuffer() .then((dynamic x) => x as ByteBuffer); } - js.JsObject skFontMgr; + js.JsObject? skFontMgr; } /// Represents a font that has been registered. @@ -198,7 +193,7 @@ class _RegisteredFont { final String actualFamily; _RegisteredFont(this.bytes, this.flutterFamily, this.actualFamily) - : assert(bytes != null), - assert(flutterFamily != null), - assert(actualFamily != null); + : assert(bytes != null), // ignore: unnecessary_null_comparison + assert(flutterFamily != null), // ignore: unnecessary_null_comparison + assert(actualFamily != null); // ignore: unnecessary_null_comparison } diff --git a/lib/web_ui/lib/src/engine/compositor/image.dart b/lib/web_ui/lib/src/engine/compositor/image.dart index 7816067269b85..a341aeb6c9c9a 100644 --- a/lib/web_ui/lib/src/engine/compositor/image.dart +++ b/lib/web_ui/lib/src/engine/compositor/image.dart @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Instantiates a [ui.Codec] backed by an `SkImage` from Skia. void skiaInstantiateImageCodec(Uint8List list, Callback callback, - [int width, int height, int format, int rowBytes]) { - final js.JsObject skAnimatedImage = + [int? width, int? height, int? format, int? rowBytes]) { + final js.JsObject? skAnimatedImage = canvasKit.callMethod('MakeAnimatedImageFromEncoded', [list]); final SkAnimatedImage animatedImage = SkAnimatedImage(skAnimatedImage); final SkAnimatedImageCodec codec = SkAnimatedImageCodec(animatedImage); @@ -17,36 +17,36 @@ void skiaInstantiateImageCodec(Uint8List list, Callback callback, /// A wrapper for `SkAnimatedImage`. class SkAnimatedImage implements ui.Image { - final js.JsObject _skAnimatedImage; + final js.JsObject? _skAnimatedImage; SkAnimatedImage(this._skAnimatedImage); @override void dispose() { - _skAnimatedImage.callMethod('delete'); + _skAnimatedImage!.callMethod('delete'); } - int get frameCount => _skAnimatedImage.callMethod('getFrameCount'); + int? get frameCount => _skAnimatedImage!.callMethod('getFrameCount'); /// Decodes the next frame and returns the frame duration. Duration decodeNextFrame() { - final int durationMillis = _skAnimatedImage.callMethod('decodeNextFrame'); + final int durationMillis = _skAnimatedImage!.callMethod('decodeNextFrame'); return Duration(milliseconds: durationMillis); } - int get repetitionCount => _skAnimatedImage.callMethod('getRepetitionCount'); + int? get repetitionCount => _skAnimatedImage!.callMethod('getRepetitionCount'); SkImage get currentFrameAsImage { - final js.JsObject _currentFrame = - _skAnimatedImage.callMethod('getCurrentFrame'); + final js.JsObject? _currentFrame = + _skAnimatedImage!.callMethod('getCurrentFrame'); return SkImage(_currentFrame); } @override - int get width => _skAnimatedImage.callMethod('width'); + int get width => _skAnimatedImage!.callMethod('width'); @override - int get height => _skAnimatedImage.callMethod('height'); + int get height => _skAnimatedImage!.callMethod('height'); @override Future toByteData( @@ -57,21 +57,21 @@ class SkAnimatedImage implements ui.Image { /// A [ui.Image] backed by an `SkImage` from Skia. class SkImage implements ui.Image { - js.JsObject skImage; + js.JsObject? skImage; SkImage(this.skImage); @override void dispose() { - skImage.callMethod('delete'); + skImage!.callMethod('delete'); skImage = null; } @override - int get width => skImage.callMethod('width'); + int get width => skImage!.callMethod('width'); @override - int get height => skImage.callMethod('height'); + int get height => skImage!.callMethod('height'); @override Future toByteData( @@ -82,26 +82,26 @@ class SkImage implements ui.Image { /// A [Codec] that wraps an `SkAnimatedImage`. class SkAnimatedImageCodec implements ui.Codec { - SkAnimatedImage animatedImage; + SkAnimatedImage? animatedImage; SkAnimatedImageCodec(this.animatedImage); @override void dispose() { - animatedImage.dispose(); + animatedImage!.dispose(); animatedImage = null; } @override - int get frameCount => animatedImage.frameCount; + int get frameCount => animatedImage!.frameCount!; @override - int get repetitionCount => animatedImage.repetitionCount; + int get repetitionCount => animatedImage!.repetitionCount!; @override Future getNextFrame() { - final Duration duration = animatedImage.decodeNextFrame(); - final SkImage image = animatedImage.currentFrameAsImage; + final Duration duration = animatedImage!.decodeNextFrame(); + final SkImage image = animatedImage!.currentFrameAsImage; return Future.value(AnimatedImageFrameInfo(duration, image)); } } diff --git a/lib/web_ui/lib/src/engine/compositor/image_filter.dart b/lib/web_ui/lib/src/engine/compositor/image_filter.dart index 8ea97082a2e10..79cc64abadf1d 100644 --- a/lib/web_ui/lib/src/engine/compositor/image_filter.dart +++ b/lib/web_ui/lib/src/engine/compositor/image_filter.dart @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// The CanvasKit implementation of [ui.ImageFilter]. /// /// Currently only supports `blur`. class SkImageFilter implements ui.ImageFilter { - js.JsObject skImageFilter; + js.JsObject? skImageFilter; SkImageFilter.blur({double sigmaX = 0.0, double sigmaY = 0.0}) : _sigmaX = sigmaX, diff --git a/lib/web_ui/lib/src/engine/compositor/initialization.dart b/lib/web_ui/lib/src/engine/compositor/initialization.dart index 1499ffb49bdbd..0052f5c9bfd5a 100644 --- a/lib/web_ui/lib/src/engine/compositor/initialization.dart +++ b/lib/web_ui/lib/src/engine/compositor/initialization.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// EXPERIMENTAL: Enable the Skia-based rendering backend. @@ -21,8 +21,8 @@ const String canvasKitBaseUrl = 'https://unpkg.com/canvaskit-wasm@0.16.2/bin/'; /// This calls `CanvasKitInit` and assigns the global [canvasKit] object. Future initializeSkia() { final Completer canvasKitCompleter = Completer(); - StreamSubscription loadSubscription; - loadSubscription = domRenderer.canvasKitScript.onLoad.listen((_) { + late StreamSubscription loadSubscription; + loadSubscription = domRenderer.canvasKitScript!.onLoad.listen((_) { loadSubscription.cancel(); final js.JsObject canvasKitInitArgs = js.JsObject.jsify({ 'locateFile': (String file, String unusedBase) => canvasKitBaseUrl + file, @@ -46,15 +46,16 @@ Future initializeSkia() { /// The entrypoint into all CanvasKit functions and classes. /// /// This is created by [initializeSkia]. -js.JsObject canvasKit; +late js.JsObject canvasKit; /// The Skia font collection. -SkiaFontCollection skiaFontCollection; +SkiaFontCollection get skiaFontCollection => _skiaFontCollection!; +SkiaFontCollection? _skiaFontCollection; /// Initializes [skiaFontCollection]. void ensureSkiaFontCollectionInitialized() { - skiaFontCollection ??= SkiaFontCollection(); + _skiaFontCollection ??= SkiaFontCollection(); } /// The scene host, where the root canvas and overlay canvases are added to. -html.Element skiaSceneHost; +html.Element? skiaSceneHost; diff --git a/lib/web_ui/lib/src/engine/compositor/layer.dart b/lib/web_ui/lib/src/engine/compositor/layer.dart index d30dc573a16b2..db70bbcab48a2 100644 --- a/lib/web_ui/lib/src/engine/compositor/layer.dart +++ b/lib/web_ui/lib/src/engine/compositor/layer.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A layer to be composed into a scene. @@ -11,7 +11,7 @@ part of engine; /// painting command. abstract class Layer implements ui.EngineLayer { /// The layer that contains us as a child. - ContainerLayer parent; + ContainerLayer? parent; /// An estimated rectangle that this layer will draw into. ui.Rect paintBounds = ui.Rect.zero; @@ -33,10 +33,10 @@ abstract class Layer implements ui.EngineLayer { /// A context shared by all layers during the preroll pass. class PrerollContext { /// A raster cache. Used to register candidates for caching. - final RasterCache rasterCache; + final RasterCache? rasterCache; /// A compositor for embedded HTML views. - final HtmlViewEmbedder viewEmbedder; + final HtmlViewEmbedder? viewEmbedder; final MutatorsStack mutatorsStack = MutatorsStack(); @@ -51,13 +51,13 @@ class PaintContext { SkNWayCanvas internalNodesCanvas; /// The canvas for leaf nodes to paint to. - SkCanvas leafNodesCanvas; + SkCanvas? leafNodesCanvas; /// A raster cache potentially containing pre-rendered pictures. - final RasterCache rasterCache; + final RasterCache? rasterCache; /// A compositor for embedded HTML views. - final HtmlViewEmbedder viewEmbedder; + final HtmlViewEmbedder? viewEmbedder; PaintContext( this.internalNodesCanvas, @@ -207,7 +207,7 @@ class ClipRectLayer extends ContainerLayer { class ClipRRectLayer extends ContainerLayer { /// The rounded rectangle used to clip child layers. final ui.RRect _clipRRect; - final ui.Clip _clipBehavior; + final ui.Clip? _clipBehavior; ClipRRectLayer(this._clipRRect, this._clipBehavior) : assert(_clipBehavior != ui.Clip.none); @@ -379,19 +379,19 @@ class PictureLayer extends Layer { @override void preroll(PrerollContext prerollContext, Matrix4 matrix) { - paintBounds = picture.cullRect.shift(offset); + paintBounds = picture.cullRect!.shift(offset); } @override void paint(PaintContext paintContext) { - assert(picture != null); + assert(picture != null); // ignore: unnecessary_null_comparison assert(needsPainting); - paintContext.leafNodesCanvas.save(); - paintContext.leafNodesCanvas.translate(offset.dx, offset.dy); + paintContext.leafNodesCanvas!.save(); + paintContext.leafNodesCanvas!.translate(offset.dx, offset.dy); - paintContext.leafNodesCanvas.drawPicture(picture); - paintContext.leafNodesCanvas.restore(); + paintContext.leafNodesCanvas!.drawPicture(picture); + paintContext.leafNodesCanvas!.restore(); } } @@ -401,10 +401,10 @@ class PictureLayer extends Layer { /// on the given elevation. class PhysicalShapeLayer extends ContainerLayer implements ui.PhysicalShapeEngineLayer { - final double _elevation; - final ui.Color _color; - final ui.Color _shadowColor; - final ui.Path _path; + final double? _elevation; + final ui.Color? _color; + final ui.Color? _shadowColor; + final ui.Path? _path; final ui.Clip _clipBehavior; PhysicalShapeLayer( @@ -419,7 +419,7 @@ class PhysicalShapeLayer extends ContainerLayer void preroll(PrerollContext prerollContext, Matrix4 matrix) { prerollChildren(prerollContext, matrix); - paintBounds = _path.getBounds(); + paintBounds = _path!.getBounds(); if (_elevation == 0.0) { // No need to extend the paint bounds if there is no shadow. return; @@ -479,16 +479,16 @@ class PhysicalShapeLayer extends ContainerLayer assert(needsPainting); if (_elevation != 0) { - drawShadow(paintContext.leafNodesCanvas, _path, _shadowColor, _elevation, - _color.alpha != 0xff); + drawShadow(paintContext.leafNodesCanvas!, _path!, _shadowColor!, _elevation!, + _color!.alpha != 0xff); } - final ui.Paint paint = ui.Paint()..color = _color; + final ui.Paint paint = ui.Paint()..color = _color!; if (_clipBehavior != ui.Clip.antiAliasWithSaveLayer) { - paintContext.leafNodesCanvas.drawPath(_path, paint); + paintContext.leafNodesCanvas!.drawPath(_path!, paint as SkPaint); } - final int saveCount = paintContext.internalNodesCanvas.save(); + final int? saveCount = paintContext.internalNodesCanvas.save(); switch (_clipBehavior) { case ui.Clip.hardEdge: paintContext.internalNodesCanvas.clipPath(_path, false); @@ -509,7 +509,7 @@ class PhysicalShapeLayer extends ContainerLayer // (https://github.com/flutter/flutter/issues/18057#issue-328003931) // using saveLayer, we have to call drawPaint instead of drawPath as // anti-aliased drawPath will always have such artifacts. - paintContext.leafNodesCanvas.drawPaint(paint); + paintContext.leafNodesCanvas!.drawPaint(paint as SkPaint); } paintChildren(paintContext); @@ -539,7 +539,7 @@ class PlatformViewLayer extends Layer { @override void preroll(PrerollContext context, Matrix4 matrix) { paintBounds = ui.Rect.fromLTWH(offset.dx, offset.dy, width, height); - context.viewEmbedder.prerollCompositeEmbeddedView( + context.viewEmbedder!.prerollCompositeEmbeddedView( viewId, EmbeddedViewParams( offset, @@ -551,7 +551,7 @@ class PlatformViewLayer extends Layer { @override void paint(PaintContext context) { - SkCanvas canvas = context.viewEmbedder.compositeEmbeddedView(viewId); + SkCanvas? canvas = context.viewEmbedder!.compositeEmbeddedView(viewId); context.leafNodesCanvas = canvas; } } diff --git a/lib/web_ui/lib/src/engine/compositor/layer_scene_builder.dart b/lib/web_ui/lib/src/engine/compositor/layer_scene_builder.dart index 64c0ac8802eaf..e7377b915a68b 100644 --- a/lib/web_ui/lib/src/engine/compositor/layer_scene_builder.dart +++ b/lib/web_ui/lib/src/engine/compositor/layer_scene_builder.dart @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; class LayerScene implements ui.Scene { final LayerTree layerTree; - LayerScene(Layer rootLayer) : layerTree = LayerTree() { + LayerScene(Layer? rootLayer) : layerTree = LayerTree() { layerTree.rootLayer = rootLayer; } @@ -16,21 +16,21 @@ class LayerScene implements ui.Scene { void dispose() {} @override - Future toImage(int width, int height) => null; - - html.Element get webOnlyRootElement => null; + Future toImage(int width, int height) { + throw UnsupportedError('LayerScene.toImage not implemented.'); + } } class LayerSceneBuilder implements ui.SceneBuilder { - Layer rootLayer; - ContainerLayer currentLayer; + Layer? rootLayer; + ContainerLayer? currentLayer; @override void addChildScene({ ui.Offset offset = ui.Offset.zero, double width = 0.0, double height = 0.0, - ui.SceneHost sceneHost, + ui.SceneHost? sceneHost, bool hitTestable = true, }) { throw UnimplementedError(); @@ -49,7 +49,7 @@ class LayerSceneBuilder implements ui.SceneBuilder { bool isComplexHint = false, bool willChangeHint = false, }) { - currentLayer.add(PictureLayer(picture, offset, isComplexHint, willChangeHint)); + currentLayer!.add(PictureLayer(picture as SkPicture, offset, isComplexHint, willChangeHint)); } @override @@ -57,7 +57,7 @@ class LayerSceneBuilder implements ui.SceneBuilder { if (currentLayer == null) { return; } - currentLayer.add(retainedLayer); + currentLayer!.add(retainedLayer as Layer); } @override @@ -78,9 +78,9 @@ class LayerSceneBuilder implements ui.SceneBuilder { ui.Offset offset = ui.Offset.zero, double width = 0.0, double height = 0.0, - Object webOnlyPaintedBy, + Object? webOnlyPaintedBy, }) { - currentLayer.add(PlatformViewLayer(viewId, offset, width, height)); + currentLayer!.add(PlatformViewLayer(viewId, offset, width, height)); } @override @@ -93,43 +93,43 @@ class LayerSceneBuilder implements ui.SceneBuilder { if (currentLayer == null) { return; } - currentLayer = currentLayer.parent; + currentLayer = currentLayer!.parent; } @override - ui.BackdropFilterEngineLayer pushBackdropFilter( + ui.BackdropFilterEngineLayer? pushBackdropFilter( ui.ImageFilter filter, { - ui.EngineLayer oldLayer, + ui.EngineLayer? oldLayer, }) { pushLayer(BackdropFilterLayer(filter)); return null; } @override - ui.ClipPathEngineLayer pushClipPath( + ui.ClipPathEngineLayer? pushClipPath( ui.Path path, { ui.Clip clipBehavior = ui.Clip.antiAlias, - ui.EngineLayer oldLayer, + ui.EngineLayer? oldLayer, }) { pushLayer(ClipPathLayer(path, clipBehavior)); return null; } @override - ui.ClipRRectEngineLayer pushClipRRect( + ui.ClipRRectEngineLayer? pushClipRRect( ui.RRect rrect, { - ui.Clip clipBehavior, - ui.EngineLayer oldLayer, + ui.Clip? clipBehavior, + ui.EngineLayer? oldLayer, }) { pushLayer(ClipRRectLayer(rrect, clipBehavior)); return null; } @override - ui.ClipRectEngineLayer pushClipRect( + ui.ClipRectEngineLayer? pushClipRect( ui.Rect rect, { ui.Clip clipBehavior = ui.Clip.antiAlias, - ui.EngineLayer oldLayer, + ui.EngineLayer? oldLayer, }) { pushLayer(ClipRectLayer(rect, clipBehavior)); return null; @@ -138,17 +138,17 @@ class LayerSceneBuilder implements ui.SceneBuilder { @override ui.ColorFilterEngineLayer pushColorFilter( ui.ColorFilter filter, { - ui.ColorFilterEngineLayer oldLayer, + ui.ColorFilterEngineLayer? oldLayer, }) { - assert(filter != null); + assert(filter != null); // ignore: unnecessary_null_comparison throw UnimplementedError(); } - ui.ImageFilterEngineLayer pushImageFilter( + ui.ImageFilterEngineLayer? pushImageFilter( ui.ImageFilter filter, { - ui.ImageFilterEngineLayer oldLayer, + ui.ImageFilterEngineLayer? oldLayer, }) { - assert(filter != null); + assert(filter != null); // ignore: unnecessary_null_comparison pushLayer(ImageFilterLayer(filter)); return null; } @@ -157,7 +157,7 @@ class LayerSceneBuilder implements ui.SceneBuilder { ui.OffsetEngineLayer pushOffset( double dx, double dy, { - ui.EngineLayer oldLayer, + ui.EngineLayer? oldLayer, }) { final Matrix4 matrix = Matrix4.translationValues(dx, dy, 0.0); final TransformLayer layer = TransformLayer(matrix); @@ -168,7 +168,7 @@ class LayerSceneBuilder implements ui.SceneBuilder { @override ui.OpacityEngineLayer pushOpacity( int alpha, { - ui.EngineLayer oldLayer, + ui.EngineLayer? oldLayer, ui.Offset offset = ui.Offset.zero, }) { final OpacityLayer layer = OpacityLayer(alpha, offset); @@ -178,12 +178,12 @@ class LayerSceneBuilder implements ui.SceneBuilder { @override ui.PhysicalShapeEngineLayer pushPhysicalShape({ - ui.Path path, - double elevation, - ui.Color color, - ui.Color shadowColor, + required ui.Path path, + required double elevation, + required ui.Color color, + ui.Color? shadowColor, ui.Clip clipBehavior = ui.Clip.none, - ui.EngineLayer oldLayer, + ui.EngineLayer? oldLayer, }) { final PhysicalShapeLayer layer = PhysicalShapeLayer(elevation, color, shadowColor, path, clipBehavior); @@ -196,15 +196,15 @@ class LayerSceneBuilder implements ui.SceneBuilder { ui.Shader shader, ui.Rect maskRect, ui.BlendMode blendMode, { - ui.EngineLayer oldLayer, + ui.EngineLayer? oldLayer, }) { throw UnimplementedError(); } @override - ui.TransformEngineLayer pushTransform( + ui.TransformEngineLayer? pushTransform( Float64List matrix4, { - ui.EngineLayer oldLayer, + ui.EngineLayer? oldLayer, }) { final Matrix4 matrix = Matrix4.fromFloat32List(toMatrix32(matrix4)); pushLayer(TransformLayer(matrix)); @@ -236,7 +236,7 @@ class LayerSceneBuilder implements ui.SceneBuilder { return; } - currentLayer.add(layer); + currentLayer!.add(layer); currentLayer = layer; } diff --git a/lib/web_ui/lib/src/engine/compositor/layer_tree.dart b/lib/web_ui/lib/src/engine/compositor/layer_tree.dart index 4d9ec292982e2..00243469dcac5 100644 --- a/lib/web_ui/lib/src/engine/compositor/layer_tree.dart +++ b/lib/web_ui/lib/src/engine/compositor/layer_tree.dart @@ -2,19 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A tree of [Layer]s that, together with a [Size] compose a frame. class LayerTree { /// The root of the layer tree. - Layer rootLayer; + Layer? rootLayer; /// The size (in physical pixels) of the frame to paint this layer tree into. - ui.Size frameSize; + final ui.Size frameSize = _computeFrameSize(); /// The devicePixelRatio of the frame to paint this layer tree into. - double devicePixelRatio; + double? devicePixelRatio; /// Performs a preroll phase before painting the layer tree. /// @@ -27,7 +27,7 @@ class LayerTree { ignoreRasterCache ? null : frame.rasterCache, frame.viewEmbedder, ); - rootLayer.preroll(context, Matrix4.identity()); + rootLayer!.preroll(context, Matrix4.identity()); } /// Paints the layer tree into the given [frame]. @@ -37,8 +37,8 @@ class LayerTree { void paint(Frame frame, {bool ignoreRasterCache = false}) { final SkNWayCanvas internalNodesCanvas = SkNWayCanvas(); internalNodesCanvas.addCanvas(frame.canvas); - final List overlayCanvases = - frame.viewEmbedder.getCurrentCanvases(); + final List overlayCanvases = + frame.viewEmbedder!.getCurrentCanvases(); for (int i = 0; i < overlayCanvases.length; i++) { internalNodesCanvas.addCanvas(overlayCanvases[i]); } @@ -48,22 +48,30 @@ class LayerTree { ignoreRasterCache ? null : frame.rasterCache, frame.viewEmbedder, ); - if (rootLayer.needsPainting) { - rootLayer.paint(context); + if (rootLayer!.needsPainting) { + rootLayer!.paint(context); } } } +ui.Size _computeFrameSize() { + final ui.Size physicalSize = ui.window.physicalSize; + return ui.Size( + physicalSize.width.truncate().toDouble(), + physicalSize.height.truncate().toDouble(), + ); +} + /// A single frame to be rendered. class Frame { /// The canvas to render this frame to. final SkCanvas canvas; /// A cache of pre-rastered pictures. - final RasterCache rasterCache; + final RasterCache? rasterCache; /// The platform view embedder. - final HtmlViewEmbedder viewEmbedder; + final HtmlViewEmbedder? viewEmbedder; Frame(this.canvas, this.rasterCache, this.viewEmbedder); @@ -82,10 +90,10 @@ class Frame { /// The state of the compositor, which is persisted between frames. class CompositorContext { /// A cache of pictures, which is shared between successive frames. - RasterCache rasterCache; + RasterCache? rasterCache; /// Acquire a frame using this compositor's settings. - Frame acquireFrame(SkCanvas canvas, HtmlViewEmbedder viewEmbedder) { + Frame acquireFrame(SkCanvas canvas, HtmlViewEmbedder? viewEmbedder) { return Frame(canvas, rasterCache, viewEmbedder); } } diff --git a/lib/web_ui/lib/src/engine/compositor/n_way_canvas.dart b/lib/web_ui/lib/src/engine/compositor/n_way_canvas.dart index b0ca17ae0f526..e351c2e66591a 100644 --- a/lib/web_ui/lib/src/engine/compositor/n_way_canvas.dart +++ b/lib/web_ui/lib/src/engine/compositor/n_way_canvas.dart @@ -2,86 +2,86 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A virtual canvas that applies operations to multiple canvases at once. class SkNWayCanvas { - final List _canvases = []; + final List _canvases = []; - void addCanvas(SkCanvas canvas) { + void addCanvas(SkCanvas? canvas) { _canvases.add(canvas); } /// Calls [save] on all canvases. - int save() { - int saveCount; + int? save() { + int? saveCount; for (int i = 0; i < _canvases.length; i++) { - saveCount = _canvases[i].save(); + saveCount = _canvases[i]!.save(); } return saveCount; } /// Calls [saveLayer] on all canvases. - void saveLayer(ui.Rect bounds, ui.Paint paint) { + void saveLayer(ui.Rect bounds, ui.Paint? paint) { for (int i = 0; i < _canvases.length; i++) { - _canvases[i].saveLayer(bounds, paint); + _canvases[i]!.saveLayer(bounds, paint as SkPaint); } } /// Calls [saveLayerWithFilter] on all canvases. void saveLayerWithFilter(ui.Rect bounds, ui.ImageFilter filter) { for (int i = 0; i < _canvases.length; i++) { - _canvases[i].saveLayerWithFilter(bounds, filter); + _canvases[i]!.saveLayerWithFilter(bounds, filter); } } /// Calls [restore] on all canvases. void restore() { for (int i = 0; i < _canvases.length; i++) { - _canvases[i].restore(); + _canvases[i]!.restore(); } } /// Calls [restoreToCount] on all canvases. - void restoreToCount(int count) { + void restoreToCount(int? count) { for (int i = 0; i < _canvases.length; i++) { - _canvases[i].restoreToCount(count); + _canvases[i]!.restoreToCount(count); } } /// Calls [translate] on all canvases. void translate(double dx, double dy) { for (int i = 0; i < _canvases.length; i++) { - _canvases[i].translate(dx, dy); + _canvases[i]!.translate(dx, dy); } } /// Calls [transform] on all canvases. - void transform(Float32List matrix) { + void transform(Float32List? matrix) { for (int i = 0; i < _canvases.length; i++) { - _canvases[i].transform(matrix); + _canvases[i]!.transform(matrix); } } /// Calls [clipPath] on all canvases. - void clipPath(ui.Path path, bool doAntiAlias) { + void clipPath(ui.Path? path, bool doAntiAlias) { for (int i = 0; i < _canvases.length; i++) { - _canvases[i].clipPath(path, doAntiAlias); + _canvases[i]!.clipPath(path!, doAntiAlias); } } /// Calls [clipRect] on all canvases. void clipRect(ui.Rect rect, ui.ClipOp clipOp, bool doAntiAlias) { for (int i = 0; i < _canvases.length; i++) { - _canvases[i].clipRect(rect, clipOp, doAntiAlias); + _canvases[i]!.clipRect(rect, clipOp, doAntiAlias); } } /// Calls [clipRRect] on all canvases. void clipRRect(ui.RRect rrect, bool doAntiAlias) { for (int i = 0; i < _canvases.length; i++) { - _canvases[i].clipRRect(rrect, doAntiAlias); + _canvases[i]!.clipRRect(rrect, doAntiAlias); } } } diff --git a/lib/web_ui/lib/src/engine/compositor/painting.dart b/lib/web_ui/lib/src/engine/compositor/painting.dart index 203e8662de6b6..1010018bf7f92 100644 --- a/lib/web_ui/lib/src/engine/compositor/painting.dart +++ b/lib/web_ui/lib/src/engine/compositor/painting.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// The implementation of [ui.Paint] used by the CanvasKit backend. @@ -13,21 +13,21 @@ class SkPaint extends SkiaObject implements ui.Paint { SkPaint(); static const ui.Color _defaultPaintColor = ui.Color(0xFF000000); - static final js.JsObject _skPaintStyleStroke = + static final js.JsObject? _skPaintStyleStroke = canvasKit['PaintStyle']['Stroke']; - static final js.JsObject _skPaintStyleFill = canvasKit['PaintStyle']['Fill']; + static final js.JsObject? _skPaintStyleFill = canvasKit['PaintStyle']['Fill']; @override ui.BlendMode get blendMode => _blendMode; @override set blendMode(ui.BlendMode value) { _blendMode = value; - _syncBlendMode(skiaObject); + _syncBlendMode(skiaObject!); } void _syncBlendMode(js.JsObject object) { - final js.JsObject skBlendMode = makeSkBlendMode(_blendMode); - object.callMethod('setBlendMode', [skBlendMode]); + final js.JsObject? skBlendMode = makeSkBlendMode(_blendMode); + object.callMethod('setBlendMode', [skBlendMode]); } ui.BlendMode _blendMode = ui.BlendMode.srcOver; @@ -41,8 +41,8 @@ class SkPaint extends SkiaObject implements ui.Paint { _syncStyle(skiaObject); } - void _syncStyle(js.JsObject object) { - js.JsObject skPaintStyle; + void _syncStyle(js.JsObject? object) { + js.JsObject? skPaintStyle; switch (_style) { case ui.PaintingStyle.stroke: skPaintStyle = _skPaintStyleStroke; @@ -51,7 +51,7 @@ class SkPaint extends SkiaObject implements ui.Paint { skPaintStyle = _skPaintStyleFill; break; } - object.callMethod('setStyle', [skPaintStyle]); + object!.callMethod('setStyle', [skPaintStyle]); } ui.PaintingStyle _style = ui.PaintingStyle.fill; @@ -61,7 +61,7 @@ class SkPaint extends SkiaObject implements ui.Paint { @override set strokeWidth(double value) { _strokeWidth = value; - _syncStrokeWidth(skiaObject); + _syncStrokeWidth(skiaObject!); } void _syncStrokeWidth(js.JsObject object) { @@ -95,7 +95,7 @@ class SkPaint extends SkiaObject implements ui.Paint { @override set isAntiAlias(bool value) { _isAntiAlias = value; - _syncAntiAlias(skiaObject); + _syncAntiAlias(skiaObject!); } void _syncAntiAlias(js.JsObject object) { @@ -109,16 +109,12 @@ class SkPaint extends SkiaObject implements ui.Paint { @override set color(ui.Color value) { _color = value; - _syncColor(skiaObject); + _syncColor(skiaObject!); } void _syncColor(js.JsObject object) { - ui.Color colorValue = _defaultPaintColor; - if (_color != null) { - colorValue = _color; - } object.callMethod('setColorInt', [ - colorValue.value, + _color.value, ]); } @@ -135,38 +131,38 @@ class SkPaint extends SkiaObject implements ui.Paint { bool _invertColors = false; @override - ui.Shader get shader => _shader as ui.Shader; + ui.Shader? get shader => _shader as ui.Shader?; @override - set shader(ui.Shader value) { - _shader = value as EngineShader; - _syncShader(skiaObject); + set shader(ui.Shader? value) { + _shader = value as EngineShader?; + _syncShader(skiaObject!); } void _syncShader(js.JsObject object) { - js.JsObject skShader; + js.JsObject? skShader; if (_shader != null) { - skShader = _shader.createSkiaShader(); + skShader = _shader!.createSkiaShader(); } - object.callMethod('setShader', [skShader]); + object.callMethod('setShader', [skShader]); } - EngineShader _shader; + EngineShader? _shader; @override - ui.MaskFilter get maskFilter => _maskFilter; + ui.MaskFilter? get maskFilter => _maskFilter; @override - set maskFilter(ui.MaskFilter value) { + set maskFilter(ui.MaskFilter? value) { _maskFilter = value; _syncMaskFilter(skiaObject); } - void _syncMaskFilter(js.JsObject object) { - js.JsObject skMaskFilter; + void _syncMaskFilter(js.JsObject? object) { + js.JsObject? skMaskFilter; if (_maskFilter != null) { - final ui.BlurStyle blurStyle = _maskFilter.webOnlyBlurStyle; - final double sigma = _maskFilter.webOnlySigma; + final ui.BlurStyle blurStyle = _maskFilter!.webOnlyBlurStyle; + final double sigma = _maskFilter!.webOnlySigma; - js.JsObject skBlurStyle; + js.JsObject? skBlurStyle; switch (blurStyle) { case ui.BlurStyle.normal: skBlurStyle = canvasKit['BlurStyle']['Normal']; @@ -185,10 +181,10 @@ class SkPaint extends SkiaObject implements ui.Paint { skMaskFilter = canvasKit.callMethod( 'MakeBlurMaskFilter', [skBlurStyle, sigma, true]); } - object.callMethod('setMaskFilter', [skMaskFilter]); + object!.callMethod('setMaskFilter', [skMaskFilter]); } - ui.MaskFilter _maskFilter; + ui.MaskFilter? _maskFilter; @override ui.FilterQuality get filterQuality => _filterQuality; @@ -198,8 +194,8 @@ class SkPaint extends SkiaObject implements ui.Paint { _syncFilterQuality(skiaObject); } - void _syncFilterQuality(js.JsObject object) { - js.JsObject skFilterQuality; + void _syncFilterQuality(js.JsObject? object) { + js.JsObject? skFilterQuality; switch (_filterQuality) { case ui.FilterQuality.none: skFilterQuality = canvasKit['FilterQuality']['None']; @@ -214,29 +210,29 @@ class SkPaint extends SkiaObject implements ui.Paint { skFilterQuality = canvasKit['FilterQuality']['High']; break; } - object.callMethod('setFilterQuality', [skFilterQuality]); + object!.callMethod('setFilterQuality', [skFilterQuality]); } ui.FilterQuality _filterQuality = ui.FilterQuality.none; @override - ui.ColorFilter get colorFilter => _colorFilter; + ui.ColorFilter? get colorFilter => _colorFilter; @override - set colorFilter(ui.ColorFilter value) { - _colorFilter = value; - _syncColorFilter(skiaObject); + set colorFilter(ui.ColorFilter? value) { + _colorFilter = value as EngineColorFilter?; + _syncColorFilter(skiaObject!); } void _syncColorFilter(js.JsObject object) { - js.JsObject skColorFilterJs; + js.JsObject? skColorFilterJs; if (_colorFilter != null) { - SkColorFilter skFilter = _colorFilter._toSkColorFilter(); + SkColorFilter skFilter = _colorFilter!._toSkColorFilter()!; skColorFilterJs = skFilter.skColorFilter; } - object.callMethod('setColorFilter', [skColorFilterJs]); + object.callMethod('setColorFilter', [skColorFilterJs]); } - EngineColorFilter _colorFilter; + EngineColorFilter? _colorFilter; // TODO(yjbanov): implement @override @@ -249,22 +245,22 @@ class SkPaint extends SkiaObject implements ui.Paint { double _strokeMiterLimit = 0.0; @override - ui.ImageFilter get imageFilter => _imageFilter; + ui.ImageFilter? get imageFilter => _imageFilter; @override - set imageFilter(ui.ImageFilter value) { - _imageFilter = value; - _syncImageFilter(skiaObject); + set imageFilter(ui.ImageFilter? value) { + _imageFilter = value as SkImageFilter?; + _syncImageFilter(skiaObject!); } void _syncImageFilter(js.JsObject object) { - js.JsObject imageFilterJs; + js.JsObject? imageFilterJs; if (_imageFilter != null) { - imageFilterJs = _imageFilter.skImageFilter; + imageFilterJs = _imageFilter!.skImageFilter; } - object.callMethod('setImageFilter', [imageFilterJs]); + object.callMethod('setImageFilter', [imageFilterJs]); } - SkImageFilter _imageFilter; + SkImageFilter? _imageFilter; @override js.JsObject createDefault() { diff --git a/lib/web_ui/lib/src/engine/compositor/path.dart b/lib/web_ui/lib/src/engine/compositor/path.dart index 1cc98e0e9c9a8..51755321c0e07 100644 --- a/lib/web_ui/lib/src/engine/compositor/path.dart +++ b/lib/web_ui/lib/src/engine/compositor/path.dart @@ -2,32 +2,32 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// An implementation of [ui.Path] which is backed by an `SkPath`. /// /// The `SkPath` is required for `SkCanvas` methods which take a path. class SkPath implements ui.Path { - js.JsObject _skPath; + js.JsObject? _skPath; /// Cached constructor function for `SkPath`, so we don't have to look it up /// every time we construct a new path. - static final js.JsFunction _skPathConstructor = canvasKit['SkPath']; + static final js.JsFunction? _skPathConstructor = canvasKit['SkPath']; SkPath() { - _skPath = js.JsObject(_skPathConstructor); + _skPath = js.JsObject(_skPathConstructor!); fillType = ui.PathFillType.nonZero; } SkPath.from(SkPath other) { - _skPath = js.JsObject(_skPathConstructor, [other._skPath]); + _skPath = js.JsObject(_skPathConstructor!, [other._skPath]); fillType = other.fillType; } - SkPath._fromSkPath(js.JsObject skPath) : _skPath = skPath; + SkPath._fromSkPath(js.JsObject? skPath) : _skPath = skPath; - ui.PathFillType _fillType; + late ui.PathFillType _fillType; @override ui.PathFillType get fillType => _fillType; @@ -36,7 +36,7 @@ class SkPath implements ui.Path { set fillType(ui.PathFillType newFillType) { _fillType = newFillType; - js.JsObject skFillType; + js.JsObject? skFillType; switch (newFillType) { case ui.PathFillType.nonZero: skFillType = canvasKit['FillType']['Winding']; @@ -46,13 +46,13 @@ class SkPath implements ui.Path { break; } - _skPath.callMethod('setFillType', [skFillType]); + _skPath!.callMethod('setFillType', [skFillType]); } @override void addArc(ui.Rect oval, double startAngle, double sweepAngle) { const double toDegrees = 180.0 / math.pi; - _skPath.callMethod('addArc', [ + _skPath!.callMethod('addArc', [ makeSkRect(oval), startAngle * toDegrees, sweepAngle * toDegrees, @@ -61,11 +61,11 @@ class SkPath implements ui.Path { @override void addOval(ui.Rect oval) { - _skPath.callMethod('addOval', [makeSkRect(oval), false, 1]); + _skPath!.callMethod('addOval', [makeSkRect(oval), false, 1]); } @override - void addPath(ui.Path path, ui.Offset offset, {Float64List matrix4}) { + void addPath(ui.Path path, ui.Offset offset, {Float64List? matrix4}) { List skMatrix; if (matrix4 == null) { skMatrix = makeSkMatrixFromFloat32( @@ -75,8 +75,8 @@ class SkPath implements ui.Path { skMatrix[2] += offset.dx; skMatrix[5] += offset.dy; } - final SkPath otherPath = path; - _skPath.callMethod('addPath', [ + final SkPath otherPath = path as SkPath; + _skPath!.callMethod('addPath', [ otherPath._skPath, skMatrix[0], skMatrix[1], @@ -93,10 +93,10 @@ class SkPath implements ui.Path { @override void addPolygon(List points, bool close) { - assert(points != null); + assert(points != null); // ignore: unnecessary_null_comparison // TODO(hterkelsen): https://github.com/flutter/flutter/issues/58824 - final List> encodedPoints = encodePointList(points); - _skPath.callMethod('addPoly', [encodedPoints, close]); + final List>? encodedPoints = encodePointList(points); + _skPath!.callMethod('addPoly', [encodedPoints, close]); } @override @@ -112,20 +112,20 @@ class SkPath implements ui.Path { rrect.blRadiusX, rrect.blRadiusY, ]; - _skPath.callMethod('addRoundRect', + _skPath!.callMethod('addRoundRect', [skRect, js.JsArray.from(radii), false]); } @override void addRect(ui.Rect rect) { - _skPath.callMethod('addRect', [makeSkRect(rect)]); + _skPath!.callMethod('addRect', [makeSkRect(rect)]); } @override void arcTo( ui.Rect rect, double startAngle, double sweepAngle, bool forceMoveTo) { const double toDegrees = 180.0 / math.pi; - _skPath.callMethod('arcTo', [ + _skPath!.callMethod('arcTo', [ makeSkRect(rect), startAngle * toDegrees, sweepAngle * toDegrees, @@ -139,7 +139,7 @@ class SkPath implements ui.Path { double rotation = 0.0, bool largeArc = false, bool clockwise = true}) { - _skPath.callMethod('arcTo', [ + _skPath!.callMethod('arcTo', [ radius.x, radius.y, rotation, @@ -152,7 +152,7 @@ class SkPath implements ui.Path { @override void close() { - _skPath.callMethod('close'); + _skPath!.callMethod('close'); } @override @@ -162,22 +162,22 @@ class SkPath implements ui.Path { @override void conicTo(double x1, double y1, double x2, double y2, double w) { - _skPath.callMethod('conicTo', [x1, y1, x2, y2, w]); + _skPath!.callMethod('conicTo', [x1, y1, x2, y2, w]); } @override bool contains(ui.Offset point) { - return _skPath.callMethod('contains', [point.dx, point.dy]); + return _skPath!.callMethod('contains', [point.dx, point.dy]); } @override void cubicTo( double x1, double y1, double x2, double y2, double x3, double y3) { - _skPath.callMethod('cubicTo', [x1, y1, x2, y2, x3, y3]); + _skPath!.callMethod('cubicTo', [x1, y1, x2, y2, x3, y3]); } @override - void extendWithPath(ui.Path path, ui.Offset offset, {Float64List matrix4}) { + void extendWithPath(ui.Path path, ui.Offset offset, {Float64List? matrix4}) { List skMatrix; if (matrix4 == null) { skMatrix = makeSkMatrixFromFloat32( @@ -187,8 +187,8 @@ class SkPath implements ui.Path { skMatrix[2] += offset.dx; skMatrix[5] += offset.dy; } - final SkPath otherPath = path; - _skPath.callMethod('addPath', [ + final SkPath otherPath = path as SkPath; + _skPath!.callMethod('addPath', [ otherPath._skPath, skMatrix[0], skMatrix[1], @@ -205,23 +205,23 @@ class SkPath implements ui.Path { @override ui.Rect getBounds() { - final js.JsObject bounds = _skPath.callMethod('getBounds'); + final js.JsObject bounds = _skPath!.callMethod('getBounds'); return fromSkRect(bounds); } @override void lineTo(double x, double y) { - _skPath.callMethod('lineTo', [x, y]); + _skPath!.callMethod('lineTo', [x, y]); } @override void moveTo(double x, double y) { - _skPath.callMethod('moveTo', [x, y]); + _skPath!.callMethod('moveTo', [x, y]); } @override void quadraticBezierTo(double x1, double y1, double x2, double y2) { - _skPath.callMethod('quadTo', [x1, y1, x2, y2]); + _skPath!.callMethod('quadTo', [x1, y1, x2, y2]); } @override @@ -230,7 +230,7 @@ class SkPath implements ui.Path { double rotation = 0.0, bool largeArc = false, bool clockwise = true}) { - _skPath.callMethod('rArcTo', [ + _skPath!.callMethod('rArcTo', [ radius.x, radius.y, rotation, @@ -243,40 +243,40 @@ class SkPath implements ui.Path { @override void relativeConicTo(double x1, double y1, double x2, double y2, double w) { - _skPath.callMethod('rConicTo', [x1, y1, x2, y2, w]); + _skPath!.callMethod('rConicTo', [x1, y1, x2, y2, w]); } @override void relativeCubicTo( double x1, double y1, double x2, double y2, double x3, double y3) { - _skPath.callMethod('rCubicTo', [x1, y1, x2, y2, x3, y3]); + _skPath!.callMethod('rCubicTo', [x1, y1, x2, y2, x3, y3]); } @override void relativeLineTo(double dx, double dy) { - _skPath.callMethod('rLineTo', [dx, dy]); + _skPath!.callMethod('rLineTo', [dx, dy]); } @override void relativeMoveTo(double dx, double dy) { - _skPath.callMethod('rMoveTo', [dx, dy]); + _skPath!.callMethod('rMoveTo', [dx, dy]); } @override void relativeQuadraticBezierTo(double x1, double y1, double x2, double y2) { - _skPath.callMethod('rQuadTo', [x1, y1, x2, y2]); + _skPath!.callMethod('rQuadTo', [x1, y1, x2, y2]); } @override void reset() { - _skPath.callMethod('reset'); + _skPath!.callMethod('reset'); } @override ui.Path shift(ui.Offset offset) { // Since CanvasKit does not expose `SkPath.offset`, create a copy of this // path and call `transform` on it. - final js.JsObject newPath = _skPath.callMethod('copy'); + final js.JsObject newPath = _skPath!.callMethod('copy'); newPath.callMethod('transform', [1.0, 0.0, offset.dx, 0.0, 1.0, offset.dy, 0.0, 0.0, 0.0]); return SkPath._fromSkPath(newPath); @@ -287,9 +287,9 @@ class SkPath implements ui.Path { ui.Path uiPath1, ui.Path uiPath2, ) { - final SkPath path1 = uiPath1; - final SkPath path2 = uiPath2; - js.JsObject pathOp; + final SkPath path1 = uiPath1 as SkPath; + final SkPath path2 = uiPath2 as SkPath; + js.JsObject? pathOp; switch (operation) { case ui.PathOperation.difference: pathOp = canvasKit['PathOp']['Difference']; @@ -307,9 +307,9 @@ class SkPath implements ui.Path { pathOp = canvasKit['PathOp']['ReverseDifference']; break; } - final js.JsObject newPath = canvasKit.callMethod( + final js.JsObject? newPath = canvasKit.callMethod( 'MakePathFromOp', - [ + [ path1._skPath, path2._skPath, pathOp, @@ -320,17 +320,17 @@ class SkPath implements ui.Path { @override ui.Path transform(Float64List matrix4) { - final js.JsObject newPath = _skPath.callMethod('copy'); + final js.JsObject newPath = _skPath!.callMethod('copy'); newPath.callMethod('transform', [makeSkMatrixFromFloat64(matrix4)]); return SkPath._fromSkPath(newPath); } - String toSvgString() { - return _skPath.callMethod('toSVGString'); + String? toSvgString() { + return _skPath!.callMethod('toSVGString'); } /// Return `true` if this path contains no segments. - bool get isEmpty { - return _skPath.callMethod('isEmpty'); + bool? get isEmpty { + return _skPath!.callMethod('isEmpty'); } } diff --git a/lib/web_ui/lib/src/engine/compositor/path_metrics.dart b/lib/web_ui/lib/src/engine/compositor/path_metrics.dart index 0913544bdbd23..f42ccf222eeb5 100644 --- a/lib/web_ui/lib/src/engine/compositor/path_metrics.dart +++ b/lib/web_ui/lib/src/engine/compositor/path_metrics.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 part of engine; class SkPathMetrics extends IterableBase @@ -14,16 +13,16 @@ class SkPathMetrics extends IterableBase /// The [SkPath.isEmpty] case is special-cased to avoid booting the WASM machinery just to find out there are no contours. @override - Iterator get iterator => _path.isEmpty ? const SkPathMetricIteratorEmpty._() : SkContourMeasureIter(_path, _forceClosed); + Iterator get iterator => _path.isEmpty! ? const SkPathMetricIteratorEmpty._() : SkContourMeasureIter(_path, _forceClosed); } class SkContourMeasureIter implements Iterator { /// Cached constructor function for `SkContourMeasureIter`, so we don't have to look it /// up every time we're constructing a new instance. - static final js.JsFunction _skContourMeasureIterConstructor = canvasKit['SkContourMeasureIter']; + static final js.JsFunction? _skContourMeasureIterConstructor = canvasKit['SkContourMeasureIter']; SkContourMeasureIter(SkPath path, bool forceClosed) - : _skObject = js.JsObject(_skContourMeasureIterConstructor, [ + : _skObject = js.JsObject(_skContourMeasureIterConstructor!, [ path._skPath, forceClosed, 1, @@ -38,12 +37,22 @@ class SkContourMeasureIter implements Iterator { int _contourIndexCounter = 0; @override - ui.PathMetric get current => _current; - SkContourMeasure _current; + ui.PathMetric get current { + final ui.PathMetric? currentMetric = _current; + if (currentMetric == null) { + throw RangeError( + 'PathMetricIterator is not pointing to a PathMetric. This can happen in two situations:\n' + '- The iteration has not started yet. If so, call "moveNext" to start iteration.' + '- The iterator ran out of elements. If so, check that "moveNext" returns true prior to calling "current".' + ); + } + return currentMetric; + } + SkContourMeasure? _current; @override bool moveNext() { - final js.JsObject skContourMeasure = _skObject.callMethod('next'); + final js.JsObject? skContourMeasure = _skObject.callMethod('next'); if (skContourMeasure == null) { _current = null; return false; @@ -65,7 +74,7 @@ class SkContourMeasure implements ui.PathMetric { @override ui.Path extractPath(double start, double end, {bool startWithMoveTo = true}) { - final js.JsObject skPath = _skObject + final js.JsObject? skPath = _skObject .callMethod('getSegment', [start, end, startWithMoveTo]); return SkPath._fromSkPath(skPath); } @@ -94,7 +103,9 @@ class SkPathMetricIteratorEmpty implements Iterator { const SkPathMetricIteratorEmpty._(); @override - ui.PathMetric get current => null; + ui.PathMetric get current { + throw RangeError('PathMetric iterator is empty.'); + } @override bool moveNext() { diff --git a/lib/web_ui/lib/src/engine/compositor/picture.dart b/lib/web_ui/lib/src/engine/compositor/picture.dart index e627d19d9fb0c..817f9b187a761 100644 --- a/lib/web_ui/lib/src/engine/compositor/picture.dart +++ b/lib/web_ui/lib/src/engine/compositor/picture.dart @@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 part of engine; class SkPicture implements ui.Picture { - final js.JsObject skPicture; - final ui.Rect cullRect; + final js.JsObject? skPicture; + final ui.Rect? cullRect; SkPicture(this.skPicture, this.cullRect); @@ -21,7 +20,6 @@ class SkPicture implements ui.Picture { @override Future toImage(int width, int height) { - // TODO: implement toImage - return null; + throw UnsupportedError('Picture.toImage not yet implemented for CanvasKit and HTML'); } } diff --git a/lib/web_ui/lib/src/engine/compositor/picture_recorder.dart b/lib/web_ui/lib/src/engine/compositor/picture_recorder.dart index 81a9163d6b800..15722eee3e557 100644 --- a/lib/web_ui/lib/src/engine/compositor/picture_recorder.dart +++ b/lib/web_ui/lib/src/engine/compositor/picture_recorder.dart @@ -2,32 +2,32 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; class SkPictureRecorder implements ui.PictureRecorder { - ui.Rect _cullRect; - js.JsObject _recorder; - SkCanvas _recordingCanvas; + ui.Rect? _cullRect; + js.JsObject? _recorder; + SkCanvas? _recordingCanvas; - SkCanvas beginRecording(ui.Rect bounds) { + SkCanvas? beginRecording(ui.Rect bounds) { _cullRect = bounds; _recorder = js.JsObject(canvasKit['SkPictureRecorder']); final js.JsObject skRect = js.JsObject(canvasKit['LTRBRect'], [bounds.left, bounds.top, bounds.right, bounds.bottom]); - final js.JsObject/*!*/ skCanvas = - _recorder.callMethod('beginRecording', [skRect]); + final js.JsObject skCanvas = + _recorder!.callMethod('beginRecording', [skRect]); _recordingCanvas = SkCanvas(skCanvas); return _recordingCanvas; } - SkCanvas get recordingCanvas => _recordingCanvas; + SkCanvas? get recordingCanvas => _recordingCanvas; @override ui.Picture endRecording() { - final js.JsObject skPicture = - _recorder.callMethod('finishRecordingAsPicture'); - _recorder.callMethod('delete'); + final js.JsObject? skPicture = + _recorder!.callMethod('finishRecordingAsPicture'); + _recorder!.callMethod('delete'); _recorder = null; return SkPicture(skPicture, _cullRect); } diff --git a/lib/web_ui/lib/src/engine/compositor/platform_message.dart b/lib/web_ui/lib/src/engine/compositor/platform_message.dart index 0b925e368b554..f7f1228241e8d 100644 --- a/lib/web_ui/lib/src/engine/compositor/platform_message.dart +++ b/lib/web_ui/lib/src/engine/compositor/platform_message.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; class PlatformMessage { diff --git a/lib/web_ui/lib/src/engine/compositor/raster_cache.dart b/lib/web_ui/lib/src/engine/compositor/raster_cache.dart index 764129e10a99e..14f8fa954a10b 100644 --- a/lib/web_ui/lib/src/engine/compositor/raster_cache.dart +++ b/lib/web_ui/lib/src/engine/compositor/raster_cache.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A cache of [Picture]s that have already been rasterized. diff --git a/lib/web_ui/lib/src/engine/compositor/rasterizer.dart b/lib/web_ui/lib/src/engine/compositor/rasterizer.dart index af9df107f1deb..9cebae49be9ca 100644 --- a/lib/web_ui/lib/src/engine/compositor/rasterizer.dart +++ b/lib/web_ui/lib/src/engine/compositor/rasterizer.dart @@ -2,38 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A class that can rasterize [LayerTree]s into a given [Surface]. class Rasterizer { final Surface surface; final CompositorContext context = CompositorContext(); - final HtmlViewEmbedder viewEmbedder = HtmlViewEmbedder(); final List _postFrameCallbacks = []; - Rasterizer(this.surface) { - surface.viewEmbedder = viewEmbedder; - } + Rasterizer(this.surface); /// Creates a new frame from this rasterizer's surface, draws the given /// [LayerTree] into it, and then submits the frame. void draw(LayerTree layerTree) { try { - if (layerTree == null) { - return; - } - - final ui.Size physicalSize = ui.window.physicalSize; - final ui.Size frameSize = ui.Size( - physicalSize.width.truncate().toDouble(), - physicalSize.height.truncate().toDouble(), - ); - - if (frameSize.isEmpty) { + if (layerTree.frameSize.isEmpty) { + // Available drawing area is empty. Skip drawing. return; } - layerTree.frameSize = frameSize; final SurfaceFrame frame = surface.acquireFrame(layerTree.frameSize); surface.viewEmbedder.frameSize = layerTree.frameSize; diff --git a/lib/web_ui/lib/src/engine/compositor/surface.dart b/lib/web_ui/lib/src/engine/compositor/surface.dart index 38ad4606d0188..9d54f37adfae2 100644 --- a/lib/web_ui/lib/src/engine/compositor/surface.dart +++ b/lib/web_ui/lib/src/engine/compositor/surface.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 part of engine; typedef SubmitCallback = bool Function(SurfaceFrame, SkCanvas); @@ -15,7 +14,8 @@ class SurfaceFrame { SurfaceFrame(this.skiaSurface, this.submitCallback) : _submitted = false, - assert(submitCallback != null); + assert(skiaSurface != null), // ignore: unnecessary_null_comparison + assert(submitCallback != null); // ignore: unnecessary_null_comparison /// Submit this frame to be drawn. bool submit() { @@ -25,7 +25,7 @@ class SurfaceFrame { return submitCallback(this, skiaCanvas); } - SkCanvas get skiaCanvas => skiaSurface?.getCanvas(); + SkCanvas get skiaCanvas => skiaSurface.getCanvas(); } /// A surface which can be drawn into by the compositor. @@ -34,76 +34,67 @@ class SurfaceFrame { /// successive frames if they are the same size. Otherwise, a new [SkSurface] is /// created. class Surface { - SkSurface _surface; - html.Element htmlElement; + Surface(this.viewEmbedder); + + SkSurface? _surface; + html.Element? htmlElement; bool _addedToScene = false; /// The default view embedder. Coordinates embedding platform views and /// overlaying subsequent draw operations on top. - HtmlViewEmbedder viewEmbedder; + final HtmlViewEmbedder viewEmbedder; /// Acquire a frame of the given [size] containing a drawable canvas. /// /// The given [size] is in physical pixels. SurfaceFrame acquireFrame(ui.Size size) { final SkSurface surface = acquireRenderSurface(size); - canvasKit.callMethod('setCurrentContext', [surface.context]); - - if (surface == null) { - return null; - } + canvasKit.callMethod('setCurrentContext', [surface.context]); SubmitCallback submitCallback = (SurfaceFrame surfaceFrame, SkCanvas canvas) { - return _presentSurface(canvas); + return _presentSurface(); }; return SurfaceFrame(surface, submitCallback); } SkSurface acquireRenderSurface(ui.Size size) { - if (!_createOrUpdateSurfaces(size)) { - return null; - } - return _surface; + _createOrUpdateSurfaces(size); + return _surface!; } void addToScene() { if (!_addedToScene) { - skiaSceneHost.children.insert(0, htmlElement); + skiaSceneHost!.children.insert(0, htmlElement!); } _addedToScene = true; } - bool _createOrUpdateSurfaces(ui.Size size) { - if (_surface != null && - size == - ui.Size( - _surface.width().toDouble(), - _surface.height().toDouble(), - )) { - return true; + void _createOrUpdateSurfaces(ui.Size size) { + if (size.isEmpty) { + throw CanvasKitError('Cannot create surfaces of empty size.'); + } + + final SkSurface? currentSurface = _surface; + if (currentSurface != null) { + final bool isSameSize = + size.width == currentSurface.width() && + size.height == currentSurface.height(); + if (isSameSize) { + // The existing surface is still reusable. + return; + } } - _surface?.dispose(); + currentSurface?.dispose(); _surface = null; htmlElement?.remove(); htmlElement = null; _addedToScene = false; - if (size.isEmpty) { - html.window.console.error('Cannot create surfaces of empty size.'); - return false; - } _surface = _wrapHtmlCanvas(size); - - if (_surface == null) { - html.window.console.error('Could not create a surface.'); - return false; - } - - return true; } SkSurface _wrapHtmlCanvas(ui.Size size) { @@ -120,9 +111,14 @@ class Surface { // anti-aliased by setting their `Paint` object's `antialias` property. js.JsObject.jsify({'antialias': 0}), ]); - final js.JsObject grContext = + final js.JsObject? grContext = canvasKit.callMethod('MakeGrContext', [glContext]); - final js.JsObject skSurface = + + if (grContext == null) { + throw CanvasKitError('Could not create a graphics context.'); + } + + final js.JsObject? skSurface = canvasKit.callMethod('MakeOnScreenGLSurface', [ grContext, size.width, @@ -130,22 +126,17 @@ class Surface { canvasKit['SkColorSpace']['SRGB'], ]); - htmlElement = htmlCanvas; - if (skSurface == null) { - return null; - } else { - return SkSurface(skSurface, glContext); + throw CanvasKitError('Could not create a surface.'); } - } - bool _presentSurface(SkCanvas canvas) { - if (canvas == null) { - return false; - } + htmlElement = htmlCanvas; + return SkSurface(skSurface, glContext); + } - canvasKit.callMethod('setCurrentContext', [_surface.context]); - _surface.getCanvas().flush(); + bool _presentSurface() { + canvasKit.callMethod('setCurrentContext', [_surface!.context]); + _surface!.getCanvas().flush(); return true; } } @@ -158,7 +149,7 @@ class SkSurface { SkSurface(this._surface, this._glContext); SkCanvas getCanvas() { - final js.JsObject/*!*/ skCanvas = _surface.callMethod('getCanvas'); + final js.JsObject skCanvas = _surface.callMethod('getCanvas'); return SkCanvas(skCanvas); } diff --git a/lib/web_ui/lib/src/engine/compositor/text.dart b/lib/web_ui/lib/src/engine/compositor/text.dart index 1e53d0e0cbbf2..8b8be4914c500 100644 --- a/lib/web_ui/lib/src/engine/compositor/text.dart +++ b/lib/web_ui/lib/src/engine/compositor/text.dart @@ -1,23 +1,23 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; class SkParagraphStyle implements ui.ParagraphStyle { SkParagraphStyle({ - ui.TextAlign textAlign, - ui.TextDirection textDirection, - int maxLines, - String fontFamily, - double fontSize, - double height, - ui.TextHeightBehavior textHeightBehavior, - ui.FontWeight fontWeight, - ui.FontStyle fontStyle, - ui.StrutStyle strutStyle, - String ellipsis, - ui.Locale locale, + ui.TextAlign? textAlign, + ui.TextDirection? textDirection, + int? maxLines, + String? fontFamily, + double? fontSize, + double? height, + ui.TextHeightBehavior? textHeightBehavior, + ui.FontWeight? fontWeight, + ui.FontStyle? fontStyle, + ui.StrutStyle? strutStyle, + String? ellipsis, + ui.Locale? locale, }) { skParagraphStyle = toSkParagraphStyle( textAlign, @@ -36,15 +36,15 @@ class SkParagraphStyle implements ui.ParagraphStyle { _fontFamily = fontFamily; } - js.JsObject skParagraphStyle; - ui.TextDirection _textDirection; - String _fontFamily; + js.JsObject? skParagraphStyle; + ui.TextDirection? _textDirection; + String? _fontFamily; static Map toSkTextStyle( - String fontFamily, - double fontSize, - ui.FontWeight fontWeight, - ui.FontStyle fontStyle, + String? fontFamily, + double? fontSize, + ui.FontWeight? fontWeight, + ui.FontStyle? fontStyle, ) { final Map skTextStyle = {}; if (fontWeight != null || fontStyle != null) { @@ -67,17 +67,17 @@ class SkParagraphStyle implements ui.ParagraphStyle { return skTextStyle; } - static js.JsObject toSkParagraphStyle( - ui.TextAlign textAlign, - ui.TextDirection textDirection, - int maxLines, - String fontFamily, - double fontSize, - double height, - ui.TextHeightBehavior textHeightBehavior, - ui.FontWeight fontWeight, - ui.FontStyle fontStyle, - String ellipsis, + static js.JsObject? toSkParagraphStyle( + ui.TextAlign? textAlign, + ui.TextDirection? textDirection, + int? maxLines, + String? fontFamily, + double? fontSize, + double? height, + ui.TextHeightBehavior? textHeightBehavior, + ui.FontWeight? fontWeight, + ui.FontStyle? fontStyle, + String? ellipsis, ) { final Map skParagraphStyle = {}; @@ -140,28 +140,28 @@ class SkParagraphStyle implements ui.ParagraphStyle { } class SkTextStyle implements ui.TextStyle { - js.JsObject skTextStyle; + js.JsObject? skTextStyle; SkTextStyle({ - ui.Color color, - ui.TextDecoration decoration, - ui.Color decorationColor, - ui.TextDecorationStyle decorationStyle, - double decorationThickness, - ui.FontWeight fontWeight, - ui.FontStyle fontStyle, - ui.TextBaseline textBaseline, - String fontFamily, - List fontFamilyFallback, - double fontSize, - double letterSpacing, - double wordSpacing, - double height, - ui.Locale locale, - SkPaint background, - SkPaint foreground, - List shadows, - List fontFeatures, + ui.Color? color, + ui.TextDecoration? decoration, + ui.Color? decorationColor, + ui.TextDecorationStyle? decorationStyle, + double? decorationThickness, + ui.FontWeight? fontWeight, + ui.FontStyle? fontStyle, + ui.TextBaseline? textBaseline, + String? fontFamily, + List? fontFamilyFallback, + double? fontSize, + double? letterSpacing, + double? wordSpacing, + double? height, + ui.Locale? locale, + SkPaint? background, + SkPaint? foreground, + List? shadows, + List? fontFeatures, }) { final js.JsObject style = js.JsObject(js.context['Object']); @@ -203,7 +203,7 @@ class SkTextStyle implements ui.TextStyle { if (skiaFontCollection.fontFamilyOverrides.containsKey(fontFamily)) { fontFamily = skiaFontCollection.fontFamilyOverrides[fontFamily]; } - List fontFamilies = [fontFamily]; + List fontFamilies = [fontFamily]; if (fontFamilyFallback != null && !fontFamilyFallback.every((font) => fontFamily == font)) { fontFamilies.addAll(fontFamilyFallback); @@ -234,9 +234,9 @@ class SkTextStyle implements ui.TextStyle { } } -Map toSkFontStyle( - ui.FontWeight fontWeight, ui.FontStyle fontStyle) { - Map style = {}; +Map toSkFontStyle( + ui.FontWeight? fontWeight, ui.FontStyle? fontStyle) { + Map style = {}; if (fontWeight != null) { switch (fontWeight) { case ui.FontWeight.w100: @@ -285,37 +285,37 @@ Map toSkFontStyle( class SkParagraph implements ui.Paragraph { SkParagraph(this.skParagraph, this._textDirection, this._fontFamily); - final js.JsObject skParagraph; - final ui.TextDirection _textDirection; - final String _fontFamily; + final js.JsObject? skParagraph; + final ui.TextDirection? _textDirection; + final String? _fontFamily; @override double get alphabeticBaseline => - skParagraph.callMethod('getAlphabeticBaseline'); + skParagraph!.callMethod('getAlphabeticBaseline'); @override - bool get didExceedMaxLines => skParagraph.callMethod('didExceedMaxLines'); + bool get didExceedMaxLines => skParagraph!.callMethod('didExceedMaxLines'); @override - double get height => skParagraph.callMethod('getHeight'); + double get height => skParagraph!.callMethod('getHeight'); @override double get ideographicBaseline => - skParagraph.callMethod('getIdeographicBaseline'); + skParagraph!.callMethod('getIdeographicBaseline'); @override - double get longestLine => skParagraph.callMethod('getLongestLine'); + double get longestLine => skParagraph!.callMethod('getLongestLine'); @override double get maxIntrinsicWidth => - skParagraph.callMethod('getMaxIntrinsicWidth'); + skParagraph!.callMethod('getMaxIntrinsicWidth'); @override double get minIntrinsicWidth => - skParagraph.callMethod('getMinIntrinsicWidth'); + skParagraph!.callMethod('getMinIntrinsicWidth'); @override - double get width => skParagraph.callMethod('getMaxWidth'); + double get width => skParagraph!.callMethod('getMaxWidth'); // TODO(hterkelsen): Implement placeholders once it's in CanvasKit @override @@ -334,7 +334,7 @@ class SkParagraph implements ui.Paragraph { return const []; } - js.JsObject heightStyle; + js.JsObject? heightStyle; switch (boxHeightStyle) { case ui.BoxHeightStyle.tight: heightStyle = canvasKit['RectHeightStyle']['Tight']; @@ -350,7 +350,7 @@ class SkParagraph implements ui.Paragraph { break; } - js.JsObject widthStyle; + js.JsObject? widthStyle; switch (boxWidthStyle) { case ui.BoxWidthStyle.tight: widthStyle = canvasKit['RectWidthStyle']['Tight']; @@ -361,24 +361,24 @@ class SkParagraph implements ui.Paragraph { } List skRects = - skParagraph.callMethod('getRectsForRange', [ + skParagraph!.callMethod('getRectsForRange', [ start, end, heightStyle, widthStyle, ]); - List result = List(skRects.length); + List result = []; for (int i = 0; i < skRects.length; i++) { final js.JsObject rect = skRects[i]; - result[i] = ui.TextBox.fromLTRBD( + result.add(ui.TextBox.fromLTRBD( rect['fLeft'], rect['fTop'], rect['fRight'], rect['fBottom'], - _textDirection, - ); + _textDirection!, + )); } return result; @@ -387,7 +387,7 @@ class SkParagraph implements ui.Paragraph { @override ui.TextPosition getPositionForOffset(ui.Offset offset) { js.JsObject positionWithAffinity = - skParagraph.callMethod('getGlyphPositionAtCoordinate', [ + skParagraph!.callMethod('getGlyphPositionAtCoordinate', [ offset.dx, offset.dy, ]); @@ -397,13 +397,13 @@ class SkParagraph implements ui.Paragraph { @override ui.TextRange getWordBoundary(ui.TextPosition position) { js.JsObject skRange = - skParagraph.callMethod('getWordBoundary', [position.offset]); + skParagraph!.callMethod('getWordBoundary', [position.offset]); return ui.TextRange(start: skRange['start'], end: skRange['end']); } @override void layout(ui.ParagraphConstraints constraints) { - assert(constraints.width != null); + assert(constraints.width != null); // ignore: unnecessary_null_comparison // 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 @@ -418,7 +418,7 @@ class SkParagraph implements ui.Paragraph { // TODO(het): CanvasKit throws an exception when laid out with // a font that wasn't registered. try { - skParagraph.callMethod('layout', [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'); @@ -440,17 +440,17 @@ class SkParagraph implements ui.Paragraph { } class SkParagraphBuilder implements ui.ParagraphBuilder { - js.JsObject _paragraphBuilder; - ui.TextDirection _textDirection; - String _fontFamily; + js.JsObject? _paragraphBuilder; + ui.TextDirection? _textDirection; + String? _fontFamily; SkParagraphBuilder(ui.ParagraphStyle style) { - SkParagraphStyle skStyle = style; + SkParagraphStyle skStyle = style as SkParagraphStyle; _textDirection = skStyle._textDirection; _fontFamily = skStyle._fontFamily; _paragraphBuilder = canvasKit['ParagraphBuilder'].callMethod( 'Make', - [ + [ skStyle.skParagraphStyle, skiaFontCollection.skFontMgr, ], @@ -464,22 +464,22 @@ class SkParagraphBuilder implements ui.ParagraphBuilder { double height, ui.PlaceholderAlignment alignment, { double scale = 1.0, - double baselineOffset, - ui.TextBaseline baseline, + double? baselineOffset, + ui.TextBaseline? baseline, }) { throw UnimplementedError('addPlaceholder'); } @override void addText(String text) { - _paragraphBuilder.callMethod('addText', [text]); + _paragraphBuilder!.callMethod('addText', [text]); } @override ui.Paragraph build() { final SkParagraph paragraph = SkParagraph( - _paragraphBuilder.callMethod('build'), _textDirection, _fontFamily); - _paragraphBuilder.callMethod('delete'); + _paragraphBuilder!.callMethod('build'), _textDirection, _fontFamily); + _paragraphBuilder!.callMethod('delete'); _paragraphBuilder = null; return paragraph; } @@ -493,13 +493,13 @@ class SkParagraphBuilder implements ui.ParagraphBuilder { @override void pop() { - _paragraphBuilder.callMethod('pop'); + _paragraphBuilder!.callMethod('pop'); } @override void pushStyle(ui.TextStyle style) { - final SkTextStyle skStyle = style; - _paragraphBuilder - .callMethod('pushStyle', [skStyle.skTextStyle]); + final SkTextStyle skStyle = style as SkTextStyle; + _paragraphBuilder! + .callMethod('pushStyle', [skStyle.skTextStyle]); } } diff --git a/lib/web_ui/lib/src/engine/compositor/util.dart b/lib/web_ui/lib/src/engine/compositor/util.dart index 008291cc2a849..0f140de94d150 100644 --- a/lib/web_ui/lib/src/engine/compositor/util.dart +++ b/lib/web_ui/lib/src/engine/compositor/util.dart @@ -2,9 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 part of engine; +/// An error related to the CanvasKit rendering backend. +class CanvasKitError extends Error { + CanvasKitError(this.message); + + /// Describes this error. + final String message; + + @override + String toString() => 'CanvasKitError: $message'; +} + /// An object backed by a [js.JsObject] mapped onto a Skia C++ object in the /// WebAssembly heap. /// @@ -36,7 +46,7 @@ abstract class SkiaObject { } /// The JavaScript object that's mapped onto a Skia C++ object in the WebAssembly heap. - js.JsObject get skiaObject { + js.JsObject? get skiaObject { if (_skiaObject == null) { _skiaObject = resurrect(); SkiaObjects.manage(this); @@ -45,7 +55,7 @@ abstract class SkiaObject { } /// Do not use this field outside this class. Use [skiaObject] instead. - js.JsObject _skiaObject; + js.JsObject? _skiaObject; /// Instantiates a new Skia-backed JavaScript object containing default /// values. @@ -66,7 +76,7 @@ class SkiaObjects { // beyond a single frame. @visibleForTesting static final List managedObjects = () { - window.rasterizer.addPostFrameCallback(postFrameCleanUp); + window.rasterizer!.addPostFrameCallback(postFrameCleanUp); return []; }(); @@ -88,7 +98,7 @@ class SkiaObjects { for (int i = 0; i < managedObjects.length; i++) { final SkiaObject object = managedObjects[i]; - object._skiaObject.callMethod('delete'); + object._skiaObject!.callMethod('delete'); object._skiaObject = null; } @@ -117,9 +127,9 @@ js.JsObject _mallocColorArray() { .callMethod('Malloc', [js.context['Float32Array'], 4]); } -js.JsObject sharedSkColor1; -js.JsObject sharedSkColor2; -js.JsObject sharedSkColor3; +js.JsObject? sharedSkColor1; +js.JsObject? sharedSkColor2; +js.JsObject? sharedSkColor3; void _setSharedColor(js.JsObject sharedColor, ui.Color color) { Float32List array = sharedColor.callMethod('toTypedArray'); @@ -133,21 +143,21 @@ void setSharedSkColor1(ui.Color color) { if (sharedSkColor1 == null) { sharedSkColor1 = _mallocColorArray(); } - _setSharedColor(sharedSkColor1, color); + _setSharedColor(sharedSkColor1!, color); } void setSharedSkColor2(ui.Color color) { if (sharedSkColor2 == null) { sharedSkColor2 = _mallocColorArray(); } - _setSharedColor(sharedSkColor2, color); + _setSharedColor(sharedSkColor2!, color); } void setSharedSkColor3(ui.Color color) { if (sharedSkColor3 == null) { sharedSkColor3 = _mallocColorArray(); } - _setSharedColor(sharedSkColor3, color); + _setSharedColor(sharedSkColor3!, color); } /// Creates a new color array. @@ -214,7 +224,7 @@ js.JsArray makeSkPoint(ui.Offset point) { // TODO(hterkelsen): https://github.com/flutter/flutter/issues/58824 /// Creates a point list using a 2D JS array. -js.JsArray> encodePointList(List points) { +js.JsArray>? encodePointList(List? points) { if (points == null) { return null; } @@ -236,7 +246,7 @@ js.JsArray> encodePointList(List points) { // TODO(hterkelsen): https://github.com/flutter/flutter/issues/58824 /// Creates a point list using a 2D JS array. -List> encodeRawPointList(Float32List points) { +List>? encodeRawPointList(Float32List? points) { if (points == null) { return null; } @@ -257,7 +267,7 @@ List> encodeRawPointList(Float32List points) { return result; } -js.JsObject makeSkPointMode(ui.PointMode pointMode) { +js.JsObject? makeSkPointMode(ui.PointMode pointMode) { switch (pointMode) { case ui.PointMode.points: return canvasKit['PointMode']['Points']; @@ -270,7 +280,7 @@ js.JsObject makeSkPointMode(ui.PointMode pointMode) { } } -js.JsObject makeSkBlendMode(ui.BlendMode blendMode) { +js.JsObject? makeSkBlendMode(ui.BlendMode? blendMode) { switch (blendMode) { case ui.BlendMode.clear: return canvasKit['BlendMode']['Clear']; @@ -344,12 +354,12 @@ const List _skMatrixIndexToMatrix4Index = [ /// Converts a 4x4 Flutter matrix (represented as a [Float32List]) to an /// SkMatrix, which is a 3x3 transform matrix. -js.JsArray makeSkMatrixFromFloat32(Float32List matrix4) { +js.JsArray makeSkMatrixFromFloat32(Float32List? matrix4) { final js.JsArray skMatrix = js.JsArray(); skMatrix.length = 9; for (int i = 0; i < 9; ++i) { final int matrix4Index = _skMatrixIndexToMatrix4Index[i]; - if (matrix4Index < matrix4.length) + if (matrix4Index < matrix4!.length) skMatrix[i] = matrix4[matrix4Index]; else skMatrix[i] = 0.0; @@ -382,7 +392,7 @@ final js.JsArray _kDefaultColorStops = () { /// Converts a list of color stops into a Skia-compatible JS array or color stops. /// /// In Flutter `null` means two color stops `[0, 1]` that in Skia must be specified explicitly. -js.JsArray makeSkiaColorStops(List colorStops) { +js.JsArray makeSkiaColorStops(List? colorStops) { if (colorStops == null) { return _kDefaultColorStops; } diff --git a/lib/web_ui/lib/src/engine/compositor/vertices.dart b/lib/web_ui/lib/src/engine/compositor/vertices.dart index f93308ee841e9..0c05dca49b28c 100644 --- a/lib/web_ui/lib/src/engine/compositor/vertices.dart +++ b/lib/web_ui/lib/src/engine/compositor/vertices.dart @@ -2,29 +2,29 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; js.JsArray _encodeRawColorList(Int32List rawColors) { final int colorCount = rawColors.length; - final List colors = List(colorCount); + final List colors = []; for (int i = 0; i < colorCount; ++i) { - colors[i] = ui.Color(rawColors[i]); + colors.add(ui.Color(rawColors[i])); } return makeColorList(colors); } class SkVertices implements ui.Vertices { - js.JsObject skVertices; + js.JsObject? skVertices; SkVertices( ui.VertexMode mode, List positions, { - List textureCoordinates, - List colors, - List indices, - }) : assert(mode != null), - assert(positions != null) { + List? textureCoordinates, + List? colors, + List? indices, + }) : assert(mode != null), // ignore: unnecessary_null_comparison + assert(positions != null) { // ignore: unnecessary_null_comparison if (textureCoordinates != null && textureCoordinates.length != positions.length) throw ArgumentError( @@ -36,10 +36,10 @@ class SkVertices implements ui.Vertices { throw ArgumentError( '"indices" values must be valid indices in the positions list.'); - final js.JsArray> encodedPositions = encodePointList(positions); - final js.JsArray> encodedTextures = + final js.JsArray>? encodedPositions = encodePointList(positions); + final js.JsArray>? encodedTextures = encodePointList(textureCoordinates); - final js.JsArray encodedColors = + final js.JsArray? encodedColors = colors != null ? makeColorList(colors) : null; if (!_init(mode, encodedPositions, encodedTextures, encodedColors, indices)) throw ArgumentError('Invalid configuration for vertices.'); @@ -48,11 +48,11 @@ class SkVertices implements ui.Vertices { SkVertices.raw( ui.VertexMode mode, Float32List positions, { - Float32List textureCoordinates, - Int32List colors, - Uint16List indices, - }) : assert(mode != null), - assert(positions != null) { + Float32List? textureCoordinates, + Int32List? colors, + Uint16List? indices, + }) : assert(mode != null), // ignore: unnecessary_null_comparison + assert(positions != null) { // ignore: unnecessary_null_comparison if (textureCoordinates != null && textureCoordinates.length != positions.length) throw ArgumentError( @@ -66,9 +66,9 @@ class SkVertices implements ui.Vertices { if (!_init( mode, - encodeRawPointList(positions), - encodeRawPointList(textureCoordinates), - _encodeRawColorList(colors), + encodeRawPointList(positions) as js.JsArray>?, + encodeRawPointList(textureCoordinates) as js.JsArray>?, + colors != null ? _encodeRawColorList(colors) : null, indices, )) { throw ArgumentError('Invalid configuration for vertices.'); @@ -77,11 +77,11 @@ class SkVertices implements ui.Vertices { bool _init( ui.VertexMode mode, - js.JsArray> positions, - js.JsArray> textureCoordinates, - js.JsArray colors, - List indices) { - js.JsObject skVertexMode; + js.JsArray>? positions, + js.JsArray>? textureCoordinates, + js.JsArray? colors, + List? indices) { + js.JsObject? skVertexMode; switch (mode) { case ui.VertexMode.triangles: skVertexMode = canvasKit['VertexMode']['Triangles']; @@ -94,7 +94,7 @@ class SkVertices implements ui.Vertices { break; } - final js.JsObject vertices = + final js.JsObject? vertices = canvasKit.callMethod('MakeSkVertices', [ skVertexMode, positions, diff --git a/lib/web_ui/lib/src/engine/compositor/viewport_metrics.dart b/lib/web_ui/lib/src/engine/compositor/viewport_metrics.dart index 13cd698db89a9..a36a9906566ff 100644 --- a/lib/web_ui/lib/src/engine/compositor/viewport_metrics.dart +++ b/lib/web_ui/lib/src/engine/compositor/viewport_metrics.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; class ViewportMetrics { diff --git a/lib/web_ui/lib/src/engine/conic.dart b/lib/web_ui/lib/src/engine/conic.dart index 5de3968c7431a..f964440518909 100644 --- a/lib/web_ui/lib/src/engine/conic.dart +++ b/lib/web_ui/lib/src/engine/conic.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Converts conic curve to a list of quadratic curves for rendering on @@ -40,10 +40,10 @@ class Conic { if (subdivideCount == _maxSubdivisionCount) { // We have an extreme number of quads, chop this conic and check if // it generates a pair of lines, in which case we should not subdivide. - final List dst = List(2); + final _ConicPair dst = _ConicPair(); _chop(dst); - final Conic conic0 = dst[0]; - final Conic conic1 = dst[1]; + final Conic conic0 = dst.first!; + final Conic conic1 = dst.second!; // If this chop generates pair of lines no need to subdivide. if (conic0.p1x == conic0.p2x && conic0.p1y == conic0.p2y && @@ -93,10 +93,10 @@ class Conic { pointList.add(ui.Offset(src.p2x, src.p2y)); return; } - final List dst = List(2); + final _ConicPair dst = _ConicPair(); src._chop(dst); - final Conic conic0 = dst[0]; - final Conic conic1 = dst[1]; + final Conic conic0 = dst.first!; + final Conic conic1 = dst.second!; final double startY = src.p0y; final double endY = src.p2y; final double cpY = src.p1y; @@ -135,7 +135,7 @@ class Conic { } // Splits conic into 2 parts based on weight. - void _chop(List dst) { + void _chop(_ConicPair pair) { final double scale = 1.0 / (1.0 + fW); final double newW = _subdivideWeightValue(fW); final ui.Offset wp1 = ui.Offset(fW * p1x, fW * p1y); @@ -147,9 +147,9 @@ class Conic { m = ui.Offset((p0x + (w2 * p1x) + p2x) * scaleHalf, (p0y + (w2 * p1y) + p2y) * scaleHalf); } - dst[0] = Conic(p0x, p0y, (p0x + wp1.dx) * scale, (p0y + wp1.dy) * scale, + pair.first = Conic(p0x, p0y, (p0x + wp1.dx) * scale, (p0y + wp1.dy) * scale, m.dx, m.dy, newW); - dst[1] = Conic(m.dx, m.dy, (p2x + wp1.dx) * scale, (p2y + wp1.dy) * scale, + pair.second = Conic(m.dx, m.dy, (p2x + wp1.dx) * scale, (p2y + wp1.dy) * scale, p2x, p2y, newW); } @@ -188,3 +188,8 @@ class Conic { return pow2; } } + +class _ConicPair { + Conic? first; + Conic? second; +} diff --git a/lib/web_ui/lib/src/engine/dom_canvas.dart b/lib/web_ui/lib/src/engine/dom_canvas.dart index 2ccb4b6aeb60c..1a106154314d2 100644 --- a/lib/web_ui/lib/src/engine/dom_canvas.dart +++ b/lib/web_ui/lib/src/engine/dom_canvas.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A canvas that renders to DOM elements and CSS properties. @@ -111,10 +111,10 @@ class DomCanvas extends EngineCanvas with SaveElementStackTracking { ..transform = effectiveTransform; final String cssColor = - paint.color == null ? '#000000' : colorToCssString(paint.color); + paint.color == null ? '#000000' : colorToCssString(paint.color)!; if (paint.maskFilter != null) { - style.filter = 'blur(${paint.maskFilter.webOnlySigma}px)'; + style.filter = 'blur(${paint.maskFilter!.webOnlySigma}px)'; } if (isStroke) { @@ -179,7 +179,7 @@ class DomCanvas extends EngineCanvas with SaveElementStackTracking { @override void drawParagraph(ui.Paragraph paragraph, ui.Offset offset) { final html.Element paragraphElement = - _drawParagraphElement(paragraph, offset, transform: currentTransform); + _drawParagraphElement(paragraph as EngineParagraph, offset, transform: currentTransform); currentElement.append(paragraphElement); } diff --git a/lib/web_ui/lib/src/engine/dom_renderer.dart b/lib/web_ui/lib/src/engine/dom_renderer.dart index a2d03c018b176..19fefdd89f3fe 100644 --- a/lib/web_ui/lib/src/engine/dom_renderer.dart +++ b/lib/web_ui/lib/src/engine/dom_renderer.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; class DomRenderer { @@ -32,22 +32,22 @@ class DomRenderer { const html.EventStreamProvider('languagechange'); /// Listens to window resize events. - StreamSubscription _resizeSubscription; + StreamSubscription? _resizeSubscription; /// Listens to window locale events. - StreamSubscription _localeSubscription; + StreamSubscription? _localeSubscription; /// Contains Flutter-specific CSS rules, such as default margins and /// paddings. - html.StyleElement _styleElement; + html.StyleElement? _styleElement; /// Configures the screen, such as scaling. - html.MetaElement _viewportMeta; + html.MetaElement? _viewportMeta; /// The canvaskit script, downloaded from a CDN. Only created if /// [experimentalUseSkia] is set to true. - html.ScriptElement get canvasKitScript => _canvasKitScript; - html.ScriptElement _canvasKitScript; + html.ScriptElement? get canvasKitScript => _canvasKitScript; + html.ScriptElement? _canvasKitScript; /// The element that contains the [sceneElement]. /// @@ -57,18 +57,18 @@ class DomRenderer { /// This element precedes the [glassPaneElement] so that it never receives /// input events. All input events are processed by [glassPaneElement] and the /// semantics tree. - html.Element get sceneHostElement => _sceneHostElement; - html.Element _sceneHostElement; + html.Element? get sceneHostElement => _sceneHostElement; + html.Element? _sceneHostElement; /// The last scene element rendered by the [render] method. - html.Element get sceneElement => _sceneElement; - html.Element _sceneElement; + html.Element? get sceneElement => _sceneElement; + html.Element? _sceneElement; /// This is state persistant across hot restarts that indicates what /// to clear. We delay removal of old visible state to make the /// transition appear smooth. static const String _staleHotRestartStore = '__flutter_state'; - List _staleHotRestartState; + List? _staleHotRestartState; /// Used to decide if the browser tab still has the focus. /// @@ -78,14 +78,14 @@ class DomRenderer { /// This getter calls the `hasFocus` method of the `Document` interface. /// See for more details: /// https://developer.mozilla.org/en-US/docs/Web/API/Document/hasFocus - bool get windowHasFocus => js_util.callMethod(html.document, 'hasFocus', []); + bool? get windowHasFocus => js_util.callMethod(html.document, 'hasFocus', []); void _setupHotRestart() { // This persists across hot restarts to clear stale DOM. _staleHotRestartState = js_util.getProperty(html.window, _staleHotRestartStore); if (_staleHotRestartState == null) { - _staleHotRestartState = []; + _staleHotRestartState = []; js_util.setProperty( html.window, _staleHotRestartStore, _staleHotRestartState); } @@ -93,7 +93,7 @@ class DomRenderer { registerHotRestartListener(() { _resizeSubscription?.cancel(); _localeSubscription?.cancel(); - _staleHotRestartState.addAll([ + _staleHotRestartState!.addAll([ _glassPaneElement, _styleElement, _viewportMeta, @@ -103,11 +103,11 @@ class DomRenderer { } void _clearOnHotRestart() { - if (_staleHotRestartState.isNotEmpty) { - for (html.Element element in _staleHotRestartState) { + if (_staleHotRestartState!.isNotEmpty) { + for (html.Element? element in _staleHotRestartState!) { element?.remove(); } - _staleHotRestartState.clear(); + _staleHotRestartState!.clear(); } } @@ -115,11 +115,11 @@ class DomRenderer { /// already in the right place, skip DOM mutation. This is both faster and /// more correct, because moving DOM nodes loses internal state, such as /// text selection. - void renderScene(html.Element sceneElement) { + void renderScene(html.Element? sceneElement) { if (sceneElement != _sceneElement) { _sceneElement?.remove(); _sceneElement = sceneElement; - append(_sceneHostElement, sceneElement); + append(_sceneHostElement!, sceneElement!); } assert(() { _clearOnHotRestart(); @@ -133,38 +133,16 @@ class DomRenderer { /// which captures semantics input events. The semantics DOM tree must be a /// child of the glass pane element so that events bubble up to the glass pane /// if they are not handled by semantics. - html.Element get glassPaneElement => _glassPaneElement; - html.Element _glassPaneElement; + html.Element? get glassPaneElement => _glassPaneElement; + html.Element? _glassPaneElement; - final html.Element rootElement = html.document.body; + final html.Element rootElement = html.document.body!; void addElementClass(html.Element element, String className) { element.classes.add(className); } - void attachBeforeElement( - html.Element parent, html.Element before, html.Element newElement) { - assert(parent != null); - if (parent != null) { - assert(() { - if (before == null) { - return true; - } - if (before.parent != parent) { - throw Exception( - 'attachBeforeElement was called with `before` element that\'s ' - 'not a child of the `parent` element:\n' - ' before: $before\n' - ' parent: $parent', - ); - } - return true; - }()); - parent.insertBefore(newElement, before); - } - } - - html.Element createElement(String tagName, {html.Element parent}) { + html.Element createElement(String tagName, {html.Element? parent}) { final html.Element element = html.document.createElement(tagName); parent?.append(element); return element; @@ -194,7 +172,7 @@ class DomRenderer { js_util.setProperty(element, name, value); } - void setElementStyle(html.Element element, String name, String value) { + void setElementStyle(html.Element element, String name, String? value) { if (value == null) { element.style.removeProperty(name); } else { @@ -210,21 +188,21 @@ class DomRenderer { element.children.clear(); } - html.Element getParent(html.Element element) => element.parent; + html.Element? getParent(html.Element element) => element.parent; void setTitle(String title) { html.document.title = title; } void setThemeColor(ui.Color color) { - html.MetaElement theme = html.document.querySelector('#flutterweb-theme'); + 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); + html.document.head!.append(theme); } - theme.content = colorToCssString(color); + theme.content = colorToCssString(color)!; } static const String defaultFontStyle = 'normal'; @@ -237,8 +215,8 @@ class DomRenderer { void reset() { _styleElement?.remove(); _styleElement = html.StyleElement(); - html.document.head.append(_styleElement); - final html.CssStyleSheet sheet = _styleElement.sheet; + html.document.head!.append(_styleElement!); + final html.CssStyleSheet sheet = _styleElement!.sheet as html.CssStyleSheet; final bool isWebKit = browserEngine == BrowserEngine.webkit; final bool isFirefox = browserEngine == BrowserEngine.firefox; // TODO(butterfly): use more efficient CSS selectors; descendant selectors @@ -329,7 +307,7 @@ flt-glass-pane * { ''', sheet.cssRules.length); } - final html.BodyElement bodyElement = html.document.body; + final html.BodyElement bodyElement = html.document.body!; setElementStyle(bodyElement, 'position', 'fixed'); setElementStyle(bodyElement, 'top', '0'); setElementStyle(bodyElement, 'right', '0'); @@ -361,7 +339,7 @@ flt-glass-pane * { bodyElement.spellcheck = false; for (html.Element viewportMeta - in html.document.head.querySelectorAll('meta[name="viewport"]')) { + in html.document.head!.querySelectorAll('meta[name="viewport"]')) { if (assertionsEnabled) { // Filter out the meta tag that we ourselves placed on the page. This is // to avoid UI flicker during hot restart. Hot restart will clean up the @@ -387,26 +365,27 @@ flt-glass-pane * { ..name = 'viewport' ..content = 'width=device-width, initial-scale=1.0, ' 'maximum-scale=1.0, user-scalable=no'; - html.document.head.append(_viewportMeta); + html.document.head!.append(_viewportMeta!); // IMPORTANT: the glass pane element must come after the scene element in the DOM node list so // it can intercept input events. _glassPaneElement?.remove(); - _glassPaneElement = createElement('flt-glass-pane'); - _glassPaneElement.style + final html.Element glassPaneElement = createElement('flt-glass-pane'); + _glassPaneElement = glassPaneElement; + glassPaneElement.style ..position = 'absolute' ..top = '0' ..right = '0' ..bottom = '0' ..left = '0'; - bodyElement.append(_glassPaneElement); + bodyElement.append(glassPaneElement); _sceneHostElement = createElement('flt-scene-host'); // Don't allow the scene to receive pointer events. - _sceneHostElement.style.pointerEvents = 'none'; + _sceneHostElement!.style.pointerEvents = 'none'; - _glassPaneElement.append(_sceneHostElement); + glassPaneElement.append(_sceneHostElement!); final html.Element _accesibilityPlaceholder = EngineSemanticsOwner .instance.semanticsHelper @@ -420,12 +399,12 @@ flt-glass-pane * { glassPaneElement .insertBefore(_accesibilityPlaceholder, _sceneHostElement); - PointerBinding.initInstance(_glassPaneElement); + PointerBinding.initInstance(glassPaneElement); // Hide the DOM nodes used to render the scene from accessibility, because // the accessibility tree is built from the SemanticsNode tree as a parallel // DOM tree. - setElementAttribute(_sceneHostElement, 'aria-hidden', 'true'); + setElementAttribute(_sceneHostElement!, 'aria-hidden', 'true'); if (html.window.visualViewport == null && isWebKit) { // Safari sometimes gives us bogus innerWidth/innerHeight values when the @@ -460,13 +439,13 @@ flt-glass-pane * { if (experimentalUseSkia) { _canvasKitScript?.remove(); _canvasKitScript = html.ScriptElement(); - _canvasKitScript.src = canvasKitBaseUrl + 'canvaskit.js'; - html.document.head.append(_canvasKitScript); + _canvasKitScript!.src = canvasKitBaseUrl + 'canvaskit.js'; + html.document.head!.append(_canvasKitScript!); } if (html.window.visualViewport != null) { _resizeSubscription = - html.window.visualViewport.onResize.listen(_metricsDidChange); + html.window.visualViewport!.onResize.listen(_metricsDidChange); } else { _resizeSubscription = html.window.onResize.listen(_metricsDidChange); } @@ -484,7 +463,7 @@ flt-glass-pane * { /// /// Note: always check for rotations for a mobile device. Update the physical /// size if the change is caused by a rotation. - void _metricsDidChange(html.Event event) { + void _metricsDidChange(html.Event? event) { if(isMobile && !window.isRotation() && textEditing.isEditing) { window.computeOnScreenKeyboardInsets(); window.invokeOnMetricsChanged(); @@ -500,7 +479,7 @@ flt-glass-pane * { void _languageDidChange(html.Event event) { window._updateLocales(); if (ui.window.onLocaleChanged != null) { - ui.window.onLocaleChanged(); + ui.window.onLocaleChanged!(); } } @@ -511,18 +490,18 @@ flt-glass-pane * { /// Removes all children of a DOM node. void clearDom(html.Node node) { while (node.lastChild != null) { - node.lastChild.remove(); + node.lastChild!.remove(); } } - static bool _ellipseFeatureDetected; + 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) { _ellipseFeatureDetected ??= js_util.getProperty(context, 'ellipse') != null; - if (_ellipseFeatureDetected) { + if (_ellipseFeatureDetected!) { context.ellipse(centerX, centerY, radiusX, radiusY, rotation, startAngle, endAngle, antiClockwise); } else { @@ -554,17 +533,17 @@ flt-glass-pane * { /// defer to the operating system default. /// /// See w3c screen api: https://www.w3.org/TR/screen-orientation/ - Future setPreferredOrientation(List orientations) { + Future setPreferredOrientation(List? orientations) { final html.Screen screen = html.window.screen; - if (screen != null) { + if (!_unsafeIsNull(screen)) { final html.ScreenOrientation screenOrientation = screen.orientation; - if (screenOrientation != null) { - if (orientations.isEmpty) { + if (!_unsafeIsNull(screenOrientation)) { + if (orientations!.isEmpty) { screenOrientation.unlock(); return Future.value(true); } else { - String lockType = _deviceOrientationToLockType(orientations.first); + String? lockType = _deviceOrientationToLockType(orientations.first); if (lockType != null) { final Completer completer = Completer(); try { @@ -588,7 +567,7 @@ flt-glass-pane * { } // Converts device orientation to w3c OrientationLockType enum. - static String _deviceOrientationToLockType(String deviceOrientation) { + static String? _deviceOrientationToLockType(String deviceOrientation) { switch(deviceOrientation) { case 'DeviceOrientation.portraitUp': return orientationLockTypePortraitPrimary; @@ -604,11 +583,14 @@ flt-glass-pane * { } /// The element corresponding to the only child of the root surface. - html.Element get _rootApplicationElement { + html.Element? get _rootApplicationElement { final html.Element lastElement = rootElement.children.last; - return lastElement.children.singleWhere((html.Element element) { - return element.tagName == 'FLT-SCENE'; - }, orElse: () => null); + for (html.Element child in lastElement.children) { + if (child.tagName == 'FLT-SCENE') { + return child; + } + } + return null; } /// Provides haptic feedback. @@ -621,22 +603,22 @@ flt-glass-pane * { String get currentHtml => _rootApplicationElement?.outerHtml ?? ''; - DebugDomRendererFrameStatistics _debugFrameStatistics; + DebugDomRendererFrameStatistics? _debugFrameStatistics; - DebugDomRendererFrameStatistics debugFlushFrameStatistics() { + DebugDomRendererFrameStatistics? debugFlushFrameStatistics() { if (!assertionsEnabled) { throw Exception('This code should not be reachable in production.'); } - final DebugDomRendererFrameStatistics current = _debugFrameStatistics; + final DebugDomRendererFrameStatistics? current = _debugFrameStatistics; _debugFrameStatistics = DebugDomRendererFrameStatistics(); return current; } - void debugRulerCacheHit() => _debugFrameStatistics.paragraphRulerCacheHits++; + void debugRulerCacheHit() => _debugFrameStatistics!.paragraphRulerCacheHits++; void debugRulerCacheMiss() => - _debugFrameStatistics.paragraphRulerCacheMisses++; - void debugRichTextLayout() => _debugFrameStatistics.richTextLayouts++; - void debugPlainTextLayout() => _debugFrameStatistics.plainTextLayouts++; + _debugFrameStatistics!.paragraphRulerCacheMisses++; + void debugRichTextLayout() => _debugFrameStatistics!.richTextLayouts++; + void debugPlainTextLayout() => _debugFrameStatistics!.plainTextLayouts++; } /// Miscellaneous statistics collecting during a single frame's execution. diff --git a/lib/web_ui/lib/src/engine/engine_canvas.dart b/lib/web_ui/lib/src/engine/engine_canvas.dart index 1c2261e766238..cfbd885d23e6a 100644 --- a/lib/web_ui/lib/src/engine/engine_canvas.dart +++ b/lib/web_ui/lib/src/engine/engine_canvas.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Defines canvas interface common across canvases that the [SceneBuilder] @@ -95,19 +95,19 @@ Matrix4 transformWithOffset(Matrix4 transform, ui.Offset offset) { class _SaveStackEntry { _SaveStackEntry({ - @required this.transform, - @required this.clipStack, + required this.transform, + required this.clipStack, }); final Matrix4 transform; - final List<_SaveClipEntry> clipStack; + final List<_SaveClipEntry>? clipStack; } /// Tagged union of clipping parameters used for canvas. class _SaveClipEntry { - final ui.Rect rect; - final ui.RRect rrect; - final ui.Path path; + final ui.Rect? rect; + final ui.RRect? rrect; + final ui.Path? path; final Matrix4 currentTransform; _SaveClipEntry.rect(this.rect, this.currentTransform) : rrect = null, @@ -129,7 +129,7 @@ mixin SaveStackTracking on EngineCanvas { /// The stack that maintains clipping operations used when text is painted /// onto bitmap canvas but is composited as separate element. - List<_SaveClipEntry> _clipStack; + List<_SaveClipEntry>? _clipStack; /// Returns whether there are active clipping regions on the canvas. bool get isClipped => _clipStack != null; @@ -157,7 +157,7 @@ mixin SaveStackTracking on EngineCanvas { _saveStack.add(_SaveStackEntry( transform: _currentTransform.clone(), clipStack: - _clipStack == null ? null : List<_SaveClipEntry>.from(_clipStack), + _clipStack == null ? null : List<_SaveClipEntry>.from(_clipStack!), )); } @@ -224,7 +224,7 @@ mixin SaveStackTracking on EngineCanvas { @override void clipRect(ui.Rect rect) { _clipStack ??= <_SaveClipEntry>[]; - _clipStack.add(_SaveClipEntry.rect(rect, _currentTransform.clone())); + _clipStack!.add(_SaveClipEntry.rect(rect, _currentTransform.clone())); } /// Adds a round rectangle to clipping stack. @@ -233,7 +233,7 @@ mixin SaveStackTracking on EngineCanvas { @override void clipRRect(ui.RRect rrect) { _clipStack ??= <_SaveClipEntry>[]; - _clipStack.add(_SaveClipEntry.rrect(rrect, _currentTransform.clone())); + _clipStack!.add(_SaveClipEntry.rrect(rrect, _currentTransform.clone())); } /// Adds a path to clipping stack. @@ -242,18 +242,18 @@ mixin SaveStackTracking on EngineCanvas { @override void clipPath(ui.Path path) { _clipStack ??= <_SaveClipEntry>[]; - _clipStack.add(_SaveClipEntry.path(path, _currentTransform.clone())); + _clipStack!.add(_SaveClipEntry.path(path, _currentTransform.clone())); } } html.Element _drawParagraphElement( EngineParagraph paragraph, ui.Offset offset, { - Matrix4 transform, + Matrix4? transform, }) { assert(paragraph._isLaidOut); - final html.Element paragraphElement = paragraph._paragraphElement.clone(true); + final html.Element paragraphElement = paragraph._paragraphElement.clone(true) as html.Element; final html.CssStyleDeclaration paragraphStyle = paragraphElement.style; paragraphStyle diff --git a/lib/web_ui/lib/src/engine/frame_reference.dart b/lib/web_ui/lib/src/engine/frame_reference.dart index 9274d67633dce..a79829f196898 100644 --- a/lib/web_ui/lib/src/engine/frame_reference.dart +++ b/lib/web_ui/lib/src/engine/frame_reference.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A monotonically increasing frame number being rendered. @@ -26,7 +26,7 @@ class FrameReference { } /// The current value of this reference. - V value; + V? value; } /// Cache where items cached before frame(N) is committed, can be reused in @@ -40,16 +40,16 @@ class FrameReference { /// at all. class CrossFrameCache { // Cached items in a scene. - Map>> _cache; + Map>>? _cache; // Cached items that have been committed, ready for reuse on next frame. - Map>> _reusablePool; + Map>>? _reusablePool; // Called when a scene or picture update is committed. void commitFrame() { // Evict unused items from prior frame. if (_reusablePool != null) { - for (List<_CrossFrameCacheItem> items in _reusablePool.values) { + for (List<_CrossFrameCacheItem> items in _reusablePool!.values) { for (_CrossFrameCacheItem item in items) { item.evict(); } @@ -64,21 +64,21 @@ class CrossFrameCache { /// /// Duplicate keys are allowed. For example the same image url may be used /// to create multiple instances of [ImageElement] to be reused in the future. - void cache(String key, T value, [CrossFrameCacheEvictCallback callback]) { + void cache(String key, T value, [CrossFrameCacheEvictCallback? callback]) { _addToCache(key, _CrossFrameCacheItem(value, callback)); } void _addToCache(String key, _CrossFrameCacheItem item) { _cache ??= {}; - (_cache[key] ??= [])..add(item); + (_cache![key] ??= [])..add(item); } /// Given a key, consumes an item that has been cached in a prior frame. - T reuse(String key) { + T? reuse(String key) { if (_reusablePool == null) { return null; } - List<_CrossFrameCacheItem> items = _reusablePool[key]; + List<_CrossFrameCacheItem>? items = _reusablePool![key]; if (items == null || items.isEmpty) { return null; } @@ -90,11 +90,11 @@ class CrossFrameCache { class _CrossFrameCacheItem { final T value; - final CrossFrameCacheEvictCallback evictCallback; + final CrossFrameCacheEvictCallback? evictCallback; _CrossFrameCacheItem(this.value, this.evictCallback); void evict() { if (evictCallback != null) { - evictCallback(value); + evictCallback!(value); } } } diff --git a/lib/web_ui/lib/src/engine/history.dart b/lib/web_ui/lib/src/engine/history.dart index 7a30d62d8f345..852dd6fa82bfc 100644 --- a/lib/web_ui/lib/src/engine/history.dart +++ b/lib/web_ui/lib/src/engine/history.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; const MethodCall _popRouteMethodCall = MethodCall('popRoute'); @@ -34,8 +34,8 @@ bool _isFlutterEntry(dynamic state) { /// /// There should only be one global instance of this class. class BrowserHistory { - LocationStrategy _locationStrategy; - ui.VoidCallback _unsubscribe; + LocationStrategy? _locationStrategy; + ui.VoidCallback? _unsubscribe; /// Changing the location strategy will unsubscribe from the old strategy's /// event listeners, and subscribe to the new one. @@ -45,7 +45,7 @@ class BrowserHistory { /// /// If the given strategy is null, it will render this [BrowserHistory] /// instance inactive. - set locationStrategy(LocationStrategy strategy) { + set locationStrategy(LocationStrategy? strategy) { if (strategy != _locationStrategy) { _tearoffStrategy(_locationStrategy); _locationStrategy = strategy; @@ -55,22 +55,22 @@ class BrowserHistory { /// Returns the currently active location strategy. @visibleForTesting - LocationStrategy get locationStrategy => _locationStrategy; + LocationStrategy? get locationStrategy => _locationStrategy; /// The path of the current location of the user's browser. String get currentPath => _locationStrategy?.path ?? '/'; /// Update the url with the given [routeName]. - void setRouteName(String routeName) { + void setRouteName(String? routeName) { if (_locationStrategy != null) { - _setupFlutterEntry(_locationStrategy, replace: true, path: routeName); + _setupFlutterEntry(_locationStrategy!, replace: true, path: routeName); } } /// This method does the same thing as the browser back button. Future back() { if (_locationStrategy != null) { - return _locationStrategy.back(); + return _locationStrategy!.back(); } return Future.value(); } @@ -81,21 +81,21 @@ class BrowserHistory { _tearoffStrategy(_locationStrategy); // After tearing off the location strategy, we should be on the "origin" // entry. So we need to go back one more time to exit the app. - final Future backFuture = _locationStrategy.back(); + final Future backFuture = _locationStrategy!.back(); _locationStrategy = null; return backFuture; } return Future.value(); } - String _userProvidedRouteName; + String? _userProvidedRouteName; void _popStateListener(covariant html.PopStateEvent event) { if (_isOriginEntry(event.state)) { // If we find ourselves in the origin entry, it means that the user // clicked the back button. // 1. Re-push the flutter entry to keep it always at the top of history. - _setupFlutterEntry(_locationStrategy); + _setupFlutterEntry(_locationStrategy!); // 2. Send a 'popRoute' platform message so the app can handle it accordingly. if (window._onPlatformMessage != null) { @@ -113,7 +113,7 @@ class BrowserHistory { // brings us here. assert(_userProvidedRouteName != null); - final String newRouteName = _userProvidedRouteName; + final String newRouteName = _userProvidedRouteName!; _userProvidedRouteName = null; // Send a 'pushRoute' platform message so the app handles it accordingly. @@ -137,7 +137,7 @@ class BrowserHistory { // 2. Then we remove the new entry. // This will take us back to our "flutter" entry and it causes a new // popstate event that will be handled in the "else if" section above. - _locationStrategy.back(); + _locationStrategy!.back(); } } @@ -145,7 +145,7 @@ class BrowserHistory { /// replaces the state of the entry so that we can recognize it later using /// [_isOriginEntry] inside [_popStateListener]. void _setupOriginEntry(LocationStrategy strategy) { - assert(strategy != null); + assert(strategy != null); // ignore: unnecessary_null_comparison strategy.replaceState(_originState, 'origin', ''); } @@ -154,9 +154,9 @@ class BrowserHistory { void _setupFlutterEntry( LocationStrategy strategy, { bool replace = false, - String path, + String? path, }) { - assert(strategy != null); + assert(strategy != null); // ignore: unnecessary_null_comparison path ??= currentPath; if (replace) { strategy.replaceState(_flutterState, 'flutter', path); @@ -165,7 +165,7 @@ class BrowserHistory { } } - void _setupStrategy(LocationStrategy strategy) { + void _setupStrategy(LocationStrategy? strategy) { if (strategy == null) { return; } @@ -180,16 +180,16 @@ class BrowserHistory { _setupOriginEntry(strategy); _setupFlutterEntry(strategy, replace: false, path: path); } - _unsubscribe = strategy.onPopState(_popStateListener); + _unsubscribe = strategy.onPopState(_popStateListener as dynamic Function(html.Event)); } - void _tearoffStrategy(LocationStrategy strategy) { + void _tearoffStrategy(LocationStrategy? strategy) { if (strategy == null) { return; } assert(_unsubscribe != null); - _unsubscribe(); + _unsubscribe!(); _unsubscribe = null; // Remove the "flutter" entry and go back to the "origin" entry so that the diff --git a/lib/web_ui/lib/src/engine/houdini_canvas.dart b/lib/web_ui/lib/src/engine/houdini_canvas.dart index dcf9e2a7c6d86..cebb845c02e60 100644 --- a/lib/web_ui/lib/src/engine/houdini_canvas.dart +++ b/lib/web_ui/lib/src/engine/houdini_canvas.dart @@ -7,7 +7,7 @@ // - avoid producing DOM-based clips if there is no text // - evaluate using stylesheets for static CSS properties // - evaluate reusing houdini canvases -// @dart = 2.6 + part of engine; /// A canvas that renders to a combination of HTML DOM and CSS Custom Paint API. @@ -22,7 +22,7 @@ class HoudiniCanvas extends EngineCanvas with SaveElementStackTracking { /// where this canvas paints. /// /// Painting outside the bounds of this rectangle is cropped. - final ui.Rect bounds; + final ui.Rect? bounds; HoudiniCanvas(this.bounds) { // TODO(yjbanov): would it be faster to specify static values in a @@ -31,8 +31,8 @@ class HoudiniCanvas extends EngineCanvas with SaveElementStackTracking { ..position = 'absolute' ..top = '0' ..left = '0' - ..width = '${bounds.size.width}px' - ..height = '${bounds.size.height}px' + ..width = '${bounds!.size.width}px' + ..height = '${bounds!.size.height}px' ..backgroundImage = 'paint(flt)'; } @@ -206,7 +206,7 @@ class HoudiniCanvas extends EngineCanvas with SaveElementStackTracking { void drawImageRect( ui.Image image, ui.Rect src, ui.Rect dst, SurfacePaintData paint) { // TODO(yjbanov): implement src rectangle - final HtmlImage htmlImage = image; + final HtmlImage htmlImage = image as HtmlImage; final html.Element imageBox = html.Element.tag('flt-img'); final String cssTransform = matrix4ToCssTransform( transformWithOffset(currentTransform, ui.Offset(dst.left, dst.top))); @@ -225,7 +225,7 @@ class HoudiniCanvas extends EngineCanvas with SaveElementStackTracking { @override void drawParagraph(ui.Paragraph paragraph, ui.Offset offset) { final html.Element paragraphElement = - _drawParagraphElement(paragraph, offset, transform: currentTransform); + _drawParagraphElement(paragraph as EngineParagraph, offset, transform: currentTransform); currentElement.append(paragraphElement); } @@ -246,8 +246,8 @@ class HoudiniCanvas extends EngineCanvas with SaveElementStackTracking { class _SaveElementStackEntry { _SaveElementStackEntry({ - @required this.savedElement, - @required this.transform, + required this.savedElement, + required this.transform, }); final html.Element savedElement; diff --git a/lib/web_ui/lib/src/engine/html_image_codec.dart b/lib/web_ui/lib/src/engine/html_image_codec.dart index cc092307c32c8..f0279db53ac80 100644 --- a/lib/web_ui/lib/src/engine/html_image_codec.dart +++ b/lib/web_ui/lib/src/engine/html_image_codec.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; final bool _supportsDecode = js_util.getProperty( @@ -16,7 +16,7 @@ typedef WebOnlyImageCodecChunkCallback = void Function( class HtmlCodec implements ui.Codec { final String src; - final WebOnlyImageCodecChunkCallback/*?*/ chunkCallback; + final WebOnlyImageCodecChunkCallback? chunkCallback; HtmlCodec(this.src, {this.chunkCallback}); @@ -33,7 +33,7 @@ class HtmlCodec implements ui.Codec { // we add 0/100 , 100/100 progress callbacks to enable loading progress // builders to create UI. if (chunkCallback != null) { - chunkCallback(0, 100); + chunkCallback!(0, 100); } if (_supportsDecode) { final html.ImageElement imgElement = html.ImageElement(); @@ -41,7 +41,7 @@ class HtmlCodec implements ui.Codec { js_util.setProperty(imgElement, 'decoding', 'async'); imgElement.decode().then((dynamic _) { if (chunkCallback != null) { - chunkCallback(100, 100); + chunkCallback!(100, 100); } final HtmlImage image = HtmlImage( imgElement, @@ -62,8 +62,8 @@ class HtmlCodec implements ui.Codec { } void _decodeUsingOnLoad(Completer completer) { - StreamSubscription loadSubscription; - StreamSubscription errorSubscription; + StreamSubscription? loadSubscription; + late StreamSubscription errorSubscription; final html.ImageElement imgElement = html.ImageElement(); // If the browser doesn't support asynchronous decoding of an image, // then use the `onload` event to decide when it's ready to paint to the @@ -76,9 +76,9 @@ class HtmlCodec implements ui.Codec { }); loadSubscription = imgElement.onLoad.listen((html.Event event) { if (chunkCallback != null) { - chunkCallback(100, 100); + chunkCallback!(100, 100); } - loadSubscription.cancel(); + loadSubscription!.cancel(); errorSubscription.cancel(); final HtmlImage image = HtmlImage( imgElement, @@ -133,11 +133,11 @@ class HtmlImage implements ui.Image { final int height; @override - Future toByteData( + Future toByteData( {ui.ImageByteFormat format = ui.ImageByteFormat.rawRgba}) { - return futurize((Callback callback) { - return _toByteData(format.index, (Uint8List encoded) { - callback(encoded?.buffer?.asByteData()); + return futurize((Callback callback) { + return _toByteData(format.index, (Uint8List? encoded) { + callback(encoded?.buffer.asByteData()); }); }); } @@ -146,7 +146,7 @@ class HtmlImage implements ui.Image { // clones on subsequent calls. html.ImageElement cloneImageElement() { if (_requiresClone) { - return imgElement.clone(true); + return imgElement.clone(true) as html.ImageElement; } else { _requiresClone = true; imgElement.style.position = 'absolute'; @@ -157,7 +157,7 @@ class HtmlImage implements ui.Image { // TODO(het): Support this for asset images and images generated from // `Picture`s. /// Returns an error message on failure, null on success. - String _toByteData(int format, Callback callback) { + String _toByteData(int format, Callback callback) { callback(null); return 'Image.toByteData is not supported in Flutter for Web'; } diff --git a/lib/web_ui/lib/src/engine/keyboard.dart b/lib/web_ui/lib/src/engine/keyboard.dart index 2569a05a3ab9f..df1e5d6b66b01 100644 --- a/lib/web_ui/lib/src/engine/keyboard.dart +++ b/lib/web_ui/lib/src/engine/keyboard.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// After a keydown is received, this is the duration we wait for a repeat event @@ -22,8 +22,8 @@ class Keyboard { } /// The [Keyboard] singleton. - static Keyboard get instance => _instance; - static Keyboard _instance; + static Keyboard? get instance => _instance; + static Keyboard? _instance; /// A mapping of [KeyboardEvent.code] to [Timer]. /// @@ -31,8 +31,8 @@ class Keyboard { /// if no repeat events were received. final Map _keydownTimers = {}; - html.EventListener _keydownListener; - html.EventListener _keyupListener; + html.EventListener? _keydownListener; + html.EventListener? _keyupListener; Keyboard._() { _keydownListener = (html.Event event) { @@ -58,7 +58,7 @@ class Keyboard { html.window.removeEventListener('keyup', _keyupListener); for (final String key in _keydownTimers.keys) { - _keydownTimers[key].cancel(); + _keydownTimers[key]!.cancel(); } _keydownTimers.clear(); @@ -79,7 +79,7 @@ class Keyboard { return; } - final html.KeyboardEvent keyboardEvent = event as html.KeyboardEvent; + final html.KeyboardEvent keyboardEvent = event; if (window._onPlatformMessage == null) { return; @@ -185,4 +185,4 @@ bool _isModifierKey(html.KeyboardEvent event) { return key == 'Meta' || key == 'Shift' || key == 'Alt' || key == 'Control'; } -void _noopCallback(ByteData data) {} +void _noopCallback(ByteData? data) {} diff --git a/lib/web_ui/lib/src/engine/mouse_cursor.dart b/lib/web_ui/lib/src/engine/mouse_cursor.dart index b96f0b2b2c1cb..2ee68977e42cd 100644 --- a/lib/web_ui/lib/src/engine/mouse_cursor.dart +++ b/lib/web_ui/lib/src/engine/mouse_cursor.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Provides mouse cursor bindings, such as the `flutter/mousecursor` channel. @@ -15,8 +15,8 @@ class MouseCursor { } /// The [MouseCursor] singleton. - static MouseCursor get instance => _instance; - static MouseCursor _instance; + static MouseCursor? get instance => _instance; + static MouseCursor? _instance; MouseCursor._() {} @@ -33,13 +33,13 @@ class MouseCursor { 'horizontalDoubleArrow': 'ew-resize', 'verticalDoubleArrow': 'ns-resize', }; - static String _mapKindToCssValue(String kind) { + static String _mapKindToCssValue(String? kind) { return _kindToCssValueMap[kind] ?? 'default'; } - void activateSystemCursor(String kind) { + void activateSystemCursor(String? kind) { domRenderer.setElementStyle( - domRenderer.glassPaneElement, + domRenderer.glassPaneElement!, 'cursor', _mapKindToCssValue(kind), ); diff --git a/lib/web_ui/lib/src/engine/onscreen_logging.dart b/lib/web_ui/lib/src/engine/onscreen_logging.dart index 95a39287503e3..2ec03e8e79e83 100644 --- a/lib/web_ui/lib/src/engine/onscreen_logging.dart +++ b/lib/web_ui/lib/src/engine/onscreen_logging.dart @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; -html.Element _logElement; -html.Element _logContainer; +html.Element? _logElement; +late html.Element _logContainer; List<_LogMessage> _logBuffer = <_LogMessage>[]; class _LogMessage { @@ -53,8 +53,8 @@ void printOnScreen(Object object) { void _initialize() { _logElement = html.Element.tag('flt-onscreen-log'); - _logElement.setAttribute('aria-hidden', 'true'); - _logElement.style + _logElement!.setAttribute('aria-hidden', 'true'); + _logElement!.style ..position = 'fixed' ..left = '0' ..right = '0' @@ -72,9 +72,9 @@ void _initialize() { _logContainer.style ..position = 'absolute' ..bottom = '0'; - _logElement.append(_logContainer); + _logElement!.append(_logContainer); - html.document.body.append(_logElement); + html.document.body!.append(_logElement!); } /// Dump the current stack to the console using [print] and @@ -86,7 +86,7 @@ void _initialize() { /// of lines. By default, all non-filtered stack lines are shown. /// /// The `label` argument, if present, will be printed before the stack. -void debugPrintStack({String label, int maxFrames}) { +void debugPrintStack({String? label, int? maxFrames}) { if (label != null) { print(label); } @@ -117,11 +117,11 @@ Iterable defaultStackFilter(Iterable frames) { final List result = []; final List skipped = []; for (String line in frames) { - final Match match = stackParser.firstMatch(line); + final Match? match = stackParser.firstMatch(line); if (match != null) { assert(match.groupCount == 2); if (filteredPackages.contains(match.group(2))) { - final Match packageMatch = packageParser.firstMatch(match.group(2)); + final Match? packageMatch = packageParser.firstMatch(match.group(2)!); if (packageMatch != null && packageMatch.group(1) == 'package') { skipped.add( 'package ${packageMatch.group(2)}'); // avoid "package package:foo" @@ -149,6 +149,6 @@ Iterable defaultStackFilter(Iterable frames) { return result; } -String debugIdentify(Object object) { - return '${object.runtimeType}(@${object.hashCode})'; +String debugIdentify(Object? object) { + return '${object!.runtimeType}(@${object.hashCode})'; } diff --git a/lib/web_ui/lib/src/engine/path_to_svg.dart b/lib/web_ui/lib/src/engine/path_to_svg.dart index be73c1e3911a0..d3f07ca47a8bc 100644 --- a/lib/web_ui/lib/src/engine/path_to_svg.dart +++ b/lib/web_ui/lib/src/engine/path_to_svg.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Converts [path] to SVG path syntax to be used as "d" attribute in path @@ -13,20 +13,20 @@ void pathToSvg(SurfacePath path, StringBuffer sb, for (PathCommand command in subPath.commands) { switch (command.type) { case PathCommandTypes.moveTo: - final MoveTo moveTo = command; + final MoveTo moveTo = command as MoveTo; sb.write('M ${moveTo.x + offsetX} ${moveTo.y + offsetY}'); break; case PathCommandTypes.lineTo: - final LineTo lineTo = command; + final LineTo lineTo = command as LineTo; sb.write('L ${lineTo.x + offsetX} ${lineTo.y + offsetY}'); break; case PathCommandTypes.bezierCurveTo: - final BezierCurveTo curve = command; + final BezierCurveTo curve = command as BezierCurveTo; sb.write('C ${curve.x1 + offsetX} ${curve.y1 + offsetY} ' '${curve.x2 + offsetX} ${curve.y2 + offsetY} ${curve.x3 + offsetX} ${curve.y3 + offsetY}'); break; case PathCommandTypes.quadraticCurveTo: - final QuadraticCurveTo quadraticCurveTo = command; + final QuadraticCurveTo quadraticCurveTo = command as QuadraticCurveTo; sb.write( 'Q ${quadraticCurveTo.x1 + offsetX} ${quadraticCurveTo.y1 + offsetY} ' '${quadraticCurveTo.x2 + offsetX} ${quadraticCurveTo.y2 + offsetY}'); @@ -35,7 +35,7 @@ void pathToSvg(SurfacePath path, StringBuffer sb, sb.write('Z'); break; case PathCommandTypes.ellipse: - final Ellipse ellipse = command; + final Ellipse ellipse = command as Ellipse; // Handle edge case where start and end points are the same by drawing // 2 half arcs. if ((ellipse.endAngle - ellipse.startAngle) % (2 * math.pi) == 0.0) { @@ -74,7 +74,7 @@ void pathToSvg(SurfacePath path, StringBuffer sb, } break; case PathCommandTypes.rRect: - final RRectCommand rrectCommand = command; + final RRectCommand rrectCommand = command as RRectCommand; final ui.RRect rrect = rrectCommand.rrect; double left = rrect.left + offsetX; double right = rrect.right + offsetX; @@ -125,7 +125,7 @@ void pathToSvg(SurfacePath path, StringBuffer sb, ); break; case PathCommandTypes.rect: - final RectCommand rectCommand = command; + final RectCommand rectCommand = command as RectCommand; final bool horizontalSwap = rectCommand.width < 0; final double left = offsetX + (horizontalSwap diff --git a/lib/web_ui/lib/src/engine/picture.dart b/lib/web_ui/lib/src/engine/picture.dart index 04010a28f27f4..62dadf917e4f3 100644 --- a/lib/web_ui/lib/src/engine/picture.dart +++ b/lib/web_ui/lib/src/engine/picture.dart @@ -2,23 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// An implementation of [ui.PictureRecorder] backed by a [RecordingCanvas]. class EnginePictureRecorder implements ui.PictureRecorder { EnginePictureRecorder(); - RecordingCanvas _canvas; - ui.Rect cullRect; + RecordingCanvas? _canvas; + late ui.Rect cullRect; bool _isRecording = false; RecordingCanvas beginRecording(ui.Rect bounds) { assert(!_isRecording); cullRect = bounds; _isRecording = true; - _canvas = RecordingCanvas(cullRect); - return _canvas; + return _canvas = RecordingCanvas(cullRect); } @override @@ -26,13 +25,13 @@ class EnginePictureRecorder implements ui.PictureRecorder { @override ui.Picture endRecording() { - // Returning null is what the flutter engine does: - // lib/ui/painting/picture_recorder.cc if (!_isRecording) { - return null; + // The mobile version returns an empty picture in this case. To match the + // behavior we produce a blank picture too. + beginRecording(ui.Rect.largest); } _isRecording = false; - _canvas.endRecording(); + _canvas!.endRecording(); return EnginePicture(_canvas, cullRect); } } @@ -49,7 +48,7 @@ class EnginePicture implements ui.Picture { Future toImage(int width, int height) async { final ui.Rect imageRect = ui.Rect.fromLTRB(0, 0, width.toDouble(), height.toDouble()); final BitmapCanvas canvas = BitmapCanvas(imageRect); - recordingCanvas.apply(canvas, imageRect); + recordingCanvas!.apply(canvas, imageRect); final String imageDataUrl = canvas.toDataUrl(); final html.ImageElement imageElement = html.ImageElement() ..src = imageDataUrl @@ -68,6 +67,6 @@ class EnginePicture implements ui.Picture { @override int get approximateBytesUsed => 0; - final RecordingCanvas recordingCanvas; - final ui.Rect cullRect; + final RecordingCanvas? recordingCanvas; + final ui.Rect? cullRect; } diff --git a/lib/web_ui/lib/src/engine/platform_views.dart b/lib/web_ui/lib/src/engine/platform_views.dart index 1d686da046b3f..813baa6edc92e 100644 --- a/lib/web_ui/lib/src/engine/platform_views.dart +++ b/lib/web_ui/lib/src/engine/platform_views.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; // TODO(yjbanov): The code in this file was temporarily moved to lib/web_ui/lib/ui.dart diff --git a/lib/web_ui/lib/src/engine/plugins.dart b/lib/web_ui/lib/src/engine/plugins.dart index b419ecab4e419..5998d8a5c4b69 100644 --- a/lib/web_ui/lib/src/engine/plugins.dart +++ b/lib/web_ui/lib/src/engine/plugins.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; -Future Function(String, ByteData, ui.PlatformMessageResponseCallback) pluginMessageCallHandler; +Future Function(String, ByteData?, ui.PlatformMessageResponseCallback?)? pluginMessageCallHandler; diff --git a/lib/web_ui/lib/src/engine/pointer_binding.dart b/lib/web_ui/lib/src/engine/pointer_binding.dart index 48e43dc72db45..5bb8e41cc723e 100644 --- a/lib/web_ui/lib/src/engine/pointer_binding.dart +++ b/lib/web_ui/lib/src/engine/pointer_binding.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Set this flag to true to see all the fired events in the console. @@ -54,33 +54,33 @@ int convertButtonToButtons(int button) { class PointerBinding { /// The singleton instance of this object. - static PointerBinding get instance => _instance; - static PointerBinding _instance; + static PointerBinding? get instance => _instance; + static PointerBinding? _instance; static void initInstance(html.Element glassPaneElement) { if (_instance == null) { _instance = PointerBinding._(glassPaneElement); assert(() { registerHotRestartListener(() { - _instance._adapter?.clearListeners(); - _instance._pointerDataConverter?.clearPointerState(); + _instance!._adapter.clearListeners(); + _instance!._pointerDataConverter.clearPointerState(); }); return true; }()); } } - PointerBinding._(this.glassPaneElement) { - _pointerDataConverter = PointerDataConverter(); - _detector = const PointerSupportDetector(); + PointerBinding._(this.glassPaneElement) + : _pointerDataConverter = PointerDataConverter(), + _detector = const PointerSupportDetector() { _adapter = _createAdapter(); } final html.Element glassPaneElement; PointerSupportDetector _detector; - _BaseAdapter _adapter; PointerDataConverter _pointerDataConverter; + late _BaseAdapter _adapter; /// Should be used in tests to define custom detection of pointer support. /// @@ -99,14 +99,14 @@ class PointerBinding { /// /// PointerBinding.instance.debugOverrideDetector(MyTestDetector()); /// ``` - void debugOverrideDetector(PointerSupportDetector newDetector) { + void debugOverrideDetector(PointerSupportDetector? newDetector) { newDetector ??= const PointerSupportDetector(); // When changing the detector, we need to swap the adapter. if (newDetector != _detector) { _detector = newDetector; - _adapter?.clearListeners(); + _adapter.clearListeners(); _adapter = _createAdapter(); - _pointerDataConverter?.clearPointerState(); + _pointerDataConverter.clearPointerState(); } } @@ -120,7 +120,7 @@ class PointerBinding { if (_detector.hasMouseEvents) { return _MouseAdapter(_onPointerData, glassPaneElement, _pointerDataConverter); } - return null; + throw UnsupportedError('This browser does not support pointer, touch, or mouse events.'); } void _onPointerData(Iterable data) { @@ -196,7 +196,7 @@ abstract class _BaseAdapter { bool acceptOutsideGlasspane = false, }) { final html.EventListener loggedHandler = (html.Event event) { - if (!acceptOutsideGlasspane && !glassPaneElement.contains(event.target)) { + if (!acceptOutsideGlasspane && !glassPaneElement.contains(event.target as html.Node?)) { return; } @@ -238,8 +238,8 @@ mixin _WheelEventListenerMixin on _BaseAdapter { // Flutter only supports pixel scroll delta. Convert deltaMode values // to pixels. - double deltaX = event.deltaX; - double deltaY = event.deltaY; + double deltaX = event.deltaX as double; + double deltaY = event.deltaY as double; switch (event.deltaMode) { case domDeltaLine: deltaX *= 32.0; @@ -261,8 +261,8 @@ mixin _WheelEventListenerMixin on _BaseAdapter { kind: ui.PointerDeviceKind.mouse, signalKind: ui.PointerSignalKind.scroll, device: _mouseDeviceId, - physicalX: event.client.x * ui.window.devicePixelRatio, - physicalY: event.client.y * ui.window.devicePixelRatio, + physicalX: event.client.x * ui.window.devicePixelRatio as double, + physicalY: event.client.y * ui.window.devicePixelRatio as double, buttons: event.buttons, pressure: 1.0, pressureMin: 0.0, @@ -292,8 +292,8 @@ mixin _WheelEventListenerMixin on _BaseAdapter { @immutable class _SanitizedDetails { const _SanitizedDetails({ - @required this.buttons, - @required this.change, + required this.buttons, + required this.change, }); final ui.PointerChange change; @@ -326,8 +326,8 @@ class _ButtonSanitizer { } _SanitizedDetails sanitizeDownEvent({ - @required int button, - @required int buttons, + required int button, + required int buttons, }) { // If the pointer is already down, we just send a move event with the new // `buttons` value. @@ -342,7 +342,7 @@ class _ButtonSanitizer { ); } - _SanitizedDetails sanitizeMoveEvent({@required int buttons}) { + _SanitizedDetails sanitizeMoveEvent({required int buttons}) { final int newPressedButtons = _htmlButtonsToFlutterButtons(buttons); // This could happen when the context menu is active and the user clicks // RMB somewhere else. The browser sends a down event with `buttons:0`. @@ -375,7 +375,7 @@ class _ButtonSanitizer { ); } - _SanitizedDetails sanitizeUpEvent() { + _SanitizedDetails? sanitizeUpEvent() { // The pointer could have been released by a `pointerout` event, in which // case `pointerup` should have no effect. if (_pressedButtons == 0) { @@ -406,8 +406,8 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin { _PointerAdapter( _PointerDataCallback callback, html.Element glassPaneElement, - PointerDataConverter _pointerDataConverter - ) : super(callback, glassPaneElement, _pointerDataConverter); + PointerDataConverter pointerDataConverter + ) : super(callback, glassPaneElement, pointerDataConverter); final Map _sanitizers = {}; @@ -419,8 +419,8 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin { } _ButtonSanitizer _getSanitizer(int device) { - final _ButtonSanitizer sanitizer = _sanitizers[device]; - assert(sanitizer != null); + final _ButtonSanitizer sanitizer = _sanitizers[device]!; + assert(sanitizer != null); // ignore: unnecessary_null_comparison return sanitizer; } @@ -436,7 +436,7 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin { bool acceptOutsideGlasspane = false, }) { addEventListener(eventName, (html.Event event) { - final html.PointerEvent pointerEvent = event; + final html.PointerEvent pointerEvent = event as html.PointerEvent; return handler(pointerEvent); }, acceptOutsideGlasspane: acceptOutsideGlasspane); } @@ -471,7 +471,7 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin { _addPointerEventListener('pointerup', (html.PointerEvent event) { final int device = event.pointerId; final List pointerData = []; - final _SanitizedDetails details = _getSanitizer(device).sanitizeUpEvent(); + final _SanitizedDetails? details = _getSanitizer(device).sanitizeUpEvent(); _removePointerIfUnhoverable(event); if (details != null) { _convertEventsToPointerData(data: pointerData, event: event, details: details); @@ -495,7 +495,7 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin { if (_debugLogPointerEvents) { print(event.type); } - _callback(_convertWheelEventToPointerData(event)); + _callback(_convertWheelEventToPointerData(event as html.WheelEvent)); // Prevent default so mouse wheel event doesn't get converted to // a scroll event that semantic nodes would process. event.preventDefault(); @@ -505,13 +505,13 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin { // For each event that is de-coalesced from `event` and described in // `details`, convert it to pointer data and store in `data`. void _convertEventsToPointerData({ - @required List data, - @required html.PointerEvent event, - @required _SanitizedDetails details, + required List data, + required html.PointerEvent event, + required _SanitizedDetails details, }) { - assert(data != null); - assert(event != null); - assert(details != null); + assert(data != null); // ignore: unnecessary_null_comparison + assert(event != null); // ignore: unnecessary_null_comparison + assert(details != null); // ignore: unnecessary_null_comparison final ui.PointerDeviceKind kind = _pointerTypeToDeviceKind(event.pointerType); // We force `device: _mouseDeviceId` on mouse pointers because Wheel events // might come before any PointerEvents, and since wheel events don't contain @@ -526,10 +526,10 @@ class _PointerAdapter extends _BaseAdapter with _WheelEventListenerMixin { kind: kind, signalKind: ui.PointerSignalKind.none, device: device, - physicalX: event.client.x * ui.window.devicePixelRatio, - physicalY: event.client.y * ui.window.devicePixelRatio, + physicalX: event.client.x * ui.window.devicePixelRatio as double, + physicalY: event.client.y * ui.window.devicePixelRatio as double, buttons: details.buttons, - pressure: event.pressure, + pressure: event.pressure as double, pressureMin: 0.0, pressureMax: 1.0, tilt: tilt, @@ -578,8 +578,8 @@ class _TouchAdapter extends _BaseAdapter { _TouchAdapter( _PointerDataCallback callback, html.Element glassPaneElement, - PointerDataConverter _pointerDataConverter - ) : super(callback, glassPaneElement, _pointerDataConverter); + PointerDataConverter pointerDataConverter + ) : super(callback, glassPaneElement, pointerDataConverter); final Set _pressedTouches = {}; bool _isTouchPressed(int identifier) => _pressedTouches.contains(identifier); @@ -588,7 +588,7 @@ class _TouchAdapter extends _BaseAdapter { void _addTouchEventListener(String eventName, _TouchEventListener handler) { addEventListener(eventName, (html.Event event) { - final html.TouchEvent touchEvent = event; + final html.TouchEvent touchEvent = event as html.TouchEvent; return handler(touchEvent); }); } @@ -676,11 +676,11 @@ class _TouchAdapter extends _BaseAdapter { } void _convertEventToPointerData({ - @required List data, - @required ui.PointerChange change, - @required html.Touch touch, - @required bool pressed, - @required Duration timeStamp, + required List data, + required ui.PointerChange change, + required html.Touch touch, + required bool pressed, + required Duration timeStamp, }) { _pointerDataConverter.convert( data, @@ -689,8 +689,8 @@ class _TouchAdapter extends _BaseAdapter { kind: ui.PointerDeviceKind.touch, signalKind: ui.PointerSignalKind.none, device: touch.identifier, - physicalX: touch.client.x * ui.window.devicePixelRatio, - physicalY: touch.client.y * ui.window.devicePixelRatio, + physicalX: touch.client.x * ui.window.devicePixelRatio as double, + physicalY: touch.client.y * ui.window.devicePixelRatio as double, buttons: pressed ? _kPrimaryMouseButton : 0, pressure: 1.0, pressureMin: 0.0, @@ -723,8 +723,8 @@ class _MouseAdapter extends _BaseAdapter with _WheelEventListenerMixin { _MouseAdapter( _PointerDataCallback callback, html.Element glassPaneElement, - PointerDataConverter _pointerDataConverter - ) : super(callback, glassPaneElement, _pointerDataConverter); + PointerDataConverter pointerDataConverter + ) : super(callback, glassPaneElement, pointerDataConverter); final _ButtonSanitizer _sanitizer = _ButtonSanitizer(); @@ -734,7 +734,7 @@ class _MouseAdapter extends _BaseAdapter with _WheelEventListenerMixin { bool acceptOutsideGlasspane = false, }) { addEventListener(eventName, (html.Event event) { - final html.MouseEvent mouseEvent = event; + final html.MouseEvent mouseEvent = event as html.MouseEvent; return handler(mouseEvent); }, acceptOutsideGlasspane: acceptOutsideGlasspane); } @@ -763,7 +763,7 @@ class _MouseAdapter extends _BaseAdapter with _WheelEventListenerMixin { final List pointerData = []; final bool isEndOfDrag = event.buttons == 0; final _SanitizedDetails sanitizedDetails = isEndOfDrag ? - _sanitizer.sanitizeUpEvent() : + _sanitizer.sanitizeUpEvent()! : _sanitizer.sanitizeMoveEvent(buttons: event.buttons); _convertEventsToPointerData(data: pointerData, event: event, details: sanitizedDetails); _callback(pointerData); @@ -774,7 +774,7 @@ class _MouseAdapter extends _BaseAdapter with _WheelEventListenerMixin { if (_debugLogPointerEvents) { print(event.type); } - _callback(_convertWheelEventToPointerData(event)); + _callback(_convertWheelEventToPointerData(event as html.WheelEvent)); // Prevent default so mouse wheel event doesn't get converted to // a scroll event that semantic nodes would process. event.preventDefault(); @@ -784,13 +784,13 @@ class _MouseAdapter extends _BaseAdapter with _WheelEventListenerMixin { // For each event that is de-coalesced from `event` and described in // `detailsList`, convert it to pointer data and store in `data`. void _convertEventsToPointerData({ - @required List data, - @required html.MouseEvent event, - @required _SanitizedDetails details, + required List data, + required html.MouseEvent event, + required _SanitizedDetails details, }) { - assert(data != null); - assert(event != null); - assert(details != null); + assert(data != null); // ignore: unnecessary_null_comparison + assert(event != null); // ignore: unnecessary_null_comparison + assert(details != null); // ignore: unnecessary_null_comparison _pointerDataConverter.convert( data, change: details.change, @@ -798,8 +798,8 @@ class _MouseAdapter extends _BaseAdapter with _WheelEventListenerMixin { kind: ui.PointerDeviceKind.mouse, signalKind: ui.PointerSignalKind.none, device: _mouseDeviceId, - physicalX: event.client.x * ui.window.devicePixelRatio, - physicalY: event.client.y * ui.window.devicePixelRatio, + physicalX: event.client.x * ui.window.devicePixelRatio as double, + physicalY: event.client.y * ui.window.devicePixelRatio as double, buttons: details.buttons, pressure: 1.0, pressureMin: 0.0, diff --git a/lib/web_ui/lib/src/engine/pointer_converter.dart b/lib/web_ui/lib/src/engine/pointer_converter.dart index f08ef76c0c937..a1e47d473a426 100644 --- a/lib/web_ui/lib/src/engine/pointer_converter.dart +++ b/lib/web_ui/lib/src/engine/pointer_converter.dart @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; class _PointerState { _PointerState(this.x, this.y); /// The identifier used in framework hit test. - int get pointer => _pointer; - int _pointer; + int? get pointer => _pointer; + int? _pointer; static int _pointerCount = 0; void startNewPointer() { _pointerCount += 1; @@ -65,33 +65,33 @@ class PointerDataConverter { } ui.PointerData _generateCompletePointerData({ - Duration timeStamp, - ui.PointerChange change, - ui.PointerDeviceKind kind, - ui.PointerSignalKind signalKind, - int device, - double physicalX, - double physicalY, - int buttons, - bool obscured, - double pressure, - double pressureMin, - double pressureMax, - double distance, - double distanceMax, - double size, - double radiusMajor, - double radiusMinor, - double radiusMin, - double radiusMax, - double orientation, - double tilt, - int platformData, - double scrollDeltaX, - double scrollDeltaY, + required Duration timeStamp, + required ui.PointerChange change, + required ui.PointerDeviceKind kind, + ui.PointerSignalKind? signalKind, + required int device, + required double physicalX, + required double physicalY, + required int buttons, + required bool obscured, + required double pressure, + required double pressureMin, + required double pressureMax, + required double distance, + required double distanceMax, + required double size, + required double radiusMajor, + required double radiusMinor, + required double radiusMin, + required double radiusMax, + required double orientation, + required double tilt, + required int platformData, + required double scrollDeltaX, + required double scrollDeltaY, }) { assert(_pointers.containsKey(device)); - final _PointerState state = _pointers[device]; + final _PointerState state = _pointers[device]!; final double deltaX = physicalX - state.x; final double deltaY = physicalY - state.y; state.x = physicalX; @@ -129,37 +129,37 @@ class PointerDataConverter { bool _locationHasChanged(int device, double physicalX, double physicalY) { assert(_pointers.containsKey(device)); - final _PointerState state = _pointers[device]; + final _PointerState state = _pointers[device]!; return state.x != physicalX || state.y != physicalY; } ui.PointerData _synthesizePointerData({ - Duration timeStamp, - ui.PointerChange change, - ui.PointerDeviceKind kind, - int device, - double physicalX, - double physicalY, - int buttons, - bool obscured, - double pressure, - double pressureMin, - double pressureMax, - double distance, - double distanceMax, - double size, - double radiusMajor, - double radiusMinor, - double radiusMin, - double radiusMax, - double orientation, - double tilt, - int platformData, - double scrollDeltaX, - double scrollDeltaY, + required Duration timeStamp, + required ui.PointerChange change, + required ui.PointerDeviceKind kind, + required int device, + required double physicalX, + required double physicalY, + required int buttons, + required bool obscured, + required double pressure, + required double pressureMin, + required double pressureMax, + required double distance, + required double distanceMax, + required double size, + required double radiusMajor, + required double radiusMinor, + required double radiusMin, + required double radiusMax, + required double orientation, + required double tilt, + required int platformData, + required double scrollDeltaX, + required double scrollDeltaY, }) { assert(_pointers.containsKey(device)); - final _PointerState state = _pointers[device]; + final _PointerState state = _pointers[device]!; final double deltaX = physicalX - state.x; final double deltaY = physicalY - state.y; state.x = physicalX; @@ -206,7 +206,7 @@ class PointerDataConverter { Duration timeStamp = Duration.zero, ui.PointerChange change = ui.PointerChange.cancel, ui.PointerDeviceKind kind = ui.PointerDeviceKind.touch, - ui.PointerSignalKind signalKind, + ui.PointerSignalKind? signalKind, int device = 0, double physicalX = 0.0, double physicalY = 0.0, @@ -228,7 +228,7 @@ class PointerDataConverter { double scrollDeltaX = 0.0, double scrollDeltaY = 0.0, }) { - assert(change != null); + assert(change != null); // ignore: unnecessary_null_comparison if (signalKind == null || signalKind == ui.PointerSignalKind.none) { switch (change) { @@ -429,7 +429,7 @@ class PointerDataConverter { break; case ui.PointerChange.move: assert(_pointers.containsKey(device)); - final _PointerState state = _pointers[device]; + final _PointerState state = _pointers[device]!; assert(state.down); result.add( _generateCompletePointerData( @@ -463,7 +463,7 @@ class PointerDataConverter { case ui.PointerChange.up: case ui.PointerChange.cancel: assert(_pointers.containsKey(device)); - final _PointerState state = _pointers[device]; + final _PointerState state = _pointers[device]!; assert(state.down); // Cancel events can have different coordinates due to various // reasons (window lost focus which is accompanied by window @@ -570,7 +570,7 @@ class PointerDataConverter { break; case ui.PointerChange.remove: assert(_pointers.containsKey(device)); - final _PointerState state = _pointers[device]; + final _PointerState state = _pointers[device]!; assert(!state.down); result.add( _generateCompletePointerData( diff --git a/lib/web_ui/lib/src/engine/profiler.dart b/lib/web_ui/lib/src/engine/profiler.dart index 7e98bdd06e1ac..811d0a89b6a37 100644 --- a/lib/web_ui/lib/src/engine/profiler.dart +++ b/lib/web_ui/lib/src/engine/profiler.dart @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A function that receives a benchmark [value] labeleb by [name]. -typedef OnBenchmark = void Function(String name, num value); +typedef OnBenchmark = void Function(String name, double value); /// A function that computes a value of type [R]. /// @@ -38,7 +38,7 @@ R timeAction(String name, Action action) { final Stopwatch stopwatch = Stopwatch()..start(); final R result = action(); stopwatch.stop(); - Profiler.instance.benchmark(name, stopwatch.elapsedMicroseconds); + Profiler.instance.benchmark(name, stopwatch.elapsedMicroseconds.toDouble()); return result; } } @@ -73,17 +73,18 @@ class Profiler { static Profiler get instance { _checkBenchmarkMode(); - if (_instance == null) { + final Profiler? profiler = _instance; + if (profiler == null) { throw Exception( 'Profiler has not been properly initialized. ' 'Make sure Profiler.ensureInitialized() is being called before you ' 'access Profiler.instance', ); } - return _instance; + return profiler; } - static Profiler _instance; + static Profiler? _instance; static void _checkBenchmarkMode() { if (!isBenchmarkMode) { @@ -96,10 +97,10 @@ class Profiler { } /// Used to send benchmark data to whoever is listening to them. - void benchmark(String name, num value) { + void benchmark(String name, double value) { _checkBenchmarkMode(); - final OnBenchmark onBenchmark = + final OnBenchmark? onBenchmark = js_util.getProperty(html.window, '_flutter_internal_on_benchmark'); if (onBenchmark != null) { onBenchmark(name, value); diff --git a/lib/web_ui/lib/src/engine/rrect_renderer.dart b/lib/web_ui/lib/src/engine/rrect_renderer.dart index 79e2377706042..3585d7c5fcf73 100644 --- a/lib/web_ui/lib/src/engine/rrect_renderer.dart +++ b/lib/web_ui/lib/src/engine/rrect_renderer.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Renders an RRect using path primitives. @@ -231,19 +231,19 @@ typedef RRectRendererCallback = void Function(double x, double y); class RRectMetricsRenderer extends _RRectRenderer { RRectMetricsRenderer({this.moveToCallback, this.lineToCallback, this.ellipseCallback}); - final RRectRendererEllipseCallback ellipseCallback; - final RRectRendererCallback lineToCallback; - final RRectRendererCallback moveToCallback; + final RRectRendererEllipseCallback? ellipseCallback; + final RRectRendererCallback? lineToCallback; + final RRectRendererCallback? moveToCallback; @override void beginPath() {} @override - void ellipse(double centerX, double centerY, double radiusX, double radiusY, double rotation, double startAngle, double endAngle, bool antiClockwise) => ellipseCallback( + void ellipse(double centerX, double centerY, double radiusX, double radiusY, double rotation, double startAngle, double endAngle, bool antiClockwise) => ellipseCallback!( centerX, centerY, radiusX, radiusY, rotation, startAngle, endAngle, antiClockwise); @override - void lineTo(double x, double y) => lineToCallback(x, y); + void lineTo(double x, double y) => lineToCallback!(x, y); @override - void moveTo(double x, double y) => moveToCallback(x, y); + void moveTo(double x, double y) => moveToCallback!(x, y); } diff --git a/lib/web_ui/lib/src/engine/semantics/accessibility.dart b/lib/web_ui/lib/src/engine/semantics/accessibility.dart index 2d874f8cf01da..bc17ef958446c 100644 --- a/lib/web_ui/lib/src/engine/semantics/accessibility.dart +++ b/lib/web_ui/lib/src/engine/semantics/accessibility.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Singleton for accessing accessibility announcements from the platform. @@ -18,7 +18,7 @@ class AccessibilityAnnouncements { return _instance ??= AccessibilityAnnouncements._(); } - static AccessibilityAnnouncements _instance; + static AccessibilityAnnouncements? _instance; AccessibilityAnnouncements._() { registerHotRestartListener(() { @@ -31,7 +31,7 @@ class AccessibilityAnnouncements { /// /// The element is added to the DOM temporarily for announcing the /// message to the assistive technology. - Timer _removeElementTimer; + Timer? _removeElementTimer; /// The duration the accessibility announcements stay on the DOM. /// @@ -47,20 +47,20 @@ class AccessibilityAnnouncements { /// This element has aria-live attribute. /// /// It also has id 'accessibility-element' for testing purposes. - html.HtmlElement _element; + html.HtmlElement? _element; html.HtmlElement get _domElement => _element ??= _createElement(); /// Decodes the message coming from the 'flutter/accessibility' channel. - void handleMessage(StandardMessageCodec codec, ByteData data) { + void handleMessage(StandardMessageCodec codec, ByteData? data) { final Map inputMap = codec.decodeMessage(data); final Map dataMap = inputMap['data']; - final String message = dataMap['message']; + final String? message = dataMap['message']; if (message != null && message.isNotEmpty) { _initLiveRegion(message); _removeElementTimer = Timer(durationA11yMessageIsOnDom, () { - _element.remove(); + _element!.remove(); }); } } @@ -68,7 +68,7 @@ class AccessibilityAnnouncements { void _initLiveRegion(String message) { _domElement.setAttribute('aria-live', 'polite'); _domElement.text = message; - html.document.body.append(_domElement); + html.document.body!.append(_domElement); } html.LabelElement _createElement() { diff --git a/lib/web_ui/lib/src/engine/semantics/checkable.dart b/lib/web_ui/lib/src/engine/semantics/checkable.dart index 8cf23b39d6770..c8d7f3ccfca8f 100644 --- a/lib/web_ui/lib/src/engine/semantics/checkable.dart +++ b/lib/web_ui/lib/src/engine/semantics/checkable.dart @@ -11,7 +11,7 @@ // framework. Currently the framework does not report the // grouping of radio buttons. -// @dart = 2.6 + part of engine; /// The specific type of checkable control. @@ -28,6 +28,16 @@ enum _CheckableKind { toggle, } +_CheckableKind _checkableKindFromSemanticsFlag(SemanticsObject semanticsObject) { + if (semanticsObject.hasFlag(ui.SemanticsFlag.isInMutuallyExclusiveGroup)) { + return _CheckableKind.radio; + } else if (semanticsObject.hasFlag(ui.SemanticsFlag.hasToggledState)) { + return _CheckableKind.toggle; + } else { + return _CheckableKind.checkbox; + } +} + /// Renders semantics objects that have checkable (on/off) states. /// /// Three objects which are implemented by this class are checkboxes, radio @@ -37,18 +47,11 @@ enum _CheckableKind { /// [ui.SemanticsFlag.isInMutuallyExclusiveGroup], [ui.SemanticsFlag.isToggled], /// [ui.SemanticsFlag.hasToggledState] class Checkable extends RoleManager { - _CheckableKind _kind; + final _CheckableKind _kind; Checkable(SemanticsObject semanticsObject) - : super(Role.checkable, semanticsObject) { - if (semanticsObject.hasFlag(ui.SemanticsFlag.isInMutuallyExclusiveGroup)) { - _kind = _CheckableKind.radio; - } else if (semanticsObject.hasFlag(ui.SemanticsFlag.hasToggledState)) { - _kind = _CheckableKind.toggle; - } else { - _kind = _CheckableKind.checkbox; - } - } + : _kind = _checkableKindFromSemanticsFlag(semanticsObject), + super(Role.checkable, semanticsObject); @override void update() { diff --git a/lib/web_ui/lib/src/engine/semantics/image.dart b/lib/web_ui/lib/src/engine/semantics/image.dart index 1b97f46f0bb4c..52dd645de2071 100644 --- a/lib/web_ui/lib/src/engine/semantics/image.dart +++ b/lib/web_ui/lib/src/engine/semantics/image.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Represents semantic objects that deliver information in a visual manner. @@ -17,7 +17,7 @@ class ImageRoleManager extends RoleManager { /// The element with role="img" and aria-label could block access to all /// children elements, therefore create an auxiliary element and describe the /// image in that if the semantic object have child nodes. - html.Element _auxiliaryImageElement; + html.Element? _auxiliaryImageElement; @override void update() { @@ -30,18 +30,18 @@ class ImageRoleManager extends RoleManager { // other nodes, then VoiceOver behaves as expected with absolute // positioning and sizing. if (semanticsObject.hasChildren) { - _auxiliaryImageElement.style + _auxiliaryImageElement!.style ..position = 'absolute' ..top = '0' ..left = '0' - ..width = '${semanticsObject.rect.width}px' - ..height = '${semanticsObject.rect.height}px'; + ..width = '${semanticsObject.rect!.width}px' + ..height = '${semanticsObject.rect!.height}px'; } - _auxiliaryImageElement.style.fontSize = '6px'; - semanticsObject.element.append(_auxiliaryImageElement); + _auxiliaryImageElement!.style.fontSize = '6px'; + semanticsObject.element.append(_auxiliaryImageElement!); } - _auxiliaryImageElement.setAttribute('role', 'img'); + _auxiliaryImageElement!.setAttribute('role', 'img'); _setLabel(_auxiliaryImageElement); } else if (semanticsObject.isVisualOnly) { semanticsObject.setAriaRole('img', true); @@ -53,15 +53,15 @@ class ImageRoleManager extends RoleManager { } } - void _setLabel(html.Element element) { + void _setLabel(html.Element? element) { if (semanticsObject.hasLabel) { - element.setAttribute('aria-label', semanticsObject.label); + element!.setAttribute('aria-label', semanticsObject.label!); } } void _cleanUpAuxiliaryElement() { if (_auxiliaryImageElement != null) { - _auxiliaryImageElement.remove(); + _auxiliaryImageElement!.remove(); _auxiliaryImageElement = null; } } diff --git a/lib/web_ui/lib/src/engine/semantics/incrementable.dart b/lib/web_ui/lib/src/engine/semantics/incrementable.dart index aec945a769b65..3a86c33494c35 100644 --- a/lib/web_ui/lib/src/engine/semantics/incrementable.dart +++ b/lib/web_ui/lib/src/engine/semantics/incrementable.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 part of engine; /// Adds increment/decrement event handling to a semantics object. @@ -30,7 +29,7 @@ class Incrementable extends RoleManager { /// Disables the input [_element] when the gesture mode switches to /// [GestureMode.pointerEvents], and enables it when the mode switches back to /// [GestureMode.browserGestures]. - GestureModeCallback _gestureModeListener; + GestureModeCallback? _gestureModeListener; /// Whether we forwarded a semantics action to the framework and awaiting an /// update. @@ -108,15 +107,15 @@ class Incrementable extends RoleManager { final String surrogateTextValue = '$_currentSurrogateValue'; _element.value = surrogateTextValue; _element.setAttribute('aria-valuenow', surrogateTextValue); - _element.setAttribute('aria-valuetext', semanticsObject.value); + _element.setAttribute('aria-valuetext', semanticsObject.value!); - final bool canIncrease = semanticsObject.increasedValue.isNotEmpty; + final bool canIncrease = semanticsObject.increasedValue!.isNotEmpty; final String surrogateMaxTextValue = canIncrease ? '${_currentSurrogateValue + 1}' : surrogateTextValue; _element.max = surrogateMaxTextValue; _element.setAttribute('aria-valuemax', surrogateMaxTextValue); - final bool canDecrease = semanticsObject.decreasedValue.isNotEmpty; + final bool canDecrease = semanticsObject.decreasedValue!.isNotEmpty; final String surrogateMinTextValue = canDecrease ? '${_currentSurrogateValue - 1}' : surrogateTextValue; _element.min = surrogateMinTextValue; diff --git a/lib/web_ui/lib/src/engine/semantics/label_and_value.dart b/lib/web_ui/lib/src/engine/semantics/label_and_value.dart index de78e08ee6d4b..204146335c6a6 100644 --- a/lib/web_ui/lib/src/engine/semantics/label_and_value.dart +++ b/lib/web_ui/lib/src/engine/semantics/label_and_value.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Renders [_label] and [_value] to the semantics DOM. @@ -43,7 +43,7 @@ class LabelAndValue extends RoleManager { /// its label is not reachable via accessibility focus. This happens, for /// example in popup dialogs, such as the alert dialog. The text of the /// alert is supplied as a label on the parent node. - html.Element _auxiliaryValueElement; + html.Element? _auxiliaryValueElement; @override void update() { @@ -89,22 +89,22 @@ class LabelAndValue extends RoleManager { // nodes, then VoiceOver behaves as expected with absolute positioning and // sizing. if (semanticsObject.hasChildren) { - _auxiliaryValueElement.style + _auxiliaryValueElement!.style ..position = 'absolute' ..top = '0' ..left = '0' - ..width = '${semanticsObject.rect.width}px' - ..height = '${semanticsObject.rect.height}px'; + ..width = '${semanticsObject.rect!.width}px' + ..height = '${semanticsObject.rect!.height}px'; } - _auxiliaryValueElement.style.fontSize = '6px'; - semanticsObject.element.append(_auxiliaryValueElement); + _auxiliaryValueElement!.style.fontSize = '6px'; + semanticsObject.element.append(_auxiliaryValueElement!); } - _auxiliaryValueElement.text = combinedValue.toString(); + _auxiliaryValueElement!.text = combinedValue.toString(); } void _cleanUpDom() { if (_auxiliaryValueElement != null) { - _auxiliaryValueElement.remove(); + _auxiliaryValueElement!.remove(); _auxiliaryValueElement = null; } semanticsObject.element.attributes.remove('aria-label'); diff --git a/lib/web_ui/lib/src/engine/semantics/live_region.dart b/lib/web_ui/lib/src/engine/semantics/live_region.dart index 8229d67c267b0..ccb6be47c1623 100644 --- a/lib/web_ui/lib/src/engine/semantics/live_region.dart +++ b/lib/web_ui/lib/src/engine/semantics/live_region.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Manages semantics configurations that represent live regions. diff --git a/lib/web_ui/lib/src/engine/semantics/scrollable.dart b/lib/web_ui/lib/src/engine/semantics/scrollable.dart index 0c818314a26f1..ae99803291f2f 100644 --- a/lib/web_ui/lib/src/engine/semantics/scrollable.dart +++ b/lib/web_ui/lib/src/engine/semantics/scrollable.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Implements vertical and horizontal scrolling functionality for semantics @@ -27,13 +27,13 @@ class Scrollable extends RoleManager { : super(Role.scrollable, semanticsObject); /// Disables browser-driven scrolling in the presence of pointer events. - GestureModeCallback _gestureModeListener; + GestureModeCallback? _gestureModeListener; /// Listens to HTML "scroll" gestures detected by the browser. /// /// This gesture is converted to [ui.SemanticsAction.scrollUp] or /// [ui.SemanticsAction.scrollDown], depending on the direction. - html.EventListener _scrollListener; + html.EventListener? _scrollListener; /// The value of the "scrollTop" or "scrollLeft" property of this object's /// [element] that has zero offset relative to the [scrollPosition]. diff --git a/lib/web_ui/lib/src/engine/semantics/semantics.dart b/lib/web_ui/lib/src/engine/semantics/semantics.dart index d1808ce2c223a..3d880a29d3de3 100644 --- a/lib/web_ui/lib/src/engine/semantics/semantics.dart +++ b/lib/web_ui/lib/src/engine/semantics/semantics.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Set this flag to `true` to cause the engine to visualize the semantics tree @@ -16,11 +16,11 @@ const bool _debugShowSemanticsNodes = false; /// This class provides private engine-side API that's not available in the /// `dart:ui` [ui.SemanticsUpdate]. class SemanticsUpdate implements ui.SemanticsUpdate { - SemanticsUpdate({List nodeUpdates}) + SemanticsUpdate({List? nodeUpdates}) : _nodeUpdates = nodeUpdates; /// Updates for individual nodes. - final List _nodeUpdates; + final List? _nodeUpdates; @override void dispose() { @@ -33,32 +33,32 @@ class SemanticsUpdate implements ui.SemanticsUpdate { /// Updates the properties of a particular semantics node. class SemanticsNodeUpdate { SemanticsNodeUpdate({ - this.id, - this.flags, - this.actions, - this.maxValueLength, - this.currentValueLength, - this.textSelectionBase, - this.textSelectionExtent, - this.platformViewId, - this.scrollChildren, - this.scrollIndex, - this.scrollPosition, - this.scrollExtentMax, - this.scrollExtentMin, - this.rect, - this.label, - this.hint, - this.value, - this.increasedValue, - this.decreasedValue, + required this.id, + required this.flags, + required this.actions, + required this.maxValueLength, + required this.currentValueLength, + required this.textSelectionBase, + required this.textSelectionExtent, + required this.platformViewId, + required this.scrollChildren, + required this.scrollIndex, + required this.scrollPosition, + required this.scrollExtentMax, + required this.scrollExtentMin, + required this.rect, + required this.label, + required this.hint, + required this.value, + required this.increasedValue, + required this.decreasedValue, this.textDirection, - this.transform, - this.elevation, - this.thickness, - this.childrenInTraversalOrder, - this.childrenInHitTestOrder, - this.additionalActions, + required this.transform, + required this.elevation, + required this.thickness, + required this.childrenInTraversalOrder, + required this.childrenInHitTestOrder, + required this.additionalActions, }); /// See [ui.SemanticsUpdateBuilder.updateNode]. @@ -119,7 +119,7 @@ class SemanticsNodeUpdate { final String decreasedValue; /// See [ui.SemanticsUpdateBuilder.updateNode]. - final ui.TextDirection textDirection; + final ui.TextDirection? textDirection; /// See [ui.SemanticsUpdateBuilder.updateNode]. final Float32List transform; @@ -199,7 +199,7 @@ abstract class RoleManager { /// /// A single role object manages exactly one [SemanticsObject]. RoleManager(this.role, this.semanticsObject) - : assert(semanticsObject != null); + : assert(semanticsObject != null); // ignore: unnecessary_null_comparison /// Role identifier. final Role role; @@ -258,8 +258,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - int get flags => _flags; - int _flags; + int? get flags => _flags; + int? _flags; /// Whether the [flags] field has been updated but has not been applied to the /// DOM yet. @@ -270,8 +270,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - int get actions => _actions; - int _actions; + int? get actions => _actions; + int? _actions; static const int _actionsIndex = 1 << 1; @@ -283,8 +283,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - int get textSelectionBase => _textSelectionBase; - int _textSelectionBase; + int? get textSelectionBase => _textSelectionBase; + int? _textSelectionBase; static const int _textSelectionBaseIndex = 1 << 2; @@ -296,8 +296,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - int get textSelectionExtent => _textSelectionExtent; - int _textSelectionExtent; + int? get textSelectionExtent => _textSelectionExtent; + int? _textSelectionExtent; static const int _textSelectionExtentIndex = 1 << 3; @@ -309,8 +309,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - int get scrollChildren => _scrollChildren; - int _scrollChildren; + int? get scrollChildren => _scrollChildren; + int? _scrollChildren; static const int _scrollChildrenIndex = 1 << 4; @@ -322,8 +322,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - int get scrollIndex => _scrollIndex; - int _scrollIndex; + int? get scrollIndex => _scrollIndex; + int? _scrollIndex; static const int _scrollIndexIndex = 1 << 5; @@ -335,8 +335,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - double get scrollPosition => _scrollPosition; - double _scrollPosition; + double? get scrollPosition => _scrollPosition; + double? _scrollPosition; static const int _scrollPositionIndex = 1 << 6; @@ -348,8 +348,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - double get scrollExtentMax => _scrollExtentMax; - double _scrollExtentMax; + double? get scrollExtentMax => _scrollExtentMax; + double? _scrollExtentMax; static const int _scrollExtentMaxIndex = 1 << 7; @@ -361,8 +361,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - double get scrollExtentMin => _scrollExtentMin; - double _scrollExtentMin; + double? get scrollExtentMin => _scrollExtentMin; + double? _scrollExtentMin; static const int _scrollExtentMinIndex = 1 << 8; @@ -374,8 +374,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - ui.Rect get rect => _rect; - ui.Rect _rect; + ui.Rect? get rect => _rect; + ui.Rect? _rect; static const int _rectIndex = 1 << 9; @@ -387,11 +387,11 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - String get label => _label; - String _label; + String? get label => _label; + String? _label; /// Whether this object contains a non-empty label. - bool get hasLabel => _label != null && _label.isNotEmpty; + bool get hasLabel => _label != null && _label!.isNotEmpty; static const int _labelIndex = 1 << 10; @@ -403,8 +403,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - String get hint => _hint; - String _hint; + String? get hint => _hint; + String? _hint; static const int _hintIndex = 1 << 11; @@ -416,11 +416,11 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - String get value => _value; - String _value; + String? get value => _value; + String? _value; /// Whether this object contains a non-empty value. - bool get hasValue => _value != null && _value.isNotEmpty; + bool get hasValue => _value != null && _value!.isNotEmpty; static const int _valueIndex = 1 << 12; @@ -432,8 +432,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - String get increasedValue => _increasedValue; - String _increasedValue; + String? get increasedValue => _increasedValue; + String? _increasedValue; static const int _increasedValueIndex = 1 << 13; @@ -445,8 +445,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - String get decreasedValue => _decreasedValue; - String _decreasedValue; + String? get decreasedValue => _decreasedValue; + String? _decreasedValue; static const int _decreasedValueIndex = 1 << 14; @@ -458,8 +458,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - ui.TextDirection get textDirection => _textDirection; - ui.TextDirection _textDirection; + ui.TextDirection? get textDirection => _textDirection; + ui.TextDirection? _textDirection; static const int _textDirectionIndex = 1 << 15; @@ -471,8 +471,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - Float32List get transform => _transform; - Float32List _transform; + Float32List? get transform => _transform; + Float32List? _transform; static const int _transformIndex = 1 << 16; @@ -484,8 +484,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - Int32List get childrenInTraversalOrder => _childrenInTraversalOrder; - Int32List _childrenInTraversalOrder; + Int32List? get childrenInTraversalOrder => _childrenInTraversalOrder; + Int32List? _childrenInTraversalOrder; static const int _childrenInTraversalOrderIndex = 1 << 19; @@ -498,8 +498,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - Int32List get childrenInHitTestOrder => _childrenInHitTestOrder; - Int32List _childrenInHitTestOrder; + Int32List? get childrenInHitTestOrder => _childrenInHitTestOrder; + Int32List? _childrenInHitTestOrder; static const int _childrenInHitTestOrderIndex = 1 << 20; @@ -512,8 +512,8 @@ class SemanticsObject { } /// See [ui.SemanticsUpdateBuilder.updateNode]. - Int32List get additionalActions => _additionalActions; - Int32List _additionalActions; + Int32List? get additionalActions => _additionalActions; + Int32List? _additionalActions; static const int _additionalActionsIndex = 1 << 21; @@ -552,11 +552,11 @@ class SemanticsObject { /// is not created. This is necessary for "aria-label" to function correctly. /// The browser will ignore the [label] of HTML element that contain child /// elements. - html.Element getOrCreateChildContainer() { + html.Element? getOrCreateChildContainer() { if (_childContainerElement == null) { _childContainerElement = html.Element.tag('flt-semantics-container'); - _childContainerElement.style.position = 'absolute'; - element.append(_childContainerElement); + _childContainerElement!.style.position = 'absolute'; + element.append(_childContainerElement!); } return _childContainerElement; } @@ -566,16 +566,16 @@ class SemanticsObject { /// /// This element is used to correct for [_rect] offsets. It is only non-`null` /// when there are non-zero children (i.e. when [hasChildren] is `true`). - html.Element _childContainerElement; + html.Element? _childContainerElement; /// The parent of this semantics object. - SemanticsObject _parent; + SemanticsObject? _parent; /// Whether this node currently has a given [SemanticsFlag]. - bool hasFlag(ui.SemanticsFlag flag) => _flags & flag.index != 0; + bool hasFlag(ui.SemanticsFlag flag) => _flags! & flag.index != 0; /// Whether [actions] contains the given action. - bool hasAction(ui.SemanticsAction action) => (_actions & action.index) != 0; + bool hasAction(ui.SemanticsAction action) => (_actions! & action.index) != 0; /// Whether this object represents a vertically scrollable area. bool get isVerticalScrollContainer => @@ -589,7 +589,7 @@ class SemanticsObject { /// Whether this object has a non-empty list of children. bool get hasChildren => - _childrenInTraversalOrder != null && _childrenInTraversalOrder.isNotEmpty; + _childrenInTraversalOrder != null && _childrenInTraversalOrder!.isNotEmpty; /// Whether this object represents an editable text field. bool get isTextField => hasFlag(ui.SemanticsFlag.isTextField); @@ -612,7 +612,7 @@ class SemanticsObject { void updateWith(SemanticsNodeUpdate update) { // Update all field values and their corresponding dirty flags before // applying the updates to the DOM. - assert(update.flags != null); + assert(update.flags != null); // ignore: unnecessary_null_comparison if (_flags != update.flags) { _flags = update.flags; _markFlagsDirty(); @@ -753,7 +753,7 @@ class SemanticsObject { /// spec: /// /// > A map literal is ordered: iterating over the keys and/or values of the maps always happens in the order the keys appeared in the source code. - final Map _roleManagers = {}; + final Map _roleManagers = {}; /// Detects the roles that this semantics object corresponds to and manages /// the lifecycles of [SemanticsObjectRole] objects. @@ -776,10 +776,10 @@ class SemanticsObject { } void _updateRole(Role role, bool enabled) { - RoleManager manager = _roleManagers[role]; + RoleManager? manager = _roleManagers[role]; if (enabled) { if (manager == null) { - manager = _roleFactories[role](this); + manager = _roleFactories[role]!(this); _roleManagers[role] = manager; } manager.update(); @@ -820,15 +820,16 @@ class SemanticsObject { /// [hasChildren], of [getOrCreateChildContainer]. void recomputePositionAndSize() { element.style - ..width = '${_rect.width}px' - ..height = '${_rect.height}px'; + ..width = '${_rect!.width}px' + ..height = '${_rect!.height}px'; - final html.Element containerElement = + final html.Element? containerElement = hasChildren ? getOrCreateChildContainer() : null; - final bool hasZeroRectOffset = _rect.top == 0.0 && _rect.left == 0.0; + final bool hasZeroRectOffset = _rect!.top == 0.0 && _rect!.left == 0.0; + final Float32List? transform = _transform; final bool hasIdentityTransform = - _transform == null || isIdentityFloat32ListTransform(_transform); + transform == null || isIdentityFloat32ListTransform(transform); if (hasZeroRectOffset && hasIdentityTransform && @@ -845,22 +846,22 @@ class SemanticsObject { return; } - Matrix4 effectiveTransform; + late Matrix4 effectiveTransform; bool effectiveTransformIsIdentity = true; if (!hasZeroRectOffset) { - if (_transform == null) { - final double left = _rect.left; - final double top = _rect.top; + if (transform == null) { + final double left = _rect!.left; + final double top = _rect!.top; effectiveTransform = Matrix4.translationValues(left, top, 0.0); effectiveTransformIsIdentity = left == 0.0 && top == 0.0; } else { // Clone to avoid mutating _transform. - effectiveTransform = Matrix4.fromFloat32List(_transform).clone() - ..translate(_rect.left, _rect.top, 0.0); + effectiveTransform = Matrix4.fromFloat32List(transform).clone() + ..translate(_rect!.left, _rect!.top, 0.0); effectiveTransformIsIdentity = effectiveTransform.isIdentity(); } } else if (!hasIdentityTransform) { - effectiveTransform = Matrix4.fromFloat32List(_transform); + effectiveTransform = Matrix4.fromFloat32List(transform!); effectiveTransformIsIdentity = false; } @@ -878,8 +879,8 @@ class SemanticsObject { if (!hasZeroRectOffset || verticalContainerAdjustment != 0.0 || horizontalContainerAdjustment != 0.0) { - final double translateX = -_rect.left + horizontalContainerAdjustment; - final double translateY = -_rect.top + verticalContainerAdjustment; + final double translateX = -_rect!.left + horizontalContainerAdjustment; + final double translateY = -_rect!.top + verticalContainerAdjustment; containerElement.style ..transformOrigin = '0 0 0' ..transform = 'translate(${translateX}px, ${translateY}px)'; @@ -891,7 +892,7 @@ class SemanticsObject { } } - Int32List _previousChildrenInTraversalOrder; + Int32List? _previousChildrenInTraversalOrder; /// Updates the traversal child list of [object] from the given [update]. /// @@ -901,9 +902,9 @@ class SemanticsObject { void _updateChildrenInTraversalOrder() { // Remove all children case. if (_childrenInTraversalOrder == null || - _childrenInTraversalOrder.isEmpty) { + _childrenInTraversalOrder!.isEmpty) { if (_previousChildrenInTraversalOrder == null || - _previousChildrenInTraversalOrder.isEmpty) { + _previousChildrenInTraversalOrder!.isEmpty) { // We must not have created a container element when child list is empty. assert(_childContainerElement == null); _previousChildrenInTraversalOrder = _childrenInTraversalOrder; @@ -914,26 +915,26 @@ class SemanticsObject { assert(_childContainerElement != null); // Remove all children from this semantics object. - final int len = _previousChildrenInTraversalOrder.length; + final int len = _previousChildrenInTraversalOrder!.length; for (int i = 0; i < len; i++) { - owner._detachObject(_previousChildrenInTraversalOrder[i]); + owner._detachObject(_previousChildrenInTraversalOrder![i]); } _previousChildrenInTraversalOrder = null; - _childContainerElement.remove(); + _childContainerElement!.remove(); _childContainerElement = null; _previousChildrenInTraversalOrder = _childrenInTraversalOrder; return; } - final html.Element containerElement = getOrCreateChildContainer(); + final html.Element? containerElement = getOrCreateChildContainer(); // Empty case. if (_previousChildrenInTraversalOrder == null || - _previousChildrenInTraversalOrder.isEmpty) { + _previousChildrenInTraversalOrder!.isEmpty) { _previousChildrenInTraversalOrder = _childrenInTraversalOrder; - for (int id in _previousChildrenInTraversalOrder) { + for (int id in _previousChildrenInTraversalOrder!) { final SemanticsObject child = owner.getOrCreateObject(id); - containerElement.append(child.element); + containerElement!.append(child.element); owner._attachObject(parent: this, child: child); } _previousChildrenInTraversalOrder = _childrenInTraversalOrder; @@ -954,34 +955,34 @@ class SemanticsObject { // The smallest of the two child list lengths. final int minLength = math.min( - _previousChildrenInTraversalOrder.length, - _childrenInTraversalOrder.length, + _previousChildrenInTraversalOrder!.length, + _childrenInTraversalOrder!.length, ); // Scan forward until first discrepancy. while (newIndex < minLength && - _previousChildrenInTraversalOrder[newIndex] == - _childrenInTraversalOrder[newIndex]) { + _previousChildrenInTraversalOrder![newIndex] == + _childrenInTraversalOrder![newIndex]) { intersectionIndicesNew.add(newIndex); intersectionIndicesOld.add(newIndex); newIndex += 1; } // If child lists are identical, do nothing. - if (_previousChildrenInTraversalOrder.length == - _childrenInTraversalOrder.length && - newIndex == _childrenInTraversalOrder.length) { + if (_previousChildrenInTraversalOrder!.length == + _childrenInTraversalOrder!.length && + newIndex == _childrenInTraversalOrder!.length) { return; } // If child lists are not identical, continue computing the intersection // between the two lists. - while (newIndex < _childrenInTraversalOrder.length) { + while (newIndex < _childrenInTraversalOrder!.length) { for (int oldIndex = 0; - oldIndex < _previousChildrenInTraversalOrder.length; + oldIndex < _previousChildrenInTraversalOrder!.length; oldIndex += 1) { - if (_previousChildrenInTraversalOrder[oldIndex] == - _childrenInTraversalOrder[newIndex]) { + if (_previousChildrenInTraversalOrder![oldIndex] == + _childrenInTraversalOrder![newIndex]) { intersectionIndicesNew.add(newIndex); intersectionIndicesOld.add(oldIndex); break; @@ -992,32 +993,32 @@ class SemanticsObject { // The longest sub-sequence in the old list maximizes the number of children // that do not need to be moved. - final List longestSequence = + final List longestSequence = longestIncreasingSubsequence(intersectionIndicesOld); final List stationaryIds = []; for (int i = 0; i < longestSequence.length; i += 1) { - stationaryIds.add(_previousChildrenInTraversalOrder[ - intersectionIndicesOld[longestSequence[i]]]); + stationaryIds.add(_previousChildrenInTraversalOrder![ + intersectionIndicesOld[longestSequence[i]!]]); } // Remove children that are no longer in the list. - for (int i = 0; i < _previousChildrenInTraversalOrder.length; i++) { + for (int i = 0; i < _previousChildrenInTraversalOrder!.length; i++) { if (!intersectionIndicesOld.contains(i)) { // Child not in the intersection. Must be removed. - final int childId = _previousChildrenInTraversalOrder[i]; + final int childId = _previousChildrenInTraversalOrder![i]; owner._detachObject(childId); } } - html.Element refNode; - for (int i = _childrenInTraversalOrder.length - 1; i >= 0; i -= 1) { - final int childId = _childrenInTraversalOrder[i]; + html.Element? refNode; + for (int i = _childrenInTraversalOrder!.length - 1; i >= 0; i -= 1) { + final int childId = _childrenInTraversalOrder![i]; final SemanticsObject child = owner.getOrCreateObject(childId); if (!stationaryIds.contains(childId)) { if (refNode == null) { - containerElement.append(child.element); + containerElement!.append(child.element); } else { - containerElement.insertBefore(child.element, refNode); + containerElement!.insertBefore(child.element, refNode); } owner._attachObject(parent: this, child: child); } else { @@ -1033,8 +1034,8 @@ class SemanticsObject { String toString() { if (assertionsEnabled) { final String children = _childrenInTraversalOrder != null && - _childrenInTraversalOrder.isNotEmpty - ? '[${_childrenInTraversalOrder.join(', ')}]' + _childrenInTraversalOrder!.isNotEmpty + ? '[${_childrenInTraversalOrder!.join(', ')}]' : ''; return '$runtimeType(#$id, children: $children)'; } else { @@ -1085,7 +1086,7 @@ class EngineSemanticsOwner { return _instance ??= EngineSemanticsOwner._(); } - static EngineSemanticsOwner _instance; + static EngineSemanticsOwner? _instance; /// Disables semantics and uninitializes the singleton [instance]. /// @@ -1096,24 +1097,24 @@ class EngineSemanticsOwner { if (_instance == null) { return; } - _instance.semanticsEnabled = false; + _instance!.semanticsEnabled = false; _instance = null; } - final Map _semanticsTree = {}; + final Map _semanticsTree = {}; /// Map [SemanticsObject.id] to parent [SemanticsObject] it was attached to /// this frame. - Map _attachments = {}; + Map _attachments = {}; /// Declares that the [child] must be attached to the [parent]. /// /// Attachments take precendence over detachments (see [_detachObject]). This /// allows the same node to be detached from one parent in the tree and /// reattached to another parent. - void _attachObject({SemanticsObject parent, SemanticsObject child}) { - assert(child != null); - assert(parent != null); + void _attachObject({required SemanticsObject parent, required SemanticsObject child}) { + assert(child != null); // ignore: unnecessary_null_comparison + assert(parent != null); // ignore: unnecessary_null_comparison child._parent = parent; _attachments[child.id] = parent; } @@ -1122,16 +1123,16 @@ class EngineSemanticsOwner { /// /// The objects in this list will be detached permanently unless they are /// reattached via the [_attachObject] method. - List _detachments = []; + List _detachments = []; /// Declares that the [SemanticsObject] with the given [id] was detached from /// its current parent object. /// /// The object will be detached permanently unless it is reattached via the /// [_attachObject] method. - void _detachObject(int id) { + void _detachObject(int? id) { assert(_semanticsTree.containsKey(id)); - final SemanticsObject object = _semanticsTree[id]; + final SemanticsObject? object = _semanticsTree[id]; _detachments.add(object); } @@ -1151,8 +1152,8 @@ class EngineSemanticsOwner { /// the one-time callbacks scheduled via the [addOneTimePostUpdateCallback] /// method. void _finalizeTree() { - for (SemanticsObject object in _detachments) { - final SemanticsObject parent = _attachments[object.id]; + for (SemanticsObject? object in _detachments) { + final SemanticsObject? parent = _attachments[object!.id]; if (parent == null) { // Was not reparented and is removed permanently from the tree. _semanticsTree.remove(object.id); @@ -1163,8 +1164,8 @@ class EngineSemanticsOwner { assert(object.element.parent == parent._childContainerElement); } } - _detachments = []; - _attachments = {}; + _detachments = []; + _attachments = {}; if (_oneTimePostUpdateCallbacks.isNotEmpty) { for (ui.VoidCallback callback in _oneTimePostUpdateCallbacks) { @@ -1177,8 +1178,8 @@ class EngineSemanticsOwner { /// Returns the entire semantics tree for testing. /// /// Works only in debug mode. - Map get debugSemanticsTree { - Map result; + Map? get debugSemanticsTree { + Map? result; assert(() { result = _semanticsTree; return true; @@ -1187,7 +1188,7 @@ class EngineSemanticsOwner { } /// The top-level DOM element of the semantics DOM element tree. - html.Element _rootSemanticsElement; + html.Element? _rootSemanticsElement; TimestampFunction _now = () => DateTime.now(); @@ -1225,7 +1226,7 @@ class EngineSemanticsOwner { _gestureMode = GestureMode.pointerEvents; _notifyGestureModeListeners(); } - final List keys = _semanticsTree.keys.toList(); + final List keys = _semanticsTree.keys.toList(); final int len = keys.length; for (int i = 0; i < len; i++) { _detachObject(keys[i]); @@ -1247,7 +1248,7 @@ class EngineSemanticsOwner { /// The default mode is [AccessibilityMode.unknown]. AccessibilityMode get mode => _mode; set mode(AccessibilityMode value) { - assert(value != null); + assert(value != null); // ignore: unnecessary_null_comparison _mode = value; } @@ -1262,12 +1263,12 @@ class EngineSemanticsOwner { GestureMode get gestureMode => _gestureMode; GestureMode _gestureMode = GestureMode.browserGestures; - AlarmClock _gestureModeClock; + AlarmClock? _gestureModeClock; - AlarmClock _getGestureModeClock() { + AlarmClock? _getGestureModeClock() { if (_gestureModeClock == null) { _gestureModeClock = AlarmClock(_now); - _gestureModeClock.callback = () { + _gestureModeClock!.callback = () { if (_gestureMode == GestureMode.browserGestures) { return; } @@ -1286,7 +1287,7 @@ class EngineSemanticsOwner { /// detected by the browser. Flutter-detected gestures have higher precedence. void _temporarilyDisableBrowserGestureMode() { const Duration _kDebounceThreshold = Duration(milliseconds: 500); - _getGestureModeClock().datetime = _now().add(_kDebounceThreshold); + _getGestureModeClock()!.datetime = _now().add(_kDebounceThreshold); if (_gestureMode != GestureMode.pointerEvents) { _gestureMode = GestureMode.pointerEvents; _notifyGestureModeListeners(); @@ -1355,14 +1356,14 @@ class EngineSemanticsOwner { /// Callbacks are called synchronously. HTML DOM updates made in a callback /// take effect in the current animation frame and/or the current message loop /// event. - List _gestureModeListeners = []; + List _gestureModeListeners = []; /// Calls the [callback] every time the current [GestureMode] changes. /// /// The callback is called synchronously. HTML DOM updates made in the /// callback take effect in the current animation frame and/or the current /// message loop event. - void addGestureModeListener(GestureModeCallback callback) { + void addGestureModeListener(GestureModeCallback? callback) { _gestureModeListeners.add(callback); } @@ -1370,14 +1371,14 @@ class EngineSemanticsOwner { /// /// The passed [callback] must be the exact same object as the one passed to /// [addGestureModeListener]. - void removeGestureModeListener(GestureModeCallback callback) { + void removeGestureModeListener(GestureModeCallback? callback) { assert(_gestureModeListeners.contains(callback)); _gestureModeListeners.remove(callback); } void _notifyGestureModeListeners() { for (int i = 0; i < _gestureModeListeners.length; i++) { - _gestureModeListeners[i](_gestureMode); + _gestureModeListeners[i]!(_gestureMode); } } @@ -1413,7 +1414,7 @@ class EngineSemanticsOwner { /// Looks up a [SemanticsObject] in the semantics tree by ID, or creates a new /// instance if it does not exist. SemanticsObject getOrCreateObject(int id) { - SemanticsObject object = _semanticsTree[id]; + SemanticsObject? object = _semanticsTree[id]; if (object == null) { object = SemanticsObject(id, this); _semanticsTree[id] = object; @@ -1422,19 +1423,19 @@ class EngineSemanticsOwner { } /// Updates the semantics tree from data in the [uiUpdate]. - void updateSemantics(ui.SemanticsUpdate/*!*/ uiUpdate) { + void updateSemantics(ui.SemanticsUpdate uiUpdate) { if (!_semanticsEnabled) { return; } - final SemanticsUpdate update = uiUpdate; - for (SemanticsNodeUpdate nodeUpdate in update._nodeUpdates) { + final SemanticsUpdate update = uiUpdate as SemanticsUpdate; + for (SemanticsNodeUpdate nodeUpdate in update._nodeUpdates!) { final SemanticsObject object = getOrCreateObject(nodeUpdate.id); object.updateWith(nodeUpdate); } if (_rootSemanticsElement == null) { - final SemanticsObject root = _semanticsTree[0]; + final SemanticsObject root = _semanticsTree[0]!; _rootSemanticsElement = root.element; // We render semantics inside the glasspane for proper focus and event // handling. If semantics is behind the glasspane, the phone will disable @@ -1447,8 +1448,8 @@ class EngineSemanticsOwner { // pointer events through to the semantics tree. However, for platform // views, the pointer events will not pass through, and will be handled // by the platform view. - domRenderer.glassPaneElement - .insertBefore(_rootSemanticsElement, domRenderer.sceneHostElement); + domRenderer.glassPaneElement! + .insertBefore(_rootSemanticsElement!, domRenderer.sceneHostElement); } _finalizeTree(); @@ -1456,13 +1457,13 @@ class EngineSemanticsOwner { assert(_semanticsTree.containsKey(0)); // must contain root node assert(() { // Validate tree - _semanticsTree.forEach((int id, SemanticsObject object) { - assert(id == object.id); + _semanticsTree.forEach((int? id, SemanticsObject? object) { + assert(id == object!.id); // Ensure child ID list is consistent with the parent-child // relationship of the semantics tree. - if (object._childrenInTraversalOrder != null) { - for (int childId in object._childrenInTraversalOrder) { - final SemanticsObject child = _semanticsTree[childId]; + if (object!._childrenInTraversalOrder != null) { + for (int childId in object._childrenInTraversalOrder!) { + final SemanticsObject? child = _semanticsTree[childId]; if (child == null) { throw AssertionError('Child #$childId is missing in the tree.'); } @@ -1474,18 +1475,16 @@ class EngineSemanticsOwner { if (!identical(child._parent, object)) { throw AssertionError( 'Parent #${object.id} has child #$childId. However, the ' - 'child is attached to #${child._parent.id}.'); + 'child is attached to #${child._parent!.id}.'); } } } }); // Validate that all updates were applied - for (SemanticsNodeUpdate update in update._nodeUpdates) { + for (SemanticsNodeUpdate update in update._nodeUpdates!) { // Node was added to the tree. assert(_semanticsTree.containsKey(update.id)); - // We created a DOM element for it. - assert(_semanticsTree[update.id].element != null); } return true; @@ -1535,7 +1534,7 @@ List longestIncreasingSubsequence(List list) { } } // Reconstruct the longest subsequence - final List seq = List(longest); + final List seq = List.filled(longest, 0); int k = mins[longest]; for (int i = longest - 1; i >= 0; i--) { seq[i] = k; diff --git a/lib/web_ui/lib/src/engine/semantics/semantics_helper.dart b/lib/web_ui/lib/src/engine/semantics/semantics_helper.dart index cc77d76498ba1..b9eff3e892ce6 100644 --- a/lib/web_ui/lib/src/engine/semantics/semantics_helper.dart +++ b/lib/web_ui/lib/src/engine/semantics/semantics_helper.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// The maximum [semanticsActivationAttempts] before we give up waiting for @@ -107,10 +107,10 @@ class DesktopSemanticsEnabler extends SemanticsEnabler { /// request to activate semantics, and a second time by Flutter's gesture /// recognizers. @visibleForTesting - Timer semanticsActivationTimer; + Timer? semanticsActivationTimer; /// A temporary placeholder used to capture a request to activate semantics. - html.Element _semanticsPlaceholder; + html.Element? _semanticsPlaceholder; /// The number of events we processed that could potentially activate /// semantics. @@ -128,7 +128,7 @@ class DesktopSemanticsEnabler extends SemanticsEnabler { @override bool tryEnableSemantics(html.Event event) { if (_schedulePlaceholderRemoval) { - _semanticsPlaceholder.remove(); + _semanticsPlaceholder!.remove(); _semanticsPlaceholder = null; semanticsActivationTimer = null; return true; @@ -190,11 +190,11 @@ class DesktopSemanticsEnabler extends SemanticsEnabler { @override html.Element prepareAccesibilityPlaceholder() { - _semanticsPlaceholder = html.Element.tag('flt-semantics-placeholder'); + final html.Element placeholder = _semanticsPlaceholder = html.Element.tag('flt-semantics-placeholder'); // Only listen to "click" because other kinds of events are reported via // PointerBinding. - _semanticsPlaceholder.addEventListener('click', (html.Event event) { + placeholder.addEventListener('click', (html.Event event) { tryEnableSemantics(event); }, true); @@ -203,18 +203,18 @@ class DesktopSemanticsEnabler extends SemanticsEnabler { // page receives focus. 'tab-index' makes sure the button is the first // target of tab. 'aria-label' is used to define the placeholder message // to the assistive technology user. - _semanticsPlaceholder + placeholder ..setAttribute('role', 'button') ..setAttribute('aria-live', 'true') ..setAttribute('tabindex', '0') ..setAttribute('aria-label', placeholderMessage); - _semanticsPlaceholder.style + placeholder.style ..position = 'absolute' ..left = '-1px' ..top = '-1px' ..width = '1px' ..height = '1px'; - return _semanticsPlaceholder; + return placeholder; } } @@ -230,10 +230,10 @@ class MobileSemanticsEnabler extends SemanticsEnabler { /// a request to activate semantics, and a second time by Flutter's gesture /// recognizers. @visibleForTesting - Timer semanticsActivationTimer; + Timer? semanticsActivationTimer; /// A temporary placeholder used to capture a request to activate semantics. - html.Element _semanticsPlaceholder; + html.Element? _semanticsPlaceholder; /// The number of events we processed that could potentially activate /// semantics. @@ -259,7 +259,7 @@ class MobileSemanticsEnabler extends SemanticsEnabler { final bool removeNow = (browserEngine != BrowserEngine.webkit || event.type == 'touchend'); if (removeNow) { - _semanticsPlaceholder.remove(); + _semanticsPlaceholder!.remove(); _semanticsPlaceholder = null; semanticsActivationTimer = null; } @@ -325,12 +325,12 @@ class MobileSemanticsEnabler extends SemanticsEnabler { switch (event.type) { case 'click': - final html.MouseEvent click = event; + final html.MouseEvent click = event as html.MouseEvent; activationPoint = click.offset; break; case 'touchstart': case 'touchend': - final html.TouchEvent touch = event; + final html.TouchEvent touch = event as html.TouchEvent; activationPoint = touch.changedTouches.first.client; break; default: @@ -338,16 +338,14 @@ class MobileSemanticsEnabler extends SemanticsEnabler { return true; } - assert(activationPoint != null); - final html.Rectangle activatingElementRect = - domRenderer.glassPaneElement.getBoundingClientRect(); + domRenderer.glassPaneElement!.getBoundingClientRect(); final double midX = activatingElementRect.left + - (activatingElementRect.right - activatingElementRect.left) / 2; + (activatingElementRect.right - activatingElementRect.left) / 2 as double; final double midY = activatingElementRect.top + - (activatingElementRect.bottom - activatingElementRect.top) / 2; - final double deltaX = activationPoint.x - midX; - final double deltaY = activationPoint.y - midY; + (activatingElementRect.bottom - activatingElementRect.top) / 2 as double; + final double deltaX = activationPoint.x - midX as double; + final double deltaY = activationPoint.y - midY as double; final double deltaSquared = deltaX * deltaX + deltaY * deltaY; if (deltaSquared < 1.0) { safariEnableConditionPassed = true; @@ -369,24 +367,24 @@ class MobileSemanticsEnabler extends SemanticsEnabler { @override html.Element prepareAccesibilityPlaceholder() { - _semanticsPlaceholder = html.Element.tag('flt-semantics-placeholder'); + final html.Element placeholder = _semanticsPlaceholder = html.Element.tag('flt-semantics-placeholder'); // Only listen to "click" because other kinds of events are reported via // PointerBinding. - _semanticsPlaceholder.addEventListener('click', (html.Event event) { + placeholder.addEventListener('click', (html.Event event) { tryEnableSemantics(event); }, true); - _semanticsPlaceholder + placeholder ..setAttribute('role', 'button') ..setAttribute('aria-label', placeholderMessage); - _semanticsPlaceholder.style + placeholder.style ..position = 'absolute' ..left = '0' ..top = '0' ..right = '0' ..bottom = '0'; - return _semanticsPlaceholder; + return placeholder; } } diff --git a/lib/web_ui/lib/src/engine/semantics/tappable.dart b/lib/web_ui/lib/src/engine/semantics/tappable.dart index e60c9881918e5..cd416e106cf82 100644 --- a/lib/web_ui/lib/src/engine/semantics/tappable.dart +++ b/lib/web_ui/lib/src/engine/semantics/tappable.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Listens to HTML "click" gestures detected by the browser. @@ -15,7 +15,7 @@ class Tappable extends RoleManager { Tappable(SemanticsObject semanticsObject) : super(Role.tappable, semanticsObject); - html.EventListener _clickListener; + html.EventListener? _clickListener; @override void update() { diff --git a/lib/web_ui/lib/src/engine/semantics/text_field.dart b/lib/web_ui/lib/src/engine/semantics/text_field.dart index 5018d8d2d5aa2..bc5bf16116e5a 100644 --- a/lib/web_ui/lib/src/engine/semantics/text_field.dart +++ b/lib/web_ui/lib/src/engine/semantics/text_field.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Text editing used by accesibility mode. @@ -46,11 +46,10 @@ class SemanticsTextEditingStrategy extends DefaultTextEditingStrategy { @override void initializeTextEditing(InputConfiguration inputConfig, - {_OnChangeCallback onChange, _OnActionCallback onAction}) { + {_OnChangeCallback? onChange, _OnActionCallback? onAction}) { // In accesibilty mode, the user of this class is supposed to insert the // [domElement] on their own. Let's make sure they did. - assert(domElement != null); - assert(html.document.body.contains(domElement)); + assert(html.document.body!.contains(domElement)); isEnabled = true; _inputConfiguration = inputConfig; @@ -61,7 +60,7 @@ class SemanticsTextEditingStrategy extends DefaultTextEditingStrategy { } @override - void setEditingState(EditingState editingState) { + void setEditingState(EditingState? editingState) { super.setEditingState(editingState); // Refocus after setting editing state. @@ -91,8 +90,8 @@ class TextField extends RoleManager { _setupDomElement(); } - SemanticsTextEditingStrategy textEditingElement; - html.Element get _textFieldElement => textEditingElement.domElement; + SemanticsTextEditingStrategy? textEditingElement; + html.Element get _textFieldElement => textEditingElement!.domElement; void _setupDomElement() { // On iOS, even though the semantic text field is transparent, the cursor @@ -119,8 +118,8 @@ class TextField extends RoleManager { // and size of the parent `` element. ..top = '0' ..left = '0' - ..width = '${semanticsObject.rect.width}px' - ..height = '${semanticsObject.rect.height}px'; + ..width = '${semanticsObject.rect!.width}px' + ..height = '${semanticsObject.rect!.height}px'; semanticsObject.element.append(_textFieldElement); switch (browserEngine) { @@ -160,18 +159,18 @@ class TextField extends RoleManager { /// events are present regardless of whether accessibility is enabled or not, /// this mode is always enabled. void _initializeForWebkit() { - num lastTouchStartOffsetX; - num lastTouchStartOffsetY; + num? lastTouchStartOffsetX; + num? lastTouchStartOffsetY; _textFieldElement.addEventListener('touchstart', (html.Event event) { textEditing.useCustomEditableElement(textEditingElement); - final html.TouchEvent touchEvent = event; + final html.TouchEvent touchEvent = event as html.TouchEvent; lastTouchStartOffsetX = touchEvent.changedTouches.last.client.x; lastTouchStartOffsetY = touchEvent.changedTouches.last.client.y; }, true); _textFieldElement.addEventListener('touchend', (html.Event event) { - final html.TouchEvent touchEvent = event; + final html.TouchEvent touchEvent = event as html.TouchEvent; if (lastTouchStartOffsetX != null) { assert(lastTouchStartOffsetY != null); diff --git a/lib/web_ui/lib/src/engine/services/buffers.dart b/lib/web_ui/lib/src/engine/services/buffers.dart index aff4c83454082..c8778a003e21b 100644 --- a/lib/web_ui/lib/src/engine/services/buffers.dart +++ b/lib/web_ui/lib/src/engine/services/buffers.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; abstract class _TypedDataBuffer extends ListBase { @@ -88,7 +88,7 @@ abstract class _TypedDataBuffer extends ListBase { /// least [start] elements, and if [end] is specified, it must be greater than /// or equal to [start] and [values] must have at least [end] elements. @override - void addAll(Iterable values, [int start = 0, int end]) { + void addAll(Iterable values, [int start = 0, int? end]) { RangeError.checkNotNegative(start, 'start'); if (end != null && start > end) { throw RangeError.range(end, start, null, 'end'); @@ -107,7 +107,7 @@ abstract class _TypedDataBuffer extends ListBase { /// least [start] elements, and if [end] is specified, it must be greater than /// or equal to [start] and [values] must have at least [end] elements. @override - void insertAll(int index, Iterable values, [int start = 0, int end]) { + void insertAll(int index, Iterable values, [int start = 0, int? end]) { RangeError.checkValidIndex(index, this, 'index', _length + 1); RangeError.checkNotNegative(start, 'start'); if (end != null) { @@ -167,11 +167,11 @@ abstract class _TypedDataBuffer extends ListBase { } // Reverses the range [start..end) of buffer. - static void _reverse(List buffer, int start, int end) { + static void _reverse(List buffer, int start, int end) { end--; // Point to last element, not after last element. while (start < end) { - final Object first = buffer[start]; - final Object last = buffer[end]; + final Object? first = buffer[start]; + final Object? last = buffer[end]; buffer[end] = first; buffer[start] = last; start++; @@ -184,8 +184,8 @@ abstract class _TypedDataBuffer extends ListBase { /// This allows [addAll] and [insertAll] to share implementation without a /// subclass unexpectedly overriding both when it intended to only override /// [addAll]. - void _addAll(Iterable values, [int start = 0, int end]) { - if (values is List) { + void _addAll(Iterable values, [int start = 0, int? end]) { + if (values is List) { end ??= values.length; } @@ -212,13 +212,10 @@ abstract class _TypedDataBuffer extends ListBase { /// Like [insertAll], but with a guaranteed non-`null` [start] and [end]. void _insertKnownLength(int index, Iterable values, int start, int end) { - if (values is List) { - end ??= values.length; - if (start > values.length || end > values.length) { - throw StateError('Too few elements'); - } - } else { - assert(end != null); + assert(values != null); // ignore: unnecessary_null_comparison + assert(end != null); // ignore: unnecessary_null_comparison + if (start > values.length || end > values.length) { + throw StateError('Too few elements'); } final int valuesLength = end - start; @@ -268,7 +265,7 @@ abstract class _TypedDataBuffer extends ListBase { /// be. If [requiredCapacity] is not null, it will be at least that /// size. It will always have at least have double the capacity of /// the current buffer. - List _createBiggerBuffer(int requiredCapacity) { + List _createBiggerBuffer(int? requiredCapacity) { int newLength = _buffer.length * 2; if (requiredCapacity != null && newLength < requiredCapacity) { newLength = requiredCapacity; diff --git a/lib/web_ui/lib/src/engine/services/message_codec.dart b/lib/web_ui/lib/src/engine/services/message_codec.dart index 0784135b145ca..d4e4a31941bff 100644 --- a/lib/web_ui/lib/src/engine/services/message_codec.dart +++ b/lib/web_ui/lib/src/engine/services/message_codec.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A message encoding/decoding mechanism. @@ -18,7 +18,7 @@ abstract class MessageCodec { /// Encodes the specified [message] in binary. /// /// Returns null if the message is null. - ByteData encodeMessage(T message); + ByteData? encodeMessage(T message); /// Decodes the specified [message] from binary. /// @@ -31,6 +31,7 @@ abstract class MessageCodec { class MethodCall { /// Creates a [MethodCall] representing the invocation of [method] with the /// specified [arguments]. + // ignore: unnecessary_null_comparison const MethodCall(this.method, [this.arguments]) : assert(method != null); /// The name of the method to be called. @@ -57,10 +58,10 @@ class MethodCall { /// between Flutter and platform plugins. abstract class MethodCodec { /// Encodes the specified [methodCall] into binary. - ByteData encodeMethodCall(MethodCall methodCall); + ByteData? encodeMethodCall(MethodCall methodCall); /// Decodes the specified [methodCall] from binary. - MethodCall decodeMethodCall(ByteData methodCall); + MethodCall decodeMethodCall(ByteData? methodCall); /// Decodes the specified result [envelope] from binary. /// @@ -69,14 +70,14 @@ abstract class MethodCodec { dynamic decodeEnvelope(ByteData envelope); /// Encodes a successful [result] into a binary envelope. - ByteData encodeSuccessEnvelope(dynamic result); + ByteData? encodeSuccessEnvelope(dynamic result); /// Encodes an error result into a binary envelope. /// /// The specified error [code], human-readable error [message], and error /// [details] correspond to the fields of [PlatformException]. - ByteData encodeErrorEnvelope( - {@required String code, String message, dynamic details}); + ByteData? encodeErrorEnvelope( + {required String code, String? message, dynamic details}); } /// Thrown to indicate that a platform interaction failed in the platform @@ -97,16 +98,16 @@ class PlatformException implements Exception { /// [message], and with the optional error [details] which must be a valid /// value for the [MethodCodec] involved in the interaction. PlatformException({ - @required this.code, + required this.code, this.message, this.details, - }) : assert(code != null); + }) : assert(code != null); // ignore: unnecessary_null_comparison /// An error code. final String code; /// A human-readable error message, possibly null. - final String message; + final String? message; /// Error details, possibly null. final dynamic details; @@ -131,7 +132,7 @@ class MissingPluginException implements Exception { MissingPluginException([this.message]); /// A human-readable error message, possibly null. - final String message; + final String? message; @override String toString() => 'MissingPluginException($message)'; diff --git a/lib/web_ui/lib/src/engine/services/message_codecs.dart b/lib/web_ui/lib/src/engine/services/message_codecs.dart index 42537f7106694..9f85cb95ecf4f 100644 --- a/lib/web_ui/lib/src/engine/services/message_codecs.dart +++ b/lib/web_ui/lib/src/engine/services/message_codecs.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// [MessageCodec] with unencoded binary messages represented using [ByteData]. @@ -31,17 +31,11 @@ class StringCodec implements MessageCodec { @override String decodeMessage(ByteData message) { - if (message == null) { - return null; - } return utf8.decoder.convert(message.buffer.asUint8List()); } @override ByteData encodeMessage(String message) { - if (message == null) { - return null; - } final Uint8List encoded = utf8.encoder.convert(message); return encoded.buffer.asByteData(); } @@ -74,7 +68,7 @@ class JSONMessageCodec implements MessageCodec { const JSONMessageCodec(); @override - ByteData encodeMessage(dynamic message) { + ByteData? encodeMessage(dynamic message) { if (message == null) { return null; } @@ -82,7 +76,7 @@ class JSONMessageCodec implements MessageCodec { } @override - dynamic decodeMessage(ByteData message) { + dynamic decodeMessage(ByteData? message) { if (message == null) { return message; } @@ -113,7 +107,7 @@ class JSONMethodCodec implements MethodCodec { const JSONMethodCodec(); @override - ByteData encodeMethodCall(MethodCall call) { + ByteData? encodeMethodCall(MethodCall call) { return const JSONMessageCodec().encodeMessage({ 'method': call.method, 'args': call.arguments, @@ -121,7 +115,7 @@ class JSONMethodCodec implements MethodCodec { } @override - MethodCall decodeMethodCall(ByteData methodCall) { + MethodCall decodeMethodCall(ByteData? methodCall) { final dynamic decoded = const JSONMessageCodec().decodeMessage(methodCall); if (decoded is! Map) { throw FormatException('Expected method call Map, got $decoded'); @@ -156,14 +150,14 @@ class JSONMethodCodec implements MethodCodec { } @override - ByteData encodeSuccessEnvelope(dynamic result) { + ByteData? encodeSuccessEnvelope(dynamic result) { return const JSONMessageCodec().encodeMessage([result]); } @override - ByteData encodeErrorEnvelope( - {@required String code, String message, dynamic details}) { - assert(code != null); + ByteData? encodeErrorEnvelope( + {required String code, String? message, dynamic details}) { + assert(code != null); // ignore: unnecessary_null_comparison return const JSONMessageCodec() .encodeMessage([code, message, details]); } @@ -271,7 +265,7 @@ class StandardMessageCodec implements MessageCodec { const StandardMessageCodec(); @override - ByteData encodeMessage(dynamic message) { + ByteData? encodeMessage(dynamic message) { if (message == null) { return null; } @@ -281,7 +275,7 @@ class StandardMessageCodec implements MessageCodec { } @override - dynamic decodeMessage(ByteData message) { + dynamic decodeMessage(ByteData? message) { if (message == null) { return null; } @@ -326,7 +320,7 @@ class StandardMessageCodec implements MessageCodec { buffer.putUint8(_valueString); final List bytes = utf8.encoder.convert(value); writeSize(buffer, bytes.length); - buffer.putUint8List(bytes); + buffer.putUint8List(bytes as Uint8List); } else if (value is Uint8List) { buffer.putUint8(_valueUint8List); writeSize(buffer, value.length); @@ -428,9 +422,9 @@ class StandardMessageCodec implements MessageCodec { break; case _valueList: final int length = readSize(buffer); - result = List(length); + result = []; for (int i = 0; i < length; i++) { - result[i] = readValue(buffer); + result.add(readValue(buffer)); } break; case _valueMap: @@ -517,8 +511,8 @@ class StandardMethodCodec implements MethodCodec { } @override - MethodCall decodeMethodCall(ByteData methodCall) { - final ReadBuffer buffer = ReadBuffer(methodCall); + MethodCall decodeMethodCall(ByteData? methodCall) { + final ReadBuffer buffer = ReadBuffer(methodCall!); final dynamic method = messageCodec.readValue(buffer); final dynamic arguments = messageCodec.readValue(buffer); if (method is String && !buffer.hasRemaining) @@ -537,7 +531,7 @@ class StandardMethodCodec implements MethodCodec { @override ByteData encodeErrorEnvelope( - {@required String code, String message, dynamic details}) { + {required String code, String? message, dynamic details}) { final WriteBuffer buffer = WriteBuffer(); buffer.putUint8(1); messageCodec.writeValue(buffer, code); diff --git a/lib/web_ui/lib/src/engine/services/serialization.dart b/lib/web_ui/lib/src/engine/services/serialization.dart index b38ae180976b9..431864a25eb73 100644 --- a/lib/web_ui/lib/src/engine/services/serialization.dart +++ b/lib/web_ui/lib/src/engine/services/serialization.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 part of engine; /// Write-only buffer for incrementally building a [ByteData] instance. @@ -13,47 +12,57 @@ part of engine; /// The byte order used is [Endian.host] throughout. class WriteBuffer { /// Creates an interface for incrementally building a [ByteData] instance. - WriteBuffer() { - _buffer = Uint8Buffer(); - _eightBytes = ByteData(8); - _eightBytesAsList = _eightBytes.buffer.asUint8List(); + factory WriteBuffer() { + final Uint8Buffer buffer = Uint8Buffer(); + final ByteData eightBytes = ByteData(8); + final Uint8List eightBytesAsList = eightBytes.buffer.asUint8List(); + return WriteBuffer._(buffer, eightBytes, eightBytesAsList); } - Uint8Buffer _buffer; - ByteData _eightBytes; - Uint8List _eightBytesAsList; + WriteBuffer._(this._buffer, this._eightBytes, this._eightBytesAsList); + + bool _debugFinalized = false; + final Uint8Buffer _buffer; + final ByteData _eightBytes; + final Uint8List _eightBytesAsList; /// Write a Uint8 into the buffer. void putUint8(int byte) { + assert(!_debugFinalized); _buffer.add(byte); } /// Write a Uint16 into the buffer. void putUint16(int value) { + assert(!_debugFinalized); _eightBytes.setUint16(0, value, Endian.host); _buffer.addAll(_eightBytesAsList, 0, 2); } /// Write a Uint32 into the buffer. void putUint32(int value) { + assert(!_debugFinalized); _eightBytes.setUint32(0, value, Endian.host); _buffer.addAll(_eightBytesAsList, 0, 4); } /// Write an Int32 into the buffer. void putInt32(int value) { + assert(!_debugFinalized); _eightBytes.setInt32(0, value, Endian.host); _buffer.addAll(_eightBytesAsList, 0, 4); } /// Write an Int64 into the buffer. void putInt64(int value) { + assert(!_debugFinalized); _eightBytes.setInt64(0, value, Endian.host); _buffer.addAll(_eightBytesAsList, 0, 8); } /// Write an Float64 into the buffer. void putFloat64(double value) { + assert(!_debugFinalized); _alignTo(8); _eightBytes.setFloat64(0, value, Endian.host); _buffer.addAll(_eightBytesAsList); @@ -61,11 +70,13 @@ class WriteBuffer { /// Write all the values from a [Uint8List] into the buffer. void putUint8List(Uint8List list) { + assert(!_debugFinalized); _buffer.addAll(list); } /// Write all the values from a [Int32List] into the buffer. void putInt32List(Int32List list) { + assert(!_debugFinalized); _alignTo(4); _buffer .addAll(list.buffer.asUint8List(list.offsetInBytes, 4 * list.length)); @@ -73,6 +84,7 @@ class WriteBuffer { /// Write all the values from an [Int64List] into the buffer. void putInt64List(Int64List list) { + assert(!_debugFinalized); _alignTo(8); _buffer .addAll(list.buffer.asUint8List(list.offsetInBytes, 8 * list.length)); @@ -80,6 +92,7 @@ class WriteBuffer { /// Write all the values from a [Float64List] into the buffer. void putFloat64List(Float64List list) { + assert(!_debugFinalized); _alignTo(8); _buffer .addAll(list.buffer.asUint8List(list.offsetInBytes, 8 * list.length)); @@ -96,8 +109,8 @@ class WriteBuffer { /// Finalize and return the written [ByteData]. ByteData done() { + _debugFinalized = true; final ByteData result = _buffer.buffer.asByteData(0, _buffer.lengthInBytes); - _buffer = null; return result; } } @@ -107,7 +120,7 @@ class WriteBuffer { /// The byte order used is [Endian.host] throughout. class ReadBuffer { /// Creates a [ReadBuffer] for reading from the specified [data]. - ReadBuffer(this.data) : assert(data != null); + ReadBuffer(this.data) : assert(data != null); // ignore: unnecessary_null_comparison /// The underlying data being read. final ByteData data; diff --git a/lib/web_ui/lib/src/engine/shader.dart b/lib/web_ui/lib/src/engine/shader.dart index d642d6c3f31c2..cdce61daf2bb5 100644 --- a/lib/web_ui/lib/src/engine/shader.dart +++ b/lib/web_ui/lib/src/engine/shader.dart @@ -2,25 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; bool _offsetIsValid(ui.Offset offset) { - assert(offset != null, 'Offset argument was null.'); + assert(offset != null, 'Offset argument was null.'); // ignore: unnecessary_null_comparison assert(!offset.dx.isNaN && !offset.dy.isNaN, 'Offset argument contained a NaN value.'); return true; } bool _matrix4IsValid(Float32List matrix4) { - assert(matrix4 != null, 'Matrix4 argument was null.'); + assert(matrix4 != null, 'Matrix4 argument was null.'); // ignore: unnecessary_null_comparison assert(matrix4.length == 16, 'Matrix4 must have 16 entries.'); return true; } abstract class EngineShader { /// Create a shader for use in the Skia backend. - js.JsObject createSkiaShader(); + js.JsObject? createSkiaShader(); } abstract class EngineGradient implements ui.Gradient, EngineShader { @@ -28,7 +28,7 @@ abstract class EngineGradient implements ui.Gradient, EngineShader { EngineGradient._(); /// Creates a fill style to be used in painting. - Object createPaintStyle(html.CanvasRenderingContext2D ctx); + Object createPaintStyle(html.CanvasRenderingContext2D? ctx); List webOnlySerializeToCssPaint() { throw UnsupportedError('CSS paint not implemented for this shader type'); @@ -39,10 +39,10 @@ class GradientSweep extends EngineGradient { GradientSweep(this.center, this.colors, this.colorStops, this.tileMode, this.startAngle, this.endAngle, this.matrix4) : assert(_offsetIsValid(center)), - assert(colors != null), - assert(tileMode != null), - assert(startAngle != null), - assert(endAngle != null), + assert(colors != null), // ignore: unnecessary_null_comparison + assert(tileMode != null), // ignore: unnecessary_null_comparison + assert(startAngle != null), // ignore: unnecessary_null_comparison + assert(endAngle != null), // ignore: unnecessary_null_comparison assert(startAngle < endAngle), assert(matrix4 == null || _matrix4IsValid(matrix4)), super._() { @@ -50,17 +50,17 @@ class GradientSweep extends EngineGradient { } @override - Object createPaintStyle(html.CanvasRenderingContext2D ctx) { + Object createPaintStyle(html.CanvasRenderingContext2D? ctx) { throw UnimplementedError(); } final ui.Offset center; final List colors; - final List colorStops; + final List? colorStops; final ui.TileMode tileMode; final double startAngle; final double endAngle; - final Float32List matrix4; + final Float32List? matrix4; @override js.JsObject createSkiaShader() { @@ -68,7 +68,7 @@ class GradientSweep extends EngineGradient { } } -void _validateColorStops(List colors, List colorStops) { +void _validateColorStops(List colors, List? colorStops) { if (colorStops == null) { if (colors.length != 2) throw ArgumentError( @@ -87,11 +87,11 @@ class GradientLinear extends EngineGradient { this.colors, this.colorStops, this.tileMode, - Float64List matrix, + Float64List? matrix, ) : assert(_offsetIsValid(from)), assert(_offsetIsValid(to)), - assert(colors != null), - assert(tileMode != null), + assert(colors != null), // ignore: unnecessary_null_comparison + assert(tileMode != null), // ignore: unnecessary_null_comparison this.matrix4 = matrix == null ? null : _FastMatrix64(matrix), super._() { if (assertionsEnabled) { @@ -102,35 +102,36 @@ class GradientLinear extends EngineGradient { final ui.Offset from; final ui.Offset to; final List colors; - final List colorStops; + final List? colorStops; final ui.TileMode tileMode; - final _FastMatrix64 matrix4; + final _FastMatrix64? matrix4; @override - html.CanvasGradient createPaintStyle(html.CanvasRenderingContext2D ctx) { - final bool hasMatrix = matrix4 != null; + html.CanvasGradient createPaintStyle(html.CanvasRenderingContext2D? ctx) { + _FastMatrix64? matrix4 = this.matrix4; html.CanvasGradient gradient; - if (hasMatrix) { + if (matrix4 != null) { final centerX = (from.dx + to.dx) / 2.0; final centerY = (from.dy + to.dy) / 2.0; matrix4.transform(from.dx - centerX, from.dy - centerY); final double fromX = matrix4.transformedX + centerX; final double fromY = matrix4.transformedY + centerY; matrix4.transform(to.dx - centerX, to.dy - centerY); - gradient = ctx.createLinearGradient(fromX, fromY, + gradient = ctx!.createLinearGradient(fromX, fromY, matrix4.transformedX + centerX, matrix4.transformedY + centerY); } else { - gradient = ctx.createLinearGradient(from.dx, from.dy, to.dx, to.dy); + gradient = ctx!.createLinearGradient(from.dx, from.dy, to.dx, to.dy); } + final List? colorStops = this.colorStops; if (colorStops == null) { assert(colors.length == 2); - gradient.addColorStop(0, colorToCssString(colors[0])); - gradient.addColorStop(1, colorToCssString(colors[1])); + gradient.addColorStop(0, colorToCssString(colors[0])!); + gradient.addColorStop(1, colorToCssString(colors[1])!); return gradient; } for (int i = 0; i < colors.length; i++) { - gradient.addColorStop(colorStops[i], colorToCssString(colors[i])); + gradient.addColorStop(colorStops[i], colorToCssString(colors[i])!); } return gradient; } @@ -154,7 +155,7 @@ class GradientLinear extends EngineGradient { } @override - js.JsObject createSkiaShader() { + js.JsObject? createSkiaShader() { assert(experimentalUseSkia); var jsColors = makeColorList(colors); @@ -181,35 +182,36 @@ class GradientRadial extends EngineGradient { final ui.Offset center; final double radius; final List colors; - final List colorStops; + final List? colorStops; final ui.TileMode tileMode; - final Float32List matrix4; + final Float32List? matrix4; @override - Object createPaintStyle(html.CanvasRenderingContext2D ctx) { + Object createPaintStyle(html.CanvasRenderingContext2D? ctx) { if (!experimentalUseSkia) { if (tileMode != ui.TileMode.clamp) { throw UnimplementedError( 'TileMode not supported in GradientRadial shader'); } } - final html.CanvasGradient gradient = ctx.createRadialGradient( + final html.CanvasGradient gradient = ctx!.createRadialGradient( center.dx, center.dy, 0, center.dx, center.dy, radius); + final List? colorStops = this.colorStops; if (colorStops == null) { assert(colors.length == 2); - gradient.addColorStop(0, colorToCssString(colors[0])); - gradient.addColorStop(1, colorToCssString(colors[1])); + gradient.addColorStop(0, colorToCssString(colors[0])!); + gradient.addColorStop(1, colorToCssString(colors[1])!); return gradient; } else { for (int i = 0; i < colors.length; i++) { - gradient.addColorStop(colorStops[i], colorToCssString(colors[i])); + gradient.addColorStop(colorStops[i], colorToCssString(colors[i])!); } } return gradient; } @override - js.JsObject createSkiaShader() { + js.JsObject? createSkiaShader() { assert(experimentalUseSkia); var jsColors = makeColorList(colors); @@ -236,17 +238,17 @@ class GradientConical extends EngineGradient { final ui.Offset center; final double radius; final List colors; - final List colorStops; + final List? colorStops; final ui.TileMode tileMode; - final Float32List matrix4; + final Float32List? matrix4; @override - Object createPaintStyle(html.CanvasRenderingContext2D ctx) { + Object createPaintStyle(html.CanvasRenderingContext2D? ctx) { throw UnimplementedError(); } @override - js.JsObject createSkiaShader() { + js.JsObject? createSkiaShader() { assert(experimentalUseSkia); var jsColors = makeColorList(colors); @@ -293,7 +295,7 @@ class EngineImageFilter implements ui.ImageFilter { } } -js.JsObject _skTileMode(ui.TileMode tileMode) { +js.JsObject? _skTileMode(ui.TileMode tileMode) { switch (tileMode) { case ui.TileMode.clamp: return canvasKit['TileMode']['Clamp']; @@ -316,6 +318,6 @@ class EngineImageShader implements ui.ImageShader, EngineShader { final Float64List matrix4; final SkImage _skImage; - js.JsObject createSkiaShader() => _skImage.skImage.callMethod( + js.JsObject? createSkiaShader() => _skImage.skImage!.callMethod( 'makeShader', [_skTileMode(tileModeX), _skTileMode(tileModeY)]); } diff --git a/lib/web_ui/lib/src/engine/shadow.dart b/lib/web_ui/lib/src/engine/shadow.dart index c5bebaf7fa350..a106eaa78304f 100644 --- a/lib/web_ui/lib/src/engine/shadow.dart +++ b/lib/web_ui/lib/src/engine/shadow.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// How far is the light source from the surface of the UI. @@ -81,8 +81,8 @@ ui.Rect computePenumbraBounds(ui.Rect shape, double elevation) { @immutable class SurfaceShadowData { const SurfaceShadowData({ - @required this.blurWidth, - @required this.offset, + required this.blurWidth, + required this.offset, }); /// The length in pixels of the shadow. @@ -106,7 +106,7 @@ class SurfaceShadowData { /// (cannot) use Skia's shadow API directly. However, this algorithms is /// consistent with [computePenumbraBounds] used by [RecordingCanvas] during /// bounds estimation. -SurfaceShadowData computeShadow(ui.Rect shape, double elevation) { +SurfaceShadowData? computeShadow(ui.Rect shape, double elevation) { if (elevation == 0.0) { return null; } @@ -128,13 +128,13 @@ SurfaceShadowData computeShadow(ui.Rect shape, double elevation) { /// Applies a CSS shadow to the [shape]. void applyCssShadow( - html.Element element, ui.Rect shape, double elevation, ui.Color color) { - final SurfaceShadowData shadow = computeShadow(shape, elevation); + html.Element? element, ui.Rect shape, double elevation, ui.Color color) { + final SurfaceShadowData? shadow = computeShadow(shape, elevation); if (shadow == null) { - element.style.boxShadow = 'none'; + element!.style.boxShadow = 'none'; } else { color = toShadowColor(color); - element.style.boxShadow = '${shadow.offset.dx}px ${shadow.offset.dy}px ' + element!.style.boxShadow = '${shadow.offset.dx}px ${shadow.offset.dy}px ' '${shadow.blurWidth}px 0px rgba(${color.red}, ${color.green}, ${color.blue}, ${color.alpha / 255})'; } } diff --git a/lib/web_ui/lib/src/engine/surface/backdrop_filter.dart b/lib/web_ui/lib/src/engine/surface/backdrop_filter.dart index 6ed5b2356d80a..ca5644af2c3d2 100644 --- a/lib/web_ui/lib/src/engine/surface/backdrop_filter.dart +++ b/lib/web_ui/lib/src/engine/surface/backdrop_filter.dart @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A surface that applies an image filter to background. class PersistedBackdropFilter extends PersistedContainerSurface implements ui.BackdropFilterEngineLayer { - PersistedBackdropFilter(PersistedBackdropFilter oldLayer, this.filter) + PersistedBackdropFilter(PersistedBackdropFilter? oldLayer, this.filter) : super(oldLayer); final EngineImageFilter filter; @@ -17,14 +17,14 @@ class PersistedBackdropFilter extends PersistedContainerSurface /// [rootElement] is used to host child in front of [filterElement] that /// is transformed to cover background. @override - html.Element get childContainer => _childContainer; - html.Element _childContainer; - html.Element _filterElement; - ui.Rect _activeClipBounds; + html.Element? get childContainer => _childContainer; + html.Element? _childContainer; + html.Element? _filterElement; + ui.Rect? _activeClipBounds; // Cached inverted transform for _transform. - Matrix4 _invertedTransform; + late Matrix4 _invertedTransform; // Reference to transform last used to cache [_invertedTransform]. - Matrix4 _previousTransform; + Matrix4? _previousTransform; @override void adoptElements(PersistedBackdropFilter oldSurface) { @@ -39,14 +39,14 @@ class PersistedBackdropFilter extends PersistedContainerSurface final html.Element element = defaultCreateElement('flt-backdrop') ..style.transformOrigin = '0 0 0'; _childContainer = html.Element.tag('flt-backdrop-interior'); - _childContainer.style.position = 'absolute'; + _childContainer!.style.position = 'absolute'; if (_debugExplainSurfaceStats) { // This creates an additional interior element. Count it too. _surfaceStatsFor(this).allocatedDomNodeCount++; } _filterElement = defaultCreateElement('flt-backdrop-filter'); - _filterElement.style.transformOrigin = '0 0 0'; - element..append(_filterElement)..append(_childContainer); + _filterElement!.style.transformOrigin = '0 0 0'; + element..append(_filterElement!)..append(_childContainer!); return element; } @@ -63,7 +63,7 @@ class PersistedBackdropFilter extends PersistedContainerSurface @override void apply() { if (_previousTransform != _transform) { - _invertedTransform = Matrix4.inverted(_transform); + _invertedTransform = Matrix4.inverted(_transform!); _previousTransform = _transform; } // https://api.flutter.dev/flutter/widgets/BackdropFilter-class.html @@ -82,19 +82,19 @@ class PersistedBackdropFilter extends PersistedContainerSurface double top = rect.top; double width = rect.width; double height = rect.height; - PersistedContainerSurface parentSurface = parent; + PersistedContainerSurface? parentSurface = parent; while (parentSurface != null) { if (parentSurface.isClipping) { - _activeClipBounds = parentSurface._localClipBounds; - left = _activeClipBounds.left; - top = _activeClipBounds.top; - width = _activeClipBounds.width; - height = _activeClipBounds.height; + final ui.Rect activeClipBounds = (_activeClipBounds = parentSurface._localClipBounds)!; + left = activeClipBounds.left; + top = activeClipBounds.top; + width = activeClipBounds.width; + height = activeClipBounds.height; break; } parentSurface = parentSurface.parent; } - final html.CssStyleDeclaration filterElementStyle = _filterElement.style; + final html.CssStyleDeclaration filterElementStyle = _filterElement!.style; filterElementStyle ..position = 'absolute' ..left = '${left}px' @@ -113,10 +113,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', + domRenderer.setElementStyle(_filterElement!, '-webkit-backdrop-filter', _imageFilterToCss(filter)); } - domRenderer.setElementStyle(_filterElement, 'backdrop-filter', _imageFilterToCss(filter)); + domRenderer.setElementStyle(_filterElement!, 'backdrop-filter', _imageFilterToCss(filter)); } } @@ -132,7 +132,7 @@ class PersistedBackdropFilter extends PersistedContainerSurface void _checkForUpdatedAncestorClipElement() { // If parent clip element has moved, adjust bounds. - PersistedContainerSurface parentSurface = parent; + PersistedContainerSurface? parentSurface = parent; while (parentSurface != null) { if (parentSurface.isClipping) { if (parentSurface._localClipBounds != _activeClipBounds) { diff --git a/lib/web_ui/lib/src/engine/surface/canvas.dart b/lib/web_ui/lib/src/engine/surface/canvas.dart index eff7ec956b87f..a180cac9a3dec 100644 --- a/lib/web_ui/lib/src/engine/surface/canvas.dart +++ b/lib/web_ui/lib/src/engine/surface/canvas.dart @@ -2,30 +2,30 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 part of engine; class SurfaceCanvas implements ui.Canvas { - RecordingCanvas/*!*/ _canvas; + RecordingCanvas _canvas; - SurfaceCanvas(EnginePictureRecorder recorder, [ui.Rect cullRect]) - : assert(recorder != null) { + factory SurfaceCanvas(EnginePictureRecorder recorder, [ui.Rect? cullRect]) { if (recorder.isRecording) { throw ArgumentError( '"recorder" must not already be associated with another Canvas.'); } cullRect ??= ui.Rect.largest; - _canvas = recorder.beginRecording(cullRect); + return SurfaceCanvas._(recorder.beginRecording(cullRect)); } + SurfaceCanvas._(this._canvas); + @override void save() { _canvas.save(); } @override - void saveLayer(ui.Rect/*?*/ bounds, ui.Paint/*!*/ paint) { - assert(paint != null); + void saveLayer(ui.Rect? bounds, ui.Paint paint) { + assert(paint != null); // ignore: unnecessary_null_comparison if (bounds == null) { _saveLayerWithoutBounds(paint); } else { @@ -35,11 +35,11 @@ class SurfaceCanvas implements ui.Canvas { } void _saveLayerWithoutBounds(ui.Paint paint) { - _canvas.saveLayerWithoutBounds(paint); + _canvas.saveLayerWithoutBounds(paint as SurfacePaint); } void _saveLayer(ui.Rect bounds, ui.Paint paint) { - _canvas.saveLayer(bounds, paint); + _canvas.saveLayer(bounds, paint as SurfacePaint); } @override @@ -48,33 +48,33 @@ class SurfaceCanvas implements ui.Canvas { } @override - int/*!*/ getSaveCount() => _canvas.saveCount; + int getSaveCount() => _canvas.saveCount; @override - void translate(double/*!*/ dx, double/*!*/ dy) { + void translate(double dx, double dy) { _canvas.translate(dx, dy); } @override - void scale(double/*!*/ sx, [double/*?*/ sy]) => _scale(sx, sy ?? sx); + void scale(double sx, [double? sy]) => _scale(sx, sy ?? sx); void _scale(double sx, double sy) { _canvas.scale(sx, sy); } @override - void rotate(double/*!*/ radians) { + void rotate(double radians) { _canvas.rotate(radians); } @override - void skew(double/*!*/ sx, double/*!*/ sy) { + void skew(double sx, double sy) { _canvas.skew(sx, sy); } @override - void transform(Float64List/*!*/ matrix4) { - assert(matrix4 != null); + void transform(Float64List matrix4) { + assert(matrix4 != null); // ignore: unnecessary_null_comparison if (matrix4.length != 16) { throw ArgumentError('"matrix4" must have 16 entries.'); } @@ -86,11 +86,11 @@ class SurfaceCanvas implements ui.Canvas { } @override - void clipRect(ui.Rect/*!*/ rect, - {ui.ClipOp/*!*/ clipOp = ui.ClipOp.intersect, bool/*!*/ doAntiAlias = true}) { + void clipRect(ui.Rect rect, + {ui.ClipOp clipOp = ui.ClipOp.intersect, bool doAntiAlias = true}) { assert(rectIsValid(rect)); - assert(clipOp != null); - assert(doAntiAlias != null); + assert(clipOp != null); // ignore: unnecessary_null_comparison + assert(doAntiAlias != null); // ignore: unnecessary_null_comparison _clipRect(rect, clipOp, doAntiAlias); } @@ -99,9 +99,9 @@ class SurfaceCanvas implements ui.Canvas { } @override - void clipRRect(ui.RRect/*!*/ rrect, {bool/*!*/ doAntiAlias = true}) { + void clipRRect(ui.RRect rrect, {bool doAntiAlias = true}) { assert(rrectIsValid(rrect)); - assert(doAntiAlias != null); + assert(doAntiAlias != null); // ignore: unnecessary_null_comparison _clipRRect(rrect, doAntiAlias); } @@ -110,9 +110,10 @@ class SurfaceCanvas implements ui.Canvas { } @override - void clipPath(ui.Path/*!*/ path, {bool/*!*/ doAntiAlias = true}) { + void clipPath(ui.Path path, {bool doAntiAlias = true}) { + // ignore: unnecessary_null_comparison assert(path != null); // path is checked on the engine side - assert(doAntiAlias != null); + assert(doAntiAlias != null); // ignore: unnecessary_null_comparison _clipPath(path, doAntiAlias); } @@ -121,9 +122,9 @@ class SurfaceCanvas implements ui.Canvas { } @override - void drawColor(ui.Color/*!*/ color, ui.BlendMode/*!*/ blendMode) { - assert(color != null); - assert(blendMode != null); + void drawColor(ui.Color color, ui.BlendMode blendMode) { + assert(color != null); // ignore: unnecessary_null_comparison + assert(blendMode != null); // ignore: unnecessary_null_comparison _drawColor(color, blendMode); } @@ -132,88 +133,88 @@ class SurfaceCanvas implements ui.Canvas { } @override - void drawLine(ui.Offset/*!*/ p1, ui.Offset/*!*/ p2, ui.Paint/*!*/ paint) { + void drawLine(ui.Offset p1, ui.Offset p2, ui.Paint paint) { assert(offsetIsValid(p1)); assert(offsetIsValid(p2)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawLine(p1, p2, paint); } void _drawLine(ui.Offset p1, ui.Offset p2, ui.Paint paint) { - _canvas.drawLine(p1, p2, paint); + _canvas.drawLine(p1, p2, paint as SurfacePaint); } @override - void drawPaint(ui.Paint/*!*/ paint) { - assert(paint != null); + void drawPaint(ui.Paint paint) { + assert(paint != null); // ignore: unnecessary_null_comparison _drawPaint(paint); } void _drawPaint(ui.Paint paint) { - _canvas.drawPaint(paint); + _canvas.drawPaint(paint as SurfacePaint); } @override - void drawRect(ui.Rect/*!*/ rect, ui.Paint/*!*/ paint) { + void drawRect(ui.Rect rect, ui.Paint paint) { assert(rectIsValid(rect)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawRect(rect, paint); } void _drawRect(ui.Rect rect, ui.Paint paint) { - _canvas.drawRect(rect, paint); + _canvas.drawRect(rect, paint as SurfacePaint); } @override - void drawRRect(ui.RRect/*!*/ rrect, ui.Paint/*!*/ paint) { + void drawRRect(ui.RRect rrect, ui.Paint paint) { assert(rrectIsValid(rrect)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawRRect(rrect, paint); } void _drawRRect(ui.RRect rrect, ui.Paint paint) { - _canvas.drawRRect(rrect, paint); + _canvas.drawRRect(rrect, paint as SurfacePaint); } @override - void drawDRRect(ui.RRect/*!*/ outer, ui.RRect/*!*/ inner, ui.Paint/*!*/ paint) { + void drawDRRect(ui.RRect outer, ui.RRect inner, ui.Paint paint) { assert(rrectIsValid(outer)); assert(rrectIsValid(inner)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawDRRect(outer, inner, paint); } void _drawDRRect(ui.RRect outer, ui.RRect inner, ui.Paint paint) { - _canvas.drawDRRect(outer, inner, paint); + _canvas.drawDRRect(outer, inner, paint as SurfacePaint); } @override - void drawOval(ui.Rect/*!*/ rect, ui.Paint/*!*/ paint) { + void drawOval(ui.Rect rect, ui.Paint paint) { assert(rectIsValid(rect)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawOval(rect, paint); } void _drawOval(ui.Rect rect, ui.Paint paint) { - _canvas.drawOval(rect, paint); + _canvas.drawOval(rect, paint as SurfacePaint); } @override - void drawCircle(ui.Offset/*!*/ c, double/*!*/ radius, ui.Paint/*!*/ paint) { + void drawCircle(ui.Offset c, double radius, ui.Paint paint) { assert(offsetIsValid(c)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawCircle(c, radius, paint); } void _drawCircle(ui.Offset c, double radius, ui.Paint paint) { - _canvas.drawCircle(c, radius, paint); + _canvas.drawCircle(c, radius, paint as SurfacePaint); } @override - void drawArc(ui.Rect/*!*/ rect, double/*!*/ startAngle, double/*!*/ sweepAngle, bool/*!*/ useCenter, - ui.Paint/*!*/ paint) { + void drawArc(ui.Rect rect, double startAngle, double sweepAngle, bool useCenter, + ui.Paint paint) { assert(rectIsValid(rect)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison const double pi = math.pi; const double pi2 = 2.0 * pi; @@ -243,51 +244,55 @@ class SurfaceCanvas implements ui.Canvas { if (useCenter) { path.close(); } - _canvas.drawPath(path, paint); + _canvas.drawPath(path, paint as SurfacePaint); } @override - void drawPath(ui.Path/*!*/ path, ui.Paint/*!*/ paint) { + void drawPath(ui.Path path, ui.Paint paint) { + // ignore: unnecessary_null_comparison assert(path != null); // path is checked on the engine side - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawPath(path, paint); } void _drawPath(ui.Path path, ui.Paint paint) { - _canvas.drawPath(path, paint); + _canvas.drawPath(path, paint as SurfacePaint); } @override - void drawImage(ui.Image/*!*/ image, ui.Offset/*!*/ offset, ui.Paint/*!*/ paint) { + void drawImage(ui.Image image, ui.Offset offset, ui.Paint paint) { + // ignore: unnecessary_null_comparison assert(image != null); // image is checked on the engine side assert(offsetIsValid(offset)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawImage(image, offset, paint); } void _drawImage(ui.Image image, ui.Offset p, ui.Paint paint) { - _canvas.drawImage(image, p, paint); + _canvas.drawImage(image, p, paint as SurfacePaint); } @override - void drawImageRect(ui.Image/*!*/ image, ui.Rect/*!*/ src, ui.Rect/*!*/ dst, ui.Paint/*!*/ paint) { + void drawImageRect(ui.Image image, ui.Rect src, ui.Rect dst, ui.Paint paint) { + // ignore: unnecessary_null_comparison assert(image != null); // image is checked on the engine side assert(rectIsValid(src)); assert(rectIsValid(dst)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison _drawImageRect(image, src, dst, paint); } void _drawImageRect(ui.Image image, ui.Rect src, ui.Rect dst, ui.Paint paint) { - _canvas.drawImageRect(image, src, dst, paint); + _canvas.drawImageRect(image, src, dst, paint as SurfacePaint); } @override - void drawImageNine(ui.Image/*!*/ image, ui.Rect/*!*/ center, ui.Rect/*!*/ dst, ui.Paint/*!*/ paint) { + void drawImageNine(ui.Image image, ui.Rect center, ui.Rect dst, ui.Paint paint) { + // ignore: unnecessary_null_comparison assert(image != null); // image is checked on the engine side assert(rectIsValid(center)); assert(rectIsValid(dst)); - assert(paint != null); + assert(paint != null); // ignore: unnecessary_null_comparison // Assert you can fit the scaled part of the image (exluding the // center source). @@ -433,15 +438,16 @@ class SurfaceCanvas implements ui.Canvas { } @override - void drawPicture(ui.Picture/*!*/ picture) { + void drawPicture(ui.Picture picture) { + // ignore: unnecessary_null_comparison assert(picture != null); // picture is checked on the engine side // TODO(het): Support this throw UnimplementedError(); } @override - void drawParagraph(ui.Paragraph/*!*/ paragraph, ui.Offset/*!*/ offset) { - assert(paragraph != null); + void drawParagraph(ui.Paragraph paragraph, ui.Offset offset) { + assert(paragraph != null); // ignore: unnecessary_null_comparison assert(offsetIsValid(offset)); _drawParagraph(paragraph, offset); } @@ -451,52 +457,50 @@ class SurfaceCanvas implements ui.Canvas { } @override - void drawPoints(ui.PointMode/*!*/ pointMode, List/*!*/ points, ui.Paint/*!*/ paint) { - assert(pointMode != null); - assert(points != null); - assert(paint != null); + void drawPoints(ui.PointMode pointMode, List points, ui.Paint paint) { + assert(pointMode != null); // ignore: unnecessary_null_comparison + assert(points != null); // ignore: unnecessary_null_comparison + assert(paint != null); // ignore: unnecessary_null_comparison final Float32List pointList = offsetListToFloat32List(points); drawRawPoints(pointMode, pointList, paint); } @override - void drawRawPoints(ui.PointMode/*!*/ pointMode, Float32List/*!*/ points, ui.Paint/*!*/ paint) { - assert(pointMode != null); - assert(points != null); - assert(paint != null); + void drawRawPoints(ui.PointMode pointMode, Float32List points, ui.Paint paint) { + assert(pointMode != null); // ignore: unnecessary_null_comparison + assert(points != null); // ignore: unnecessary_null_comparison + assert(paint != null); // ignore: unnecessary_null_comparison if (points.length % 2 != 0) { throw ArgumentError('"points" must have an even number of values.'); } - _canvas.drawRawPoints(pointMode, points, paint); + _canvas.drawRawPoints(pointMode, points, paint as SurfacePaint); } @override - void drawVertices(ui.Vertices/*!*/ vertices, ui.BlendMode/*!*/ blendMode, ui.Paint/*!*/ paint) { - if (vertices == null) { - return; - } + void drawVertices(ui.Vertices vertices, ui.BlendMode blendMode, ui.Paint paint) { //assert(vertices != null); // vertices is checked on the engine side - assert(paint != null); - assert(blendMode != null); - _canvas.drawVertices(vertices, blendMode, paint); + assert(paint != null); // ignore: unnecessary_null_comparison + assert(blendMode != null); // ignore: unnecessary_null_comparison + _canvas.drawVertices(vertices as SurfaceVertices, blendMode, paint as SurfacePaint); } @override void drawAtlas( - ui.Image/*!*/ atlas, - List/*!*/ transforms, - List/*!*/ rects, - List/*!*/ colors, - ui.BlendMode/*!*/ blendMode, - ui.Rect/*?*/ cullRect, - ui.Paint/*!*/ paint, + ui.Image atlas, + List transforms, + List rects, + List colors, + ui.BlendMode blendMode, + ui.Rect? cullRect, + ui.Paint paint, ) { + // ignore: unnecessary_null_comparison assert(atlas != null); // atlas is checked on the engine side - assert(transforms != null); - assert(rects != null); - assert(colors != null); - assert(blendMode != null); - assert(paint != null); + assert(transforms != null); // ignore: unnecessary_null_comparison + assert(rects != null); // ignore: unnecessary_null_comparison + assert(colors != null); // ignore: unnecessary_null_comparison + assert(blendMode != null); // ignore: unnecessary_null_comparison + assert(paint != null); // ignore: unnecessary_null_comparison final int rectCount = rects.length; if (transforms.length != rectCount) { @@ -513,20 +517,21 @@ class SurfaceCanvas implements ui.Canvas { @override void drawRawAtlas( - ui.Image/*!*/ atlas, - Float32List/*!*/ rstTransforms, - Float32List/*!*/ rects, - Int32List/*!*/ colors, - ui.BlendMode/*!*/ blendMode, - ui.Rect/*?*/ cullRect, - ui.Paint/*!*/ paint, + ui.Image atlas, + Float32List rstTransforms, + Float32List rects, + Int32List colors, + ui.BlendMode blendMode, + ui.Rect? cullRect, + ui.Paint paint, ) { + // ignore: unnecessary_null_comparison assert(atlas != null); // atlas is checked on the engine side - assert(rstTransforms != null); - assert(rects != null); - assert(colors != null); - assert(blendMode != null); - assert(paint != null); + assert(rstTransforms != null); // ignore: unnecessary_null_comparison + assert(rects != null); // ignore: unnecessary_null_comparison + assert(colors != null); // ignore: unnecessary_null_comparison + assert(blendMode != null); // ignore: unnecessary_null_comparison + assert(paint != null); // ignore: unnecessary_null_comparison final int rectCount = rects.length; if (rstTransforms.length != rectCount) { @@ -536,7 +541,7 @@ class SurfaceCanvas implements ui.Canvas { throw ArgumentError( '"rstTransforms" and "rects" lengths must be a multiple of four.'); } - if (colors != null && colors.length * 4 != rectCount) { + if (colors.length * 4 != rectCount) { throw ArgumentError( 'If non-null, "colors" length must be one fourth the length of "rstTransforms" and "rects".'); } @@ -547,14 +552,15 @@ class SurfaceCanvas implements ui.Canvas { @override void drawShadow( - ui.Path/*!*/ path, - ui.Color/*!*/ color, - double/*!*/ elevation, - bool/*!*/ transparentOccluder, + ui.Path path, + ui.Color color, + double elevation, + bool transparentOccluder, ) { + // ignore: unnecessary_null_comparison assert(path != null); // path is checked on the engine side - assert(color != null); - assert(transparentOccluder != null); + assert(color != null); // ignore: unnecessary_null_comparison + assert(transparentOccluder != null); // ignore: unnecessary_null_comparison _canvas.drawShadow(path, color, elevation, transparentOccluder); } } diff --git a/lib/web_ui/lib/src/engine/surface/clip.dart b/lib/web_ui/lib/src/engine/surface/clip.dart index e022195b13f8d..d49be6ab45db4 100644 --- a/lib/web_ui/lib/src/engine/surface/clip.dart +++ b/lib/web_ui/lib/src/engine/surface/clip.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Mixin used by surfaces that clip their contents using an overflowing DOM @@ -12,8 +12,8 @@ mixin _DomClip on PersistedContainerSurface { /// [rootElement] is used to compensate for the coordinate system shift /// introduced by the [rootElement] translation. @override - html.Element get childContainer => _childContainer; - html.Element _childContainer; + html.Element? get childContainer => _childContainer; + html.Element? _childContainer; @override void adoptElements(_DomClip oldSurface) { @@ -42,9 +42,9 @@ mixin _DomClip on PersistedContainerSurface { // This creates an additional interior element. Count it too. _surfaceStatsFor(this).allocatedDomNodeCount++; } - _childContainer.style.position = 'absolute'; + _childContainer!.style.position = 'absolute'; - element.append(_childContainer); + element.append(_childContainer!); return element; } @@ -63,13 +63,13 @@ mixin _DomClip on PersistedContainerSurface { class PersistedClipRect extends PersistedContainerSurface with _DomClip implements ui.ClipRectEngineLayer { - PersistedClipRect(PersistedClipRect oldLayer, this.rect) : super(oldLayer); + PersistedClipRect(PersistedClipRect? oldLayer, this.rect) : super(oldLayer); final ui.Rect rect; @override void recomputeTransformAndClip() { - _transform = parent._transform; + _transform = parent!._transform; _localClipBounds = rect; _localTransformInverse = null; _projectedClip = null; @@ -82,7 +82,7 @@ class PersistedClipRect extends PersistedContainerSurface @override void apply() { - rootElement.style + rootElement!.style ..left = '${rect.left}px' ..top = '${rect.top}px' ..width = '${rect.right - rect.left}px' @@ -91,7 +91,7 @@ class PersistedClipRect extends PersistedContainerSurface // Translate the child container in the opposite direction to compensate for // the shift in the coordinate system introduced by the translation of the // rootElement. Clipping in Flutter has no effect on the coordinate system. - childContainer.style + childContainer!.style ..left = '${-rect.left}px' ..top = '${-rect.top}px'; } @@ -112,16 +112,16 @@ class PersistedClipRect extends PersistedContainerSurface class PersistedClipRRect extends PersistedContainerSurface with _DomClip implements ui.ClipRRectEngineLayer { - PersistedClipRRect(ui.EngineLayer oldLayer, this.rrect, this.clipBehavior) - : super(oldLayer); + PersistedClipRRect(ui.EngineLayer? oldLayer, this.rrect, this.clipBehavior) + : super(oldLayer as PersistedSurface?); final ui.RRect rrect; // TODO(yjbanov): can this be controlled in the browser? - final ui.Clip clipBehavior; + final ui.Clip? clipBehavior; @override void recomputeTransformAndClip() { - _transform = parent._transform; + _transform = parent!._transform; _localClipBounds = rrect.outerRect; _localTransformInverse = null; _projectedClip = null; @@ -134,7 +134,7 @@ class PersistedClipRRect extends PersistedContainerSurface @override void apply() { - rootElement.style + rootElement!.style ..left = '${rrect.left}px' ..top = '${rrect.top}px' ..width = '${rrect.width}px' @@ -147,7 +147,7 @@ class PersistedClipRRect extends PersistedContainerSurface // Translate the child container in the opposite direction to compensate for // the shift in the coordinate system introduced by the translation of the // rootElement. Clipping in Flutter has no effect on the coordinate system. - childContainer.style + childContainer!.style ..left = '${-rrect.left}px' ..top = '${-rrect.top}px'; } @@ -167,7 +167,7 @@ class PersistedClipRRect extends PersistedContainerSurface class PersistedPhysicalShape extends PersistedContainerSurface with _DomClip implements ui.PhysicalShapeEngineLayer { - PersistedPhysicalShape(PersistedPhysicalShape oldLayer, this.path, + PersistedPhysicalShape(PersistedPhysicalShape? oldLayer, this.path, this.elevation, int color, int shadowColor, this.clipBehavior) : color = ui.Color(color), shadowColor = ui.Color(shadowColor), @@ -180,17 +180,17 @@ class PersistedPhysicalShape extends PersistedContainerSurface final ui.Color color; final ui.Color shadowColor; final ui.Clip clipBehavior; - html.Element _clipElement; + html.Element? _clipElement; @override void recomputeTransformAndClip() { - _transform = parent._transform; + _transform = parent!._transform; - final ui.RRect roundRect = path.webOnlyPathAsRoundedRect; + final ui.RRect? roundRect = path.webOnlyPathAsRoundedRect; if (roundRect != null) { _localClipBounds = roundRect.outerRect; } else { - final ui.Rect rect = path.webOnlyPathAsRect; + final ui.Rect? rect = path.webOnlyPathAsRect; if (rect != null) { _localClipBounds = rect; } else { @@ -202,7 +202,7 @@ class PersistedPhysicalShape extends PersistedContainerSurface } void _applyColor() { - rootElement.style.backgroundColor = colorToCssString(color); + rootElement!.style.backgroundColor = colorToCssString(color); } void _applyShadow() { @@ -222,24 +222,21 @@ class PersistedPhysicalShape extends PersistedContainerSurface } void _applyShape() { - if (path == null) { - return; - } // Handle special case of round rect physical shape mapping to // rounded div. - final ui.RRect roundRect = path.webOnlyPathAsRoundedRect; + final ui.RRect? roundRect = path.webOnlyPathAsRoundedRect; if (roundRect != null) { final String borderRadius = '${roundRect.tlRadiusX}px ${roundRect.trRadiusX}px ' '${roundRect.brRadiusX}px ${roundRect.blRadiusX}px'; - final html.CssStyleDeclaration style = rootElement.style; + final html.CssStyleDeclaration style = rootElement!.style; style ..left = '${roundRect.left}px' ..top = '${roundRect.top}px' ..width = '${roundRect.width}px' ..height = '${roundRect.height}px' ..borderRadius = borderRadius; - childContainer.style + childContainer!.style ..left = '${-roundRect.left}px' ..top = '${-roundRect.top}px'; if (clipBehavior != ui.Clip.none) { @@ -247,16 +244,16 @@ class PersistedPhysicalShape extends PersistedContainerSurface } return; } else { - final ui.Rect rect = path.webOnlyPathAsRect; + final ui.Rect? rect = path.webOnlyPathAsRect; if (rect != null) { - final html.CssStyleDeclaration style = rootElement.style; + final html.CssStyleDeclaration style = rootElement!.style; style ..left = '${rect.left}px' ..top = '${rect.top}px' ..width = '${rect.width}px' ..height = '${rect.height}px' ..borderRadius = ''; - childContainer.style + childContainer!.style ..left = '${-rect.left}px' ..top = '${-rect.top}px'; if (clipBehavior != ui.Clip.none) { @@ -264,13 +261,13 @@ class PersistedPhysicalShape extends PersistedContainerSurface } return; } else { - final Ellipse ellipse = path.webOnlyPathAsCircle; + final Ellipse? ellipse = path.webOnlyPathAsCircle; if (ellipse != null) { final double rx = ellipse.radiusX; final double ry = ellipse.radiusY; final String borderRadius = rx == ry ? '${rx}px ' : '${rx}px ${ry}px '; - final html.CssStyleDeclaration style = rootElement.style; + final html.CssStyleDeclaration style = rootElement!.style; final double left = ellipse.x - rx; final double top = ellipse.y - ry; style @@ -279,7 +276,7 @@ class PersistedPhysicalShape extends PersistedContainerSurface ..width = '${rx * 2}px' ..height = '${ry * 2}px' ..borderRadius = borderRadius; - childContainer.style + childContainer!.style ..left = '${-left}px' ..top = '${-top}px'; if (clipBehavior != ui.Clip.none) { @@ -298,12 +295,12 @@ class PersistedPhysicalShape extends PersistedContainerSurface assert(_clipElement == null); _clipElement = html.Element.html(svgClipPath, treeSanitizer: _NullTreeSanitizer()); - domRenderer.append(rootElement, _clipElement); + domRenderer.append(rootElement!, _clipElement!); domRenderer.setElementStyle( - rootElement, 'clip-path', 'url(#svgClip$_clipIdCounter)'); + rootElement!, 'clip-path', 'url(#svgClip$_clipIdCounter)'); domRenderer.setElementStyle( - rootElement, '-webkit-clip-path', 'url(#svgClip$_clipIdCounter)'); - final html.CssStyleDeclaration rootElementStyle = rootElement.style; + rootElement!, '-webkit-clip-path', 'url(#svgClip$_clipIdCounter)'); + final html.CssStyleDeclaration rootElementStyle = rootElement!.style; rootElementStyle ..overflow = '' ..left = '${pathBounds.left}px' @@ -311,7 +308,7 @@ class PersistedPhysicalShape extends PersistedContainerSurface ..width = '${pathBounds.width}px' ..height = '${pathBounds.height}px' ..borderRadius = ''; - childContainer.style + childContainer!.style ..left = '-${pathBounds.left}px' ..top = '-${pathBounds.top}px'; } @@ -328,18 +325,9 @@ class PersistedPhysicalShape extends PersistedContainerSurface } if (oldSurface.path != path) { oldSurface._clipElement?.remove(); - domRenderer.setElementStyle(rootElement, 'clip-path', ''); - domRenderer.setElementStyle(rootElement, '-webkit-clip-path', ''); + domRenderer.setElementStyle(rootElement!, 'clip-path', ''); + domRenderer.setElementStyle(rootElement!, '-webkit-clip-path', ''); _applyShape(); - // This null check is in update since we don't want to unnecessarily - // clear style in apply on first build. - if (path == null) { - // Reset style on prior element when path becomes null. - final html.CssStyleDeclaration style = rootElement.style; - style.left = ''; - style.top = ''; - style.borderRadius = ''; - } } else { _clipElement = oldSurface._clipElement; } @@ -351,12 +339,12 @@ class PersistedPhysicalShape extends PersistedContainerSurface class PersistedClipPath extends PersistedContainerSurface implements ui.ClipPathEngineLayer { PersistedClipPath( - PersistedClipPath oldLayer, this.clipPath, this.clipBehavior) + PersistedClipPath? oldLayer, this.clipPath, this.clipBehavior) : super(oldLayer); final ui.Path clipPath; final ui.Clip clipBehavior; - html.Element _clipElement; + html.Element? _clipElement; @override html.Element createElement() { @@ -371,20 +359,11 @@ class PersistedClipPath extends PersistedContainerSurface @override void apply() { - if (clipPath == null) { - if (_clipElement != null) { - domRenderer.setElementStyle(childContainer, 'clip-path', ''); - domRenderer.setElementStyle(childContainer, '-webkit-clip-path', ''); - _clipElement.remove(); - _clipElement = null; - } - return; - } _clipElement?.remove(); - final String svgClipPath = createSvgClipDef(childContainer, clipPath); + final String svgClipPath = createSvgClipDef(childContainer as html.HtmlElement, clipPath); _clipElement = html.Element.html(svgClipPath, treeSanitizer: _NullTreeSanitizer()); - domRenderer.append(childContainer, _clipElement); + domRenderer.append(childContainer!, _clipElement!); } @override diff --git a/lib/web_ui/lib/src/engine/surface/debug_canvas_reuse_overlay.dart b/lib/web_ui/lib/src/engine/surface/debug_canvas_reuse_overlay.dart index 2b16739da049d..8ac6a13833d3b 100644 --- a/lib/web_ui/lib/src/engine/surface/debug_canvas_reuse_overlay.dart +++ b/lib/web_ui/lib/src/engine/surface/debug_canvas_reuse_overlay.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; html.HtmlElement _createContainer() { @@ -32,7 +32,7 @@ class DebugCanvasReuseOverlay { ..textDecoration = 'underline'; title.text = 'Canvas Reuse'; - html.document.body.append( + html.document.body!.append( container ..append(title) ..append( @@ -71,8 +71,8 @@ class DebugCanvasReuseOverlay { ); } - static DebugCanvasReuseOverlay _instance; - static DebugCanvasReuseOverlay/*!*/ get instance { + static DebugCanvasReuseOverlay? _instance; + static DebugCanvasReuseOverlay get instance { if (_instance == null) { // Only call the constructor when assertions are enabled to guard against // mistakingly including this class in a release build. @@ -80,7 +80,7 @@ class DebugCanvasReuseOverlay { _instance = DebugCanvasReuseOverlay._(); } } - return _instance; + return _instance!; } final html.Text _created = html.Text('0'); diff --git a/lib/web_ui/lib/src/engine/surface/image_filter.dart b/lib/web_ui/lib/src/engine/surface/image_filter.dart index 57ee4334a74e6..8ccf727387336 100644 --- a/lib/web_ui/lib/src/engine/surface/image_filter.dart +++ b/lib/web_ui/lib/src/engine/surface/image_filter.dart @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A surface that applies an [imageFilter] to its children. class PersistedImageFilter extends PersistedContainerSurface implements ui.ImageFilterEngineLayer { - PersistedImageFilter(PersistedImageFilter oldLayer, this.filter) : super(oldLayer); + PersistedImageFilter(PersistedImageFilter? oldLayer, this.filter) : super(oldLayer); final ui.ImageFilter filter; @@ -19,7 +19,7 @@ class PersistedImageFilter extends PersistedContainerSurface @override void apply() { - rootElement.style.filter = _imageFilterToCss(filter); + rootElement!.style.filter = _imageFilterToCss(filter as EngineImageFilter); } @override diff --git a/lib/web_ui/lib/src/engine/surface/offset.dart b/lib/web_ui/lib/src/engine/surface/offset.dart index e99623747dd9c..9567edd3da526 100644 --- a/lib/web_ui/lib/src/engine/surface/offset.dart +++ b/lib/web_ui/lib/src/engine/surface/offset.dart @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A surface that translates its children using CSS transform and translate. class PersistedOffset extends PersistedContainerSurface implements ui.OffsetEngineLayer { - PersistedOffset(PersistedOffset oldLayer, this.dx, this.dy) : super(oldLayer); + PersistedOffset(PersistedOffset? oldLayer, this.dx, this.dy) : super(oldLayer); /// Horizontal displacement. final double dx; @@ -18,10 +18,10 @@ class PersistedOffset extends PersistedContainerSurface @override void recomputeTransformAndClip() { - _transform = parent._transform; + _transform = parent!._transform; if (dx != 0.0 || dy != 0.0) { - _transform = _transform.clone(); - _transform.translate(dx, dy); + _transform = _transform!.clone(); + _transform!.translate(dx, dy); } _projectedClip = null; _localTransformInverse = null; @@ -38,7 +38,7 @@ class PersistedOffset extends PersistedContainerSurface @override void apply() { - rootElement.style.transform = 'translate(${dx}px, ${dy}px)'; + rootElement!.style.transform = 'translate(${dx}px, ${dy}px)'; } @override diff --git a/lib/web_ui/lib/src/engine/surface/opacity.dart b/lib/web_ui/lib/src/engine/surface/opacity.dart index e867ca8ed6561..fe7b4647dd3a8 100644 --- a/lib/web_ui/lib/src/engine/surface/opacity.dart +++ b/lib/web_ui/lib/src/engine/surface/opacity.dart @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A surface that makes its children transparent. class PersistedOpacity extends PersistedContainerSurface implements ui.OpacityEngineLayer { - PersistedOpacity(PersistedOpacity oldLayer, this.alpha, this.offset) + PersistedOpacity(PersistedOpacity? oldLayer, this.alpha, this.offset) : super(oldLayer); final int alpha; @@ -16,14 +16,14 @@ class PersistedOpacity extends PersistedContainerSurface @override void recomputeTransformAndClip() { - _transform = parent._transform; + _transform = parent!._transform; final double dx = offset.dx; final double dy = offset.dy; if (dx != 0.0 || dy != 0.0) { - _transform = _transform.clone(); - _transform.translate(dx, dy); + _transform = _transform!.clone(); + _transform!.translate(dx, dy); } _localTransformInverse = null; _projectedClip = null; @@ -43,8 +43,8 @@ class PersistedOpacity extends PersistedContainerSurface // TODO(yjbanov): evaluate using `filter: opacity(X)`. It is a longer string // but it reportedly has better hardware acceleration, so may // be worth the trade-off. - rootElement.style.opacity = '${alpha / 255}'; - rootElement.style.transform = 'translate(${offset.dx}px, ${offset.dy}px)'; + rootElement!.style.opacity = '${alpha / 255}'; + rootElement!.style.transform = 'translate(${offset.dx}px, ${offset.dy}px)'; } @override diff --git a/lib/web_ui/lib/src/engine/surface/painting.dart b/lib/web_ui/lib/src/engine/surface/painting.dart index cce4564ea6782..f98687c32ec89 100644 --- a/lib/web_ui/lib/src/engine/surface/painting.dart +++ b/lib/web_ui/lib/src/engine/surface/painting.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Implementation of [ui.Paint] used by the HTML rendering backend. @@ -46,7 +46,7 @@ class SurfacePaint implements ui.Paint { } @override - ui.StrokeCap get strokeCap => _paintData.strokeCap; + ui.StrokeCap get strokeCap => _paintData.strokeCap ?? ui.StrokeCap.butt; @override set strokeCap(ui.StrokeCap value) { @@ -58,7 +58,7 @@ class SurfacePaint implements ui.Paint { } @override - ui.StrokeJoin get strokeJoin => _paintData.strokeJoin; + ui.StrokeJoin get strokeJoin => _paintData.strokeJoin ?? ui.StrokeJoin.miter; @override set strokeJoin(ui.StrokeJoin value) { @@ -82,7 +82,7 @@ class SurfacePaint implements ui.Paint { } @override - ui.Color get color => _paintData.color; + ui.Color get color => _paintData.color ?? _defaultPaintColor; @override set color(ui.Color value) { @@ -105,10 +105,10 @@ class SurfacePaint implements ui.Paint { static const ui.Color _defaultPaintColor = ui.Color(0xFF000000); @override - ui.Shader get shader => _paintData.shader; + ui.Shader? get shader => _paintData.shader; @override - set shader(ui.Shader value) { + set shader(ui.Shader? value) { if (_frozen) { _paintData = _paintData.clone(); _frozen = false; @@ -117,10 +117,10 @@ class SurfacePaint implements ui.Paint { } @override - ui.MaskFilter get maskFilter => _paintData.maskFilter; + ui.MaskFilter? get maskFilter => _paintData.maskFilter; @override - set maskFilter(ui.MaskFilter value) { + set maskFilter(ui.MaskFilter? value) { if (_frozen) { _paintData = _paintData.clone(); _frozen = false; @@ -129,7 +129,7 @@ class SurfacePaint implements ui.Paint { } @override - ui.FilterQuality get filterQuality => _paintData.filterQuality; + ui.FilterQuality get filterQuality => _paintData.filterQuality ?? ui.FilterQuality.none; @override set filterQuality(ui.FilterQuality value) { @@ -141,10 +141,10 @@ class SurfacePaint implements ui.Paint { } @override - ui.ColorFilter get colorFilter => _paintData.colorFilter; + ui.ColorFilter? get colorFilter => _paintData.colorFilter; @override - set colorFilter(ui.ColorFilter value) { + set colorFilter(ui.ColorFilter? value) { if (_frozen) { _paintData = _paintData.clone(); _frozen = false; @@ -155,22 +155,22 @@ class SurfacePaint implements ui.Paint { // TODO(flutter_web): see https://github.com/flutter/flutter/issues/33605 @override double get strokeMiterLimit { - return null; + throw UnsupportedError('SurfacePaint.strokeMiterLimit'); } @override set strokeMiterLimit(double value) { - assert(value != null); + assert(value != null); // ignore: unnecessary_null_comparison } @override - ui.ImageFilter get imageFilter { + ui.ImageFilter? get imageFilter { // TODO(flutter/flutter#35156): Implement ImageFilter. return null; } @override - set imageFilter(ui.ImageFilter value) { + set imageFilter(ui.ImageFilter? value) { // TODO(flutter/flutter#35156): Implement ImageFilter. } @@ -192,11 +192,11 @@ class SurfacePaint implements ui.Paint { result.write('Paint('); if (style == ui.PaintingStyle.stroke) { result.write('$style'); - if (strokeWidth != null && strokeWidth != 0.0) + if (strokeWidth != 0.0) result.write(' $strokeWidth'); else result.write(' hairline'); - if (strokeCap != null && strokeCap != ui.StrokeCap.butt) + if (strokeCap != ui.StrokeCap.butt) result.write(' $strokeCap'); semicolon = '; '; } @@ -205,10 +205,7 @@ class SurfacePaint implements ui.Paint { semicolon = '; '; } if (color != _defaultPaintColor) { - if (color != null) - result.write('$semicolon$color'); - else - result.write('${semicolon}no color'); + result.write('$semicolon$color'); semicolon = '; '; } result.write(')'); @@ -219,17 +216,17 @@ class SurfacePaint implements ui.Paint { /// Private Paint context data used for recording canvas commands allowing /// Paint to be mutated post canvas draw operations. class SurfacePaintData { - ui.BlendMode blendMode; - ui.PaintingStyle style; - double strokeWidth; - ui.StrokeCap strokeCap; - ui.StrokeJoin strokeJoin; + ui.BlendMode? blendMode; + ui.PaintingStyle? style; + double? strokeWidth; + ui.StrokeCap? strokeCap; + ui.StrokeJoin? strokeJoin; bool isAntiAlias = true; - ui.Color color; - ui.Shader shader; - ui.MaskFilter maskFilter; - ui.FilterQuality filterQuality; - ui.ColorFilter colorFilter; + ui.Color? color; + ui.Shader? shader; + ui.MaskFilter? maskFilter; + ui.FilterQuality? filterQuality; + ui.ColorFilter? colorFilter; // Internal for recording canvas use. SurfacePaintData clone() { diff --git a/lib/web_ui/lib/src/engine/surface/path.dart b/lib/web_ui/lib/src/engine/surface/path.dart index de9b90a24d1f1..7d08c284219ee 100644 --- a/lib/web_ui/lib/src/engine/surface/path.dart +++ b/lib/web_ui/lib/src/engine/surface/path.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A complex, one-dimensional subset of a plane. @@ -26,18 +26,18 @@ class SurfacePath implements ui.Path { final List subpaths; ui.PathFillType _fillType = ui.PathFillType.nonZero; - Subpath get _currentSubpath => subpaths.isEmpty ? null : subpaths.last; + Subpath get _currentSubpath => subpaths.last; - List get _commands => _currentSubpath?.commands; + List get _commands => _currentSubpath.commands; /// The current x-coordinate for this path. - double get _currentX => _currentSubpath?.currentX ?? 0.0; + double get _currentX => subpaths.isNotEmpty ? _currentSubpath.currentX : 0.0; /// The current y-coordinate for this path. - double get _currentY => _currentSubpath?.currentY ?? 0.0; + double get _currentY => subpaths.isNotEmpty ? _currentSubpath.currentY : 0.0; /// Recorder used for hit testing paths. - static RawRecordingCanvas _rawRecorder; + static RawRecordingCanvas? _rawRecorder; SurfacePath() : subpaths = []; @@ -465,7 +465,7 @@ class SurfacePath implements ui.Path { /// The `points` argument is interpreted as offsets from the origin. @override void addPolygon(List points, bool close) { - assert(points != null); + assert(points != null); // ignore: unnecessary_null_comparison if (points.isEmpty) { return; } @@ -504,13 +504,14 @@ class SurfacePath implements ui.Path { /// after the matrix is translated by the given offset. The matrix is a 4x4 /// matrix stored in column major order. @override - void addPath(ui.Path path, ui.Offset offset, {Float64List matrix4}) { + void addPath(ui.Path path, ui.Offset offset, {Float64List? matrix4}) { + // ignore: unnecessary_null_comparison assert(path != null); // path is checked on the engine side assert(offsetIsValid(offset)); if (matrix4 != null) { - _addPathWithMatrix(path, offset.dx, offset.dy, toMatrix32(matrix4)); + _addPathWithMatrix(path as SurfacePath, offset.dx, offset.dy, toMatrix32(matrix4)); } else { - _addPath(path, offset.dx, offset.dy); + _addPath(path as SurfacePath, offset.dx, offset.dy); } } @@ -539,15 +540,16 @@ class SurfacePath implements ui.Path { /// after the matrix is translated by the given `offset`. The matrix is a 4x4 /// matrix stored in column major order. @override - void extendWithPath(ui.Path path, ui.Offset offset, {Float64List matrix4}) { + void extendWithPath(ui.Path path, ui.Offset offset, {Float64List? matrix4}) { + // ignore: unnecessary_null_comparison assert(path != null); // path is checked on the engine side assert(offsetIsValid(offset)); if (matrix4 != null) { final Float32List matrix32 = toMatrix32(matrix4); assert(matrix4IsValid(matrix32)); - _extendWithPathAndMatrix(path, offset.dx, offset.dy, matrix32); + _extendWithPathAndMatrix(path as SurfacePath, offset.dx, offset.dy, matrix32); } else { - _extendWithPath(path, offset.dx, offset.dy); + _extendWithPath(path as SurfacePath, offset.dx, offset.dy); } } @@ -668,22 +670,22 @@ class SurfacePath implements ui.Path { final ui.Size size = window.physicalSize; // If device pixel ratio has changed we can't reuse prior raw recorder. if (_rawRecorder != null && - _rawRecorder._devicePixelRatio != + _rawRecorder!._devicePixelRatio != EngineWindow.browserDevicePixelRatio) { _rawRecorder = null; } final double dpr = window.devicePixelRatio; - _rawRecorder ??= + final RawRecordingCanvas rawRecorder = _rawRecorder ??= RawRecordingCanvas(ui.Size(size.width / dpr, size.height / dpr)); // Account for the shift due to padding. - _rawRecorder.translate(-BitmapCanvas.kPaddingPixels.toDouble(), + rawRecorder.translate(-BitmapCanvas.kPaddingPixels.toDouble(), -BitmapCanvas.kPaddingPixels.toDouble()); - _rawRecorder.drawPath( + rawRecorder.drawPath( this, (SurfacePaint()..color = const ui.Color(0xFF000000)).paintData); - final double recorderDevicePixelRatio = _rawRecorder._devicePixelRatio; - final bool result = _rawRecorder._canvasPool.context.isPointInPath( + final double recorderDevicePixelRatio = rawRecorder._devicePixelRatio; + final bool result = rawRecorder._canvasPool.context.isPointInPath( pointX * recorderDevicePixelRatio, pointY * recorderDevicePixelRatio); - _rawRecorder.dispose(); + rawRecorder.dispose(); return result; } @@ -746,17 +748,17 @@ class SurfacePath implements ui.Path { bool skipBounds = false; switch (op.type) { case PathCommandTypes.moveTo: - final MoveTo cmd = op; + final MoveTo cmd = op as MoveTo; curX = minX = maxX = cmd.x; curY = minY = maxY = cmd.y; break; case PathCommandTypes.lineTo: - final LineTo cmd = op; + final LineTo cmd = op as LineTo; curX = minX = maxX = cmd.x; curY = minY = maxY = cmd.y; break; case PathCommandTypes.ellipse: - final Ellipse cmd = op; + final Ellipse cmd = op as Ellipse; // Rotate 4 corners of bounding box. final double rx = cmd.radiusX; final double ry = cmd.radiusY; @@ -805,7 +807,7 @@ class SurfacePath implements ui.Path { curY = centerY; break; case PathCommandTypes.quadraticCurveTo: - final QuadraticCurveTo cmd = op; + final QuadraticCurveTo cmd = op as QuadraticCurveTo; final double x1 = curX; final double y1 = curY; final double cpX = cmd.x1; @@ -827,14 +829,14 @@ class SurfacePath implements ui.Path { double denom = x1 - (2 * cpX) + x2; if (denom.abs() > epsilon) { - final num t1 = (x1 - cpX) / denom; + final double t1 = (x1 - cpX) / denom; if ((t1 >= 0) && (t1 <= 1.0)) { // Solve (x,y) for curve at t = tx to find extrema - final num tprime = 1.0 - t1; - final num extremaX = (tprime * tprime * x1) + + final double tprime = 1.0 - t1; + final double extremaX = (tprime * tprime * x1) + (2 * t1 * tprime * cpX) + (t1 * t1 * x2); - final num extremaY = (tprime * tprime * y1) + + final double extremaY = (tprime * tprime * y1) + (2 * t1 * tprime * cpY) + (t1 * t1 * y2); // Expand bounds. @@ -847,13 +849,13 @@ class SurfacePath implements ui.Path { // Now calculate dy/dt = 0 denom = y1 - (2 * cpY) + y2; if (denom.abs() > epsilon) { - final num t2 = (y1 - cpY) / denom; + final double t2 = (y1 - cpY) / denom; if ((t2 >= 0) && (t2 <= 1.0)) { - final num tprime2 = 1.0 - t2; - final num extrema2X = (tprime2 * tprime2 * x1) + + final double tprime2 = 1.0 - t2; + final double extrema2X = (tprime2 * tprime2 * x1) + (2 * t2 * tprime2 * cpX) + (t2 * t2 * x2); - final num extrema2Y = (tprime2 * tprime2 * y1) + + final double extrema2Y = (tprime2 * tprime2 * y1) + (2 * t2 * tprime2 * cpY) + (t2 * t2 * y2); // Expand bounds. @@ -867,7 +869,7 @@ class SurfacePath implements ui.Path { curY = y2; break; case PathCommandTypes.bezierCurveTo: - final BezierCurveTo cmd = op; + final BezierCurveTo cmd = op as BezierCurveTo; final double startX = curX; final double startY = curY; final double cpX1 = cmd.x1; @@ -902,13 +904,13 @@ class SurfacePath implements ui.Path { // Now find roots for quadratic equation with known coefficients // a,b,c // The roots are (-b+-sqrt(b*b-4*a*c)) / 2a - num s = (b * b) - (4 * a * c); + double s = (b * b) - (4 * a * c); // If s is negative, we have no real roots if ((s >= 0.0) && (a.abs() > epsilon)) { if (s == 0.0) { // we have only 1 root - final num t = -b / (2 * a); - final num tprime = 1.0 - t; + final double t = -b / (2 * a); + final double tprime = 1.0 - t; if ((t >= 0.0) && (t <= 1.0)) { extremaX = ((tprime * tprime * tprime) * startX) + ((3 * tprime * tprime * t) * cpX1) + @@ -920,8 +922,8 @@ class SurfacePath implements ui.Path { } else { // we have 2 roots s = math.sqrt(s); - num t = (-b - s) / (2 * a); - num tprime = 1.0 - t; + double t = (-b - s) / (2 * a); + double tprime = 1.0 - t; if ((t >= 0.0) && (t <= 1.0)) { extremaX = ((tprime * tprime * tprime) * startX) + ((3 * tprime * tprime * t) * cpX1) + @@ -960,13 +962,13 @@ class SurfacePath implements ui.Path { // Now find roots for quadratic equation with known coefficients // a,b,c // The roots are (-b+-sqrt(b*b-4*a*c)) / 2a - num s = (b * b) - (4 * a * c); + double s = (b * b) - (4 * a * c); // If s is negative, we have no real roots if ((s >= 0.0) && (a.abs() > epsilon)) { if (s == 0.0) { // we have only 1 root - final num t = -b / (2 * a); - final num tprime = 1.0 - t; + final double t = -b / (2 * a); + final double tprime = 1.0 - t; if ((t >= 0.0) && (t <= 1.0)) { extremaY = ((tprime * tprime * tprime) * startY) + ((3 * tprime * tprime * t) * cpY1) + @@ -978,8 +980,8 @@ class SurfacePath implements ui.Path { } else { // we have 2 roots s = math.sqrt(s); - final num t = (-b - s) / (2 * a); - final num tprime = 1.0 - t; + final double t = (-b - s) / (2 * a); + final double tprime = 1.0 - t; if ((t >= 0.0) && (t <= 1.0)) { extremaY = ((tprime * tprime * tprime) * startY) + ((3 * tprime * tprime * t) * cpY1) + @@ -989,8 +991,8 @@ class SurfacePath implements ui.Path { maxY = math.max(extremaY, maxY); } // check 2nd root - final num t2 = (-b + s) / (2 * a); - final num tprime2 = 1.0 - t2; + final double t2 = (-b + s) / (2 * a); + final double tprime2 = 1.0 - t2; if ((t2 >= 0.0) && (t2 <= 1.0)) { extremaY = ((tprime2 * tprime2 * tprime2) * startY) + ((3 * tprime2 * tprime2 * t2) * cpY1) + @@ -1006,7 +1008,7 @@ class SurfacePath implements ui.Path { curY = endY; break; case PathCommandTypes.rect: - final RectCommand cmd = op; + final RectCommand cmd = op as RectCommand; minX = cmd.x; double width = cmd.width; if (cmd.width < 0) { @@ -1025,7 +1027,7 @@ class SurfacePath implements ui.Path { maxY = minY + height; break; case PathCommandTypes.rRect: - final RRectCommand cmd = op; + final RRectCommand cmd = op as RRectCommand; final ui.RRect rRect = cmd.rrect; curX = minX = rRect.left; maxX = rRect.left + rRect.width; @@ -1072,7 +1074,7 @@ class SurfacePath implements ui.Path { /// /// Used for web optimization of physical shape represented as /// a persistent div. - ui.RRect get webOnlyPathAsRoundedRect { + ui.RRect? get webOnlyPathAsRoundedRect { if (subpaths.length != 1) { return null; } @@ -1088,7 +1090,7 @@ class SurfacePath implements ui.Path { /// /// Used for web optimization of physical shape represented as /// a persistent div. - ui.Rect get webOnlyPathAsRect { + ui.Rect? get webOnlyPathAsRect { if (subpaths.length != 1) { return null; } @@ -1106,7 +1108,7 @@ class SurfacePath implements ui.Path { /// /// Used for web optimization of physical shape represented as /// a persistent div. - Ellipse get webOnlyPathAsCircle { + Ellipse? get webOnlyPathAsCircle { if (subpaths.length != 1) { return null; } diff --git a/lib/web_ui/lib/src/engine/surface/path_metrics.dart b/lib/web_ui/lib/src/engine/surface/path_metrics.dart index 7ad30fd725dc3..7ac19658256ae 100644 --- a/lib/web_ui/lib/src/engine/surface/path_metrics.dart +++ b/lib/web_ui/lib/src/engine/surface/path_metrics.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 part of engine; const double kEpsilon = 0.000000001; @@ -36,10 +35,7 @@ class SurfacePathMetrics extends IterableBase /// Maintains a single instance of computed segments for set of PathMetric /// objects exposed through iterator. class _SurfacePathMeasure { - _SurfacePathMeasure(this._path, this.forceClosed) { - // nextContour will increment this to the zero based index. - _currentContourIndex = -1; - } + _SurfacePathMeasure(this._path, this.forceClosed); final SurfacePath _path; final List<_PathContourMeasure> _contours = []; @@ -48,12 +44,12 @@ class _SurfacePathMeasure { // have been implied when using [Path.addRect]) final bool forceClosed; - int _currentContourIndex; + // nextContour will increment this to the zero based index. + int _currentContourIndex = -1; int get currentContourIndex => _currentContourIndex; // Iterator index into [Path.subPaths] int _subPathIndex = -1; - _PathContourMeasure _contourMeasure; double length(int contourIndex) { assert(contourIndex <= currentContourIndex, @@ -71,7 +67,7 @@ class _SurfacePathMeasure { /// Returns null if the contour has zero [length]. /// /// The distance is clamped to the [length] of the current contour. - ui.Tangent getTangentForOffset(int contourIndex, double distance) { + ui.Tangent? getTangentForOffset(int contourIndex, double distance) { return _contours[contourIndex].getTangentForOffset(distance); } @@ -104,13 +100,11 @@ class _SurfacePathMeasure { return false; } ++_subPathIndex; - _contourMeasure = - _PathContourMeasure(_path.subpaths[_subPathIndex], forceClosed); - _contours.add(_contourMeasure); + _contours.add(_PathContourMeasure(_path.subpaths[_subPathIndex], forceClosed)); return true; } - ui.Path extractPath(int contourIndex, double start, double end, + ui.Path? extractPath(int contourIndex, double start, double end, {bool startWithMoveTo = true}) { return _contours[contourIndex].extractPath(start, end, startWithMoveTo); } @@ -133,10 +127,10 @@ class _PathContourMeasure { double get length => _contourLength; bool get isClosed => _isClosed; - double _contourLength = 0.0; + double _contourLength = 0; bool _isClosed = false; - ui.Tangent getTangentForOffset(double distance) { + ui.Tangent? getTangentForOffset(double distance) { final segmentIndex = _segmentIndexAtDistance(distance); if (segmentIndex == -1) { return null; @@ -190,7 +184,7 @@ class _PathContourMeasure { return segment.computeTangent(t); } - ui.Path extractPath( + ui.Path? extractPath( double startDistance, double stopDistance, bool startWithMoveTo) { if (startDistance < 0) { startDistance = 0; @@ -284,23 +278,25 @@ class _PathContourMeasure { currentX = x; currentY = y; }; - _EllipseSegmentResult ellipseResult; + + // TODO(yjbanov): make late final (https://github.com/dart-lang/sdk/issues/42422) + _EllipseSegmentResult? ellipseResult; for (PathCommand command in commands) { switch (command.type) { case PathCommandTypes.moveTo: - final MoveTo moveTo = command; + final MoveTo moveTo = command as MoveTo; currentX = moveTo.x; currentY = moveTo.y; haveSeenMoveTo = true; break; case PathCommandTypes.lineTo: assert(haveSeenMoveTo); - final LineTo lineTo = command; + final LineTo lineTo = command as LineTo; lineToHandler(lineTo.x, lineTo.y); break; case PathCommandTypes.bezierCurveTo: assert(haveSeenMoveTo); - final BezierCurveTo curve = command; + final BezierCurveTo curve = command as BezierCurveTo; // Compute cubic curve distance. distance = _computeCubicSegments( currentX, @@ -318,7 +314,7 @@ class _PathContourMeasure { break; case PathCommandTypes.quadraticCurveTo: assert(haveSeenMoveTo); - final QuadraticCurveTo quadraticCurveTo = command; + final QuadraticCurveTo quadraticCurveTo = command as QuadraticCurveTo; // Compute quad curve distance. distance = _computeQuadSegments( currentX, @@ -334,7 +330,7 @@ class _PathContourMeasure { case PathCommandTypes.close: break; case PathCommandTypes.ellipse: - final Ellipse ellipse = command; + final Ellipse ellipse = command as Ellipse; ellipseResult ??= _EllipseSegmentResult(); _computeEllipseSegments( currentX, @@ -348,15 +344,15 @@ class _PathContourMeasure { ellipse.radiusX, ellipse.radiusY, ellipse.anticlockwise, - ellipseResult, + ellipseResult!, _segments); - distance = ellipseResult.distance; - currentX = ellipseResult.endPointX; - currentY = ellipseResult.endPointY; + distance = ellipseResult!.distance; + currentX = ellipseResult!.endPointX; + currentY = ellipseResult!.endPointY; _isClosed = true; break; case PathCommandTypes.rRect: - final RRectCommand rrectCommand = command; + final RRectCommand rrectCommand = command as RRectCommand; final ui.RRect rrect = rrectCommand.rrect; RRectMetricsRenderer(moveToCallback: (double x, double y) { currentX = x; @@ -386,16 +382,16 @@ class _PathContourMeasure { radiusX, radiusY, antiClockwise, - ellipseResult, + ellipseResult!, _segments); - distance = ellipseResult.distance; - currentX = ellipseResult.endPointX; - currentY = ellipseResult.endPointY; + distance = ellipseResult!.distance; + currentX = ellipseResult!.endPointX; + currentY = ellipseResult!.endPointY; }).render(rrect); _isClosed = true; break; case PathCommandTypes.rect: - final RectCommand rectCommand = command; + final RectCommand rectCommand = command as RectCommand; final double x = rectCommand.x; final double y = rectCommand.y; final double width = rectCommand.width; @@ -612,13 +608,14 @@ class _PathContourMeasure { /// Tracks iteration from one segment of a path to the next for measurement. class SurfacePathMetricIterator implements Iterator { + // ignore: unnecessary_null_comparison SurfacePathMetricIterator._(this._pathMeasure) : assert(_pathMeasure != null); - SurfacePathMetric _pathMetric; + SurfacePathMetric? _pathMetric; _SurfacePathMeasure _pathMeasure; @override - SurfacePathMetric get current => _pathMetric; + SurfacePathMetric get current => _pathMetric!; @override bool moveNext() { @@ -655,7 +652,7 @@ const double _fTolerance = 0.5; /// to maintain consistency with native platforms. class SurfacePathMetric implements ui.PathMetric { SurfacePathMetric._(this._measure) - : assert(_measure != null), + : assert(_measure != null), // ignore: unnecessary_null_comparison length = _measure.length(_measure.currentContourIndex), isClosed = _measure.isClosed(_measure.currentContourIndex), contourIndex = _measure.currentContourIndex; @@ -699,7 +696,7 @@ class SurfacePathMetric implements ui.PathMetric { /// /// The distance is clamped to the [length] of the current contour. @override - ui.Tangent getTangentForOffset(double distance) { + ui.Tangent? getTangentForOffset(double distance) { return _measure.getTangentForOffset(contourIndex, distance); } @@ -708,7 +705,7 @@ class SurfacePathMetric implements ui.PathMetric { /// `start` and `end` are pinned to legal values (0..[length]) /// Returns null if the segment is 0 length or `start` > `stop`. /// Begin the segment with a moveTo if `startWithMoveTo` is true. - ui.Path extractPath(double start, double end, {bool startWithMoveTo = true}) { + ui.Path? extractPath(double start, double end, {bool startWithMoveTo = true}) { return _measure.extractPath(contourIndex, start, end, startWithMoveTo: startWithMoveTo); } @@ -718,10 +715,9 @@ class SurfacePathMetric implements ui.PathMetric { } class _EllipseSegmentResult { - double endPointX; - double endPointY; - double distance; - _EllipseSegmentResult(); + double endPointX = 0; + double endPointY = 0; + double distance = 0; } // Given a vector dx, dy representing slope, normalize and return as [ui.Offset]. @@ -734,9 +730,9 @@ ui.Offset _normalizeSlope(double dx, double dy) { class _SurfaceTangent extends ui.Tangent { const _SurfaceTangent(ui.Offset position, ui.Offset vector, this.t) - : assert(position != null), - assert(vector != null), - assert(t != null), + : assert(position != null), // ignore: unnecessary_null_comparison + assert(vector != null), // ignore: unnecessary_null_comparison + assert(t != null), // ignore: unnecessary_null_comparison super(position, vector); // Normalized distance of tangent point from start of a contour. diff --git a/lib/web_ui/lib/src/engine/surface/picture.dart b/lib/web_ui/lib/src/engine/surface/picture.dart index cb67a0e3e526d..2e57ff1279972 100644 --- a/lib/web_ui/lib/src/engine/surface/picture.dart +++ b/lib/web_ui/lib/src/engine/surface/picture.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; // TODO(yjbanov): this is currently very naive. We probably want to cache @@ -36,10 +36,10 @@ void _reduceCanvasMemoryUsage() { /// canvases forcing us to allocate new large canvases. class _PaintRequest { _PaintRequest({ - this.canvasSize, - this.paintCallback, - }) : assert(canvasSize != null), - assert(paintCallback != null); + required this.canvasSize, + required this.paintCallback, + }) : assert(canvasSize != null), // ignore: unnecessary_null_comparison + assert(paintCallback != null); // ignore: unnecessary_null_comparison final ui.Size canvasSize; final ui.VoidCallback paintCallback; @@ -50,7 +50,7 @@ class _PaintRequest { /// the number of reusable canvases. List<_PaintRequest> _paintQueue = <_PaintRequest>[]; -void _recycleCanvas(EngineCanvas canvas) { +void _recycleCanvas(EngineCanvas? canvas) { if (canvas is BitmapCanvas) { if (canvas.isReusable()) { _recycledCanvases.add(canvas); @@ -99,7 +99,7 @@ PersistedHoudiniPicture houdiniPictureFactory( class PersistedHoudiniPicture extends PersistedPicture { PersistedHoudiniPicture(double dx, double dy, ui.Picture picture, int hints) - : super(dx, dy, picture, hints) { + : super(dx, dy, picture as EnginePicture, hints) { if (!_cssPainterRegistered) { _registerCssPainter(); } @@ -139,20 +139,20 @@ class PersistedHoudiniPicture extends PersistedPicture { int get bitmapPixelCount => 0; @override - void applyPaint(EngineCanvas oldCanvas) { + void applyPaint(EngineCanvas? oldCanvas) { _recycleCanvas(oldCanvas); final HoudiniCanvas canvas = HoudiniCanvas(_optimalLocalCullRect); _canvas = canvas; - domRenderer.clearDom(rootElement); - rootElement.append(_canvas.rootElement); - picture.recordingCanvas.apply(_canvas, _optimalLocalCullRect); + domRenderer.clearDom(rootElement!); + rootElement!.append(_canvas!.rootElement); + picture.recordingCanvas!.apply(_canvas, _optimalLocalCullRect); canvas.commit(); } } class PersistedStandardPicture extends PersistedPicture { PersistedStandardPicture(double dx, double dy, ui.Picture picture, int hints) - : super(dx, dy, picture, hints); + : super(dx, dy, picture as EnginePicture, hints); @override double matchForUpdate(PersistedStandardPicture existingSurface) { @@ -161,15 +161,15 @@ class PersistedStandardPicture extends PersistedPicture { return 0.0; } - if (!existingSurface.picture.recordingCanvas.didDraw) { + if (!existingSurface.picture.recordingCanvas!.didDraw) { // The previous surface didn't draw anything and therefore has no // resources to reuse. return 1.0; } final bool didRequireBitmap = - existingSurface.picture.recordingCanvas.hasArbitraryPaint; - final bool requiresBitmap = picture.recordingCanvas.hasArbitraryPaint; + existingSurface.picture.recordingCanvas!.hasArbitraryPaint; + final bool requiresBitmap = picture.recordingCanvas!.hasArbitraryPaint; if (didRequireBitmap != requiresBitmap) { // Switching canvas types is always expensive. return 1.0; @@ -179,17 +179,17 @@ class PersistedStandardPicture extends PersistedPicture { // which point we may return other values here. return 1.0; } else { - final BitmapCanvas oldCanvas = existingSurface._canvas; + final BitmapCanvas? oldCanvas = existingSurface._canvas as BitmapCanvas?; if (oldCanvas == null) { // We did not allocate a canvas last time. This can happen when the // picture is completely clipped out of the view. return 1.0; - } else if (!oldCanvas.doesFitBounds(_exactLocalCullRect)) { + } else if (!oldCanvas.doesFitBounds(_exactLocalCullRect!)) { // The canvas needs to be resized before painting. return 1.0; } else { - final int newPixelCount = BitmapCanvas._widthToPhysical(_exactLocalCullRect.width) - * BitmapCanvas._heightToPhysical(_exactLocalCullRect.height); + final int newPixelCount = BitmapCanvas._widthToPhysical(_exactLocalCullRect!.width) + * BitmapCanvas._heightToPhysical(_exactLocalCullRect!.height); final int oldPixelCount = oldCanvas._widthInBitmapPixels * oldCanvas._heightInBitmapPixels; @@ -206,7 +206,7 @@ class PersistedStandardPicture extends PersistedPicture { } @override - Matrix4 get localTransformInverse => null; + Matrix4? get localTransformInverse => null; @override int get bitmapPixelCount { @@ -214,39 +214,39 @@ class PersistedStandardPicture extends PersistedPicture { return 0; } - final BitmapCanvas bitmapCanvas = _canvas; + final BitmapCanvas bitmapCanvas = _canvas as BitmapCanvas; return bitmapCanvas.bitmapPixelCount; } @override - void applyPaint(EngineCanvas oldCanvas) { - if (picture.recordingCanvas.hasArbitraryPaint) { + void applyPaint(EngineCanvas? oldCanvas) { + if (picture.recordingCanvas!.hasArbitraryPaint) { _applyBitmapPaint(oldCanvas); } else { _applyDomPaint(oldCanvas); } } - void _applyDomPaint(EngineCanvas oldCanvas) { + void _applyDomPaint(EngineCanvas? oldCanvas) { _recycleCanvas(oldCanvas); _canvas = DomCanvas(); - domRenderer.clearDom(rootElement); - rootElement.append(_canvas.rootElement); - picture.recordingCanvas.apply(_canvas, _optimalLocalCullRect); + domRenderer.clearDom(rootElement!); + rootElement!.append(_canvas!.rootElement); + picture.recordingCanvas!.apply(_canvas, _optimalLocalCullRect); } - void _applyBitmapPaint(EngineCanvas oldCanvas) { + void _applyBitmapPaint(EngineCanvas? oldCanvas) { if (oldCanvas is BitmapCanvas && - oldCanvas.doesFitBounds(_optimalLocalCullRect) && + oldCanvas.doesFitBounds(_optimalLocalCullRect!) && oldCanvas.isReusable()) { if (_debugShowCanvasReuseStats) { DebugCanvasReuseOverlay.instance.keptCount++; } - oldCanvas.bounds = _optimalLocalCullRect; + oldCanvas.bounds = _optimalLocalCullRect!; _canvas = oldCanvas; oldCanvas.setElementCache(_elementCache); - _canvas.clear(); - picture.recordingCanvas.apply(_canvas, _optimalLocalCullRect); + _canvas!.clear(); + picture.recordingCanvas!.apply(_canvas, _optimalLocalCullRect); } else { // We can't use the old canvas because the size has changed, so we put // it in a cache for later reuse. @@ -256,20 +256,20 @@ class PersistedStandardPicture extends PersistedPicture { // picture to be painted after the update cycle is done syncing the layer // tree then reuse canvases that were freed up. _paintQueue.add(_PaintRequest( - canvasSize: _optimalLocalCullRect.size, + canvasSize: _optimalLocalCullRect!.size, paintCallback: () { - _canvas = _findOrCreateCanvas(_optimalLocalCullRect); + _canvas = _findOrCreateCanvas(_optimalLocalCullRect!); assert(_canvas is BitmapCanvas - && (_canvas as BitmapCanvas)._elementCache == _elementCache); + && (_canvas as BitmapCanvas?)!._elementCache == _elementCache); if (_debugExplainSurfaceStats) { - final BitmapCanvas bitmapCanvas = _canvas; + final BitmapCanvas bitmapCanvas = _canvas as BitmapCanvas; _surfaceStatsFor(this).paintPixelCount += bitmapCanvas.bitmapPixelCount; } - domRenderer.clearDom(rootElement); - rootElement.append(_canvas.rootElement); - _canvas.clear(); - picture.recordingCanvas.apply(_canvas, _optimalLocalCullRect); + domRenderer.clearDom(rootElement!); + rootElement!.append(_canvas!.rootElement); + _canvas!.clear(); + picture.recordingCanvas!.apply(_canvas, _optimalLocalCullRect); }, )); } @@ -288,7 +288,7 @@ class PersistedStandardPicture extends PersistedPicture { /// sure we do not use too much memory for small canvases. BitmapCanvas _findOrCreateCanvas(ui.Rect bounds) { final ui.Size canvasSize = bounds.size; - BitmapCanvas bestRecycledCanvas; + BitmapCanvas? bestRecycledCanvas; double lastPixelCount = double.infinity; for (int i = 0; i < _recycledCanvases.length; i++) { final BitmapCanvas candidate = _recycledCanvases[i]; @@ -358,19 +358,19 @@ class PersistedStandardPicture extends PersistedPicture { /// to draw shapes and text. abstract class PersistedPicture extends PersistedLeafSurface { PersistedPicture(this.dx, this.dy, this.picture, this.hints) - : localPaintBounds = picture.recordingCanvas.pictureBounds; + : localPaintBounds = picture.recordingCanvas!.pictureBounds; - EngineCanvas _canvas; + EngineCanvas? _canvas; /// Returns the canvas used by this picture layer. /// /// Useful for tests. - EngineCanvas get debugCanvas => _canvas; + EngineCanvas? get debugCanvas => _canvas; final double dx; final double dy; final EnginePicture picture; - final ui.Rect localPaintBounds; + final ui.Rect? localPaintBounds; final int hints; /// Cache for reusing elements such as images across picture updates. @@ -384,10 +384,10 @@ abstract class PersistedPicture extends PersistedLeafSurface { @override void recomputeTransformAndClip() { - _transform = parent._transform; + _transform = parent!._transform; if (dx != 0.0 || dy != 0.0) { - _transform = _transform.clone(); - _transform.translate(dx, dy); + _transform = _transform!.clone(); + _transform!.translate(dx, dy); } _computeExactCullRects(); } @@ -399,14 +399,14 @@ abstract class PersistedPicture extends PersistedLeafSurface { /// contain everything that's visible, but it may be bigger than necessary. /// Therefore it should not be used for clipping. It is meant to be used for /// optimizing canvas allocation. - ui.Rect get optimalLocalCullRect => _optimalLocalCullRect; - ui.Rect _optimalLocalCullRect; + ui.Rect? get optimalLocalCullRect => _optimalLocalCullRect; + ui.Rect? _optimalLocalCullRect; /// Same as [optimalLocalCullRect] but in screen coordinate system. - ui.Rect get debugExactGlobalCullRect => _exactGlobalCullRect; - ui.Rect _exactGlobalCullRect; + ui.Rect? get debugExactGlobalCullRect => _exactGlobalCullRect; + ui.Rect? _exactGlobalCullRect; - ui.Rect _exactLocalCullRect; + ui.Rect? _exactLocalCullRect; /// Computes the canvas paint bounds based on the estimated paint bounds and /// the scaling produced by transformations. @@ -420,15 +420,15 @@ abstract class PersistedPicture extends PersistedLeafSurface { assert(transform != null); assert(localPaintBounds != null); - if (parent._projectedClip == null) { + if (parent!._projectedClip == null) { // Compute and cache chain of clipping bounds on parent of picture since // parent may include multiple pictures so it can be reused by all // child pictures. - ui.Rect bounds; - PersistedSurface parentSurface = parent; + ui.Rect? bounds; + PersistedSurface? parentSurface = parent; final Matrix4 clipTransform = Matrix4.identity(); while (parentSurface != null) { - final ui.Rect localClipBounds = parentSurface._localClipBounds; + final ui.Rect? localClipBounds = parentSurface._localClipBounds; if (localClipBounds != null) { if (bounds == null) { bounds = transformRect(clipTransform, localClipBounds); @@ -437,7 +437,7 @@ abstract class PersistedPicture extends PersistedLeafSurface { bounds.intersect(transformRect(clipTransform, localClipBounds)); } } - final Matrix4 localInverse = parentSurface.localTransformInverse; + final Matrix4? localInverse = parentSurface.localTransformInverse; if (localInverse != null && !localInverse.isIdentity()) { clipTransform.multiply(localInverse); } @@ -447,30 +447,30 @@ abstract class PersistedPicture extends PersistedLeafSurface { bounds = ui.Rect.zero; } // Cache projected clip on parent. - parent._projectedClip = bounds; + parent!._projectedClip = bounds; } // Intersect localPaintBounds with parent projected clip to calculate // and cache [_exactLocalCullRect]. - if (parent._projectedClip == null) { + if (parent!._projectedClip == null) { _exactLocalCullRect = localPaintBounds; } else { - _exactLocalCullRect = localPaintBounds.intersect(parent._projectedClip); + _exactLocalCullRect = localPaintBounds!.intersect(parent!._projectedClip!); } - if (_exactLocalCullRect.width <= 0 || _exactLocalCullRect.height <= 0) { + if (_exactLocalCullRect!.width <= 0 || _exactLocalCullRect!.height <= 0) { _exactLocalCullRect = ui.Rect.zero; _exactGlobalCullRect = ui.Rect.zero; } else { assert(() { - _exactGlobalCullRect = transformRect(transform, _exactLocalCullRect); + _exactGlobalCullRect = transformRect(transform!, _exactLocalCullRect!); return true; }()); } } - bool _computeOptimalCullRect(PersistedPicture oldSurface) { + bool _computeOptimalCullRect(PersistedPicture? oldSurface) { assert(_exactLocalCullRect != null); - if (oldSurface == null || !oldSurface.picture.recordingCanvas.didDraw) { + if (oldSurface == null || !oldSurface.picture.recordingCanvas!.didDraw) { // First useful paint. _optimalLocalCullRect = _exactLocalCullRect; return true; @@ -479,7 +479,7 @@ abstract class PersistedPicture extends PersistedLeafSurface { assert(oldSurface._optimalLocalCullRect != null); final bool surfaceBeingRetained = identical(oldSurface, this); - final ui.Rect oldOptimalLocalCullRect = surfaceBeingRetained + final ui.Rect? oldOptimalLocalCullRect = surfaceBeingRetained ? _optimalLocalCullRect : oldSurface._optimalLocalCullRect; @@ -490,7 +490,7 @@ abstract class PersistedPicture extends PersistedLeafSurface { return oldOptimalLocalCullRect != ui.Rect.zero; } - if (rectContainsOther(oldOptimalLocalCullRect, _exactLocalCullRect)) { + if (rectContainsOther(oldOptimalLocalCullRect!, _exactLocalCullRect!)) { // The cull rect we computed in the past contains the newly computed cull // rect. This can happen, for example, when the picture is being shrunk by // a clip when it is scrolled out of the screen. In this case we do not @@ -512,18 +512,18 @@ abstract class PersistedPicture extends PersistedLeafSurface { // Compute the delta, by which each of the side of the clip rect has "moved" // since the last time we updated the cull rect. - final double leftwardDelta = oldOptimalLocalCullRect.left - _exactLocalCullRect.left; - final double upwardDelta = oldOptimalLocalCullRect.top - _exactLocalCullRect.top; - final double rightwardDelta = _exactLocalCullRect.right - oldOptimalLocalCullRect.right; - final double bottomwardDelta = _exactLocalCullRect.bottom - oldOptimalLocalCullRect.bottom; + final double leftwardDelta = oldOptimalLocalCullRect.left - _exactLocalCullRect!.left; + final double upwardDelta = oldOptimalLocalCullRect.top - _exactLocalCullRect!.top; + final double rightwardDelta = _exactLocalCullRect!.right - oldOptimalLocalCullRect.right; + final double bottomwardDelta = _exactLocalCullRect!.bottom - oldOptimalLocalCullRect.bottom; // Compute the new optimal rect to paint into. final ui.Rect newLocalCullRect = ui.Rect.fromLTRB( - _exactLocalCullRect.left - _predictTrend(leftwardDelta, _exactLocalCullRect.width), - _exactLocalCullRect.top - _predictTrend(upwardDelta, _exactLocalCullRect.height), - _exactLocalCullRect.right + _predictTrend(rightwardDelta, _exactLocalCullRect.width), - _exactLocalCullRect.bottom + _predictTrend(bottomwardDelta, _exactLocalCullRect.height), - ).intersect(localPaintBounds); + _exactLocalCullRect!.left - _predictTrend(leftwardDelta, _exactLocalCullRect!.width), + _exactLocalCullRect!.top - _predictTrend(upwardDelta, _exactLocalCullRect!.height), + _exactLocalCullRect!.right + _predictTrend(rightwardDelta, _exactLocalCullRect!.width), + _exactLocalCullRect!.bottom + _predictTrend(bottomwardDelta, _exactLocalCullRect!.height), + ).intersect(localPaintBounds!); final bool localCullRectChanged = _optimalLocalCullRect != newLocalCullRect; _optimalLocalCullRect = newLocalCullRect; @@ -555,14 +555,14 @@ abstract class PersistedPicture extends PersistedLeafSurface { /// return zero. int get bitmapPixelCount; - void _applyPaint(PersistedPicture oldSurface) { - final EngineCanvas oldCanvas = oldSurface?._canvas; - if (!picture.recordingCanvas.didDraw || _optimalLocalCullRect.isEmpty) { + void _applyPaint(PersistedPicture? oldSurface) { + final EngineCanvas? oldCanvas = oldSurface?._canvas; + if (!picture.recordingCanvas!.didDraw || _optimalLocalCullRect!.isEmpty) { // The picture is empty, or it has been completely clipped out. Skip // painting. This removes all the setup work and scaffolding objects // that won't be useful for anything anyway. _recycleCanvas(oldCanvas); - domRenderer.clearDom(rootElement); + domRenderer.clearDom(rootElement!); _canvas = null; return; } @@ -576,10 +576,10 @@ abstract class PersistedPicture extends PersistedLeafSurface { } /// Concrete implementations implement this method to do actual painting. - void applyPaint(EngineCanvas oldCanvas); + void applyPaint(EngineCanvas? oldCanvas); void _applyTranslate() { - rootElement.style.transform = 'translate(${dx}px, ${dy}px)'; + rootElement!.style.transform = 'translate(${dx}px, ${dy}px)'; } @override @@ -640,14 +640,14 @@ abstract class PersistedPicture extends PersistedLeafSurface { @override void debugPrintChildren(StringBuffer buffer, int indent) { super.debugPrintChildren(buffer, indent); - if (rootElement != null && rootElement.firstChild != null) { - final html.Element firstChild = rootElement.firstChild; + if (rootElement != null && rootElement!.firstChild != null) { + final html.Element firstChild = rootElement!.firstChild as html.Element; final String canvasTag = firstChild.tagName.toLowerCase(); - final int canvasHash = rootElement.firstChild.hashCode; + final int canvasHash = rootElement!.firstChild!.hashCode; buffer.writeln('${' ' * (indent + 1)}<$canvasTag @$canvasHash />'); } else if (rootElement != null) { buffer.writeln( - '${' ' * (indent + 1)}<${rootElement.tagName.toLowerCase()} @$hashCode />'); + '${' ' * (indent + 1)}<${rootElement!.tagName.toLowerCase()} @$hashCode />'); } else { buffer.writeln('${' ' * (indent + 1)}'); } @@ -657,8 +657,8 @@ abstract class PersistedPicture extends PersistedLeafSurface { void debugValidate(List validationErrors) { super.debugValidate(validationErrors); - if (picture.recordingCanvas.didDraw) { - if (!_optimalLocalCullRect.isEmpty && debugCanvas == null) { + if (picture.recordingCanvas!.didDraw) { + if (!_optimalLocalCullRect!.isEmpty && debugCanvas == null) { validationErrors .add('$runtimeType has non-trivial picture but it has null canvas'); } diff --git a/lib/web_ui/lib/src/engine/surface/platform_view.dart b/lib/web_ui/lib/src/engine/surface/platform_view.dart index 8f0fd5cfd0de2..df75492cc8b82 100644 --- a/lib/web_ui/lib/src/engine/surface/platform_view.dart +++ b/lib/web_ui/lib/src/engine/surface/platform_view.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// A surface containing a platform view, which is an HTML element. @@ -13,7 +13,7 @@ class PersistedPlatformView extends PersistedLeafSurface { final double width; final double height; - html.ShadowRoot _shadowRoot; + late html.ShadowRoot _shadowRoot; PersistedPlatformView(this.viewId, this.dx, this.dy, this.width, this.height); @@ -46,7 +46,7 @@ class PersistedPlatformView extends PersistedLeafSurface { all: initial; }'''; _shadowRoot.append(_styleReset); - final html.Element platformView = + final html.Element? platformView = ui.platformViewRegistry.getCreatedView(viewId); if (platformView != null) { _shadowRoot.append(platformView); @@ -57,16 +57,16 @@ class PersistedPlatformView extends PersistedLeafSurface { } @override - Matrix4 get localTransformInverse => null; + Matrix4? get localTransformInverse => null; @override void apply() { - rootElement.style + rootElement!.style ..transform = 'translate(${dx}px, ${dy}px)' ..width = '${width}px' ..height = '${height}px'; // Set size of the root element created by the PlatformView. - final html.Element platformView = + final html.Element? platformView = ui.platformViewRegistry.getCreatedView(viewId); if (platformView != null) { platformView.style diff --git a/lib/web_ui/lib/src/engine/surface/recording_canvas.dart b/lib/web_ui/lib/src/engine/surface/recording_canvas.dart index 650b2d5e4e41b..7ae1c8edcb2ea 100644 --- a/lib/web_ui/lib/src/engine/surface/recording_canvas.dart +++ b/lib/web_ui/lib/src/engine/surface/recording_canvas.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Enable this to print every command applied by a canvas. @@ -34,14 +34,14 @@ class RawRecordingCanvas extends BitmapCanvas @override ui.Picture endRecording() => throw UnsupportedError(''); - RecordingCanvas _canvas; // ignore: unused_field + RecordingCanvas? _canvas; // ignore: unused_field bool _isRecording = true; // ignore: unused_field @override bool get isRecording => true; - ui.Rect cullRect; + ui.Rect? cullRect; } /// Records canvas commands to be applied to a [EngineCanvas]. @@ -56,14 +56,14 @@ class RecordingCanvas { /// The bounds contain the full picture. The commands recorded for the picture /// are later pruned based on the clip applied to the picture. See the [apply] /// method for more details. - ui.Rect get pictureBounds { + ui.Rect? get pictureBounds { assert( _debugRecordingEnded, 'Picture bounds not available yet. Call [endRecording] before accessing picture bounds.', ); return _pictureBounds; } - ui.Rect _pictureBounds; + ui.Rect? _pictureBounds; final List _commands = []; @@ -75,7 +75,7 @@ class RecordingCanvas { throw UnsupportedError('For debugging only.'); } - RecordingCanvas(ui.Rect bounds) : _paintBounds = _PaintBounds(bounds); + RecordingCanvas(ui.Rect? bounds) : _paintBounds = _PaintBounds(bounds ?? ui.Rect.largest); /// Whether this canvas is doing arbitrary paint operations not expressible /// via DOM elements. @@ -125,14 +125,14 @@ class RecordingCanvas { /// a minimum). The commands that fall outside the clip are skipped and are /// not applied to the [engineCanvas]. A command must have a non-zero /// intersection with the clip in order to be applied. - void apply(EngineCanvas engineCanvas, ui.Rect clipRect) { + void apply(EngineCanvas? engineCanvas, ui.Rect? clipRect) { assert(_debugRecordingEnded); if (_debugDumpPaintCommands) { final StringBuffer debugBuf = StringBuffer(); int skips = 0; debugBuf.writeln( - '--- Applying RecordingCanvas to ${engineCanvas.runtimeType} ' - 'with bounds $_paintBounds and clip $clipRect (w = ${clipRect.width},' + '--- Applying RecordingCanvas to ${engineCanvas!.runtimeType} ' + 'with bounds $_paintBounds and clip $clipRect (w = ${clipRect!.width},' ' h = ${clipRect.height})'); for (int i = 0; i < _commands.length; i++) { final PaintCommand command = _commands[i]; @@ -154,7 +154,7 @@ class RecordingCanvas { print(debugBuf); } else { try { - if (rectContainsOther(clipRect, _pictureBounds)) { + if (rectContainsOther(clipRect!, _pictureBounds!)) { // No need to check if commands fit in the clip rect if we already // know that the entire picture fits it. for (int i = 0, len = _commands.length; i < len; i++) { @@ -182,11 +182,11 @@ class RecordingCanvas { } } } - engineCanvas.endOfPaint(); + engineCanvas!.endOfPaint(); } /// Prints recorded commands. - String debugPrintCommands() { + String? debugPrintCommands() { if (assertionsEnabled) { final StringBuffer debugBuf = StringBuffer(); for (int i = 0; i < _commands.length; i++) { @@ -287,7 +287,7 @@ class RecordingCanvas { void clipPath(ui.Path path, {bool doAntiAlias = true}) { assert(!_debugRecordingEnded); - final PaintClipPath command = PaintClipPath(path); + final PaintClipPath command = PaintClipPath(path as SurfacePath); _paintBounds.clipRect(path.getBounds(), command); _hasArbitraryPaint = true; _commands.add(command); @@ -453,19 +453,19 @@ class RecordingCanvas { if (paint.shader == null) { // For Rect/RoundedRect paths use drawRect/drawRRect code paths for // DomCanvas optimization. - SurfacePath sPath = path; - final ui.Rect rect = sPath.webOnlyPathAsRect; + SurfacePath sPath = path as SurfacePath; + final ui.Rect? rect = sPath.webOnlyPathAsRect; if (rect != null) { drawRect(rect, paint); return; } - final ui.RRect rrect = sPath.webOnlyPathAsRoundedRect; + final ui.RRect? rrect = sPath.webOnlyPathAsRoundedRect; if (rrect != null) { drawRRect(rrect, paint); return; } } - SurfacePath sPath = path; + SurfacePath sPath = path as SurfacePath; if (sPath.subpaths.isNotEmpty) { _hasArbitraryPaint = true; _didDraw = true; @@ -476,7 +476,7 @@ class RecordingCanvas { } // Clone path so it can be reused for subsequent draw calls. final ui.Path clone = SurfacePath._shallowCopy(path); - final PaintDrawPath command = PaintDrawPath(clone, paint.paintData); + final PaintDrawPath command = PaintDrawPath(clone as SurfacePath, paint.paintData); _paintBounds.grow(pathBounds, command); clone.fillType = sPath.fillType; _commands.add(command); @@ -506,7 +506,7 @@ class RecordingCanvas { void drawParagraph(ui.Paragraph paragraph, ui.Offset offset) { assert(!_debugRecordingEnded); - final EngineParagraph engineParagraph = paragraph; + final EngineParagraph engineParagraph = paragraph as EngineParagraph; if (!engineParagraph._isLaidOut) { // Ignore non-laid out paragraphs. This matches Flutter's behavior. return; @@ -536,7 +536,7 @@ class RecordingCanvas { _didDraw = true; final ui.Rect shadowRect = computePenumbraBounds(path.getBounds(), elevation); - final PaintDrawShadow command = PaintDrawShadow(path, color, elevation, transparentOccluder); + final PaintDrawShadow command = PaintDrawShadow(path as SurfacePath, color, elevation, transparentOccluder); _paintBounds.grow(shadowRect, command); _commands.add(command); } @@ -554,9 +554,6 @@ class RecordingCanvas { void drawRawPoints( ui.PointMode pointMode, Float32List points, SurfacePaint paint) { assert(!_debugRecordingEnded); - if (paint.strokeWidth == null) { - return; - } _hasArbitraryPaint = true; _didDraw = true; final PaintDrawPoints command = PaintDrawPoints(pointMode, points, paint.paintData); @@ -606,7 +603,7 @@ class RecordingCanvas { abstract class PaintCommand { const PaintCommand(); - void apply(EngineCanvas canvas); + void apply(EngineCanvas? canvas); void serializeToCssPaint(List> serializedCommands); } @@ -634,14 +631,14 @@ abstract class DrawCommand extends PaintCommand { double bottomBound = double.infinity; /// Whether this command intersects with the [clipRect]. - bool isInvisible(ui.Rect clipRect) { + bool isInvisible(ui.Rect? clipRect) { if (isClippedOut) { return true; } // Check top and bottom first because vertical scrolling is more common // than horizontal scrolling. - return bottomBound < clipRect.top || + return bottomBound < clipRect!.top || topBound > clipRect.bottom || rightBound < clipRect.left || leftBound > clipRect.right; @@ -652,8 +649,8 @@ class PaintSave extends PaintCommand { const PaintSave(); @override - void apply(EngineCanvas canvas) { - canvas.save(); + void apply(EngineCanvas? canvas) { + canvas!.save(); } @override @@ -675,8 +672,8 @@ class PaintRestore extends PaintCommand { const PaintRestore(); @override - void apply(EngineCanvas canvas) { - canvas.restore(); + void apply(EngineCanvas? canvas) { + canvas!.restore(); } @override @@ -701,8 +698,8 @@ class PaintTranslate extends PaintCommand { PaintTranslate(this.dx, this.dy); @override - void apply(EngineCanvas canvas) { - canvas.translate(dx, dy); + void apply(EngineCanvas? canvas) { + canvas!.translate(dx, dy); } @override @@ -727,8 +724,8 @@ class PaintScale extends PaintCommand { PaintScale(this.sx, this.sy); @override - void apply(EngineCanvas canvas) { - canvas.scale(sx, sy); + void apply(EngineCanvas? canvas) { + canvas!.scale(sx, sy); } @override @@ -752,8 +749,8 @@ class PaintRotate extends PaintCommand { PaintRotate(this.radians); @override - void apply(EngineCanvas canvas) { - canvas.rotate(radians); + void apply(EngineCanvas? canvas) { + canvas!.rotate(radians); } @override @@ -777,8 +774,8 @@ class PaintTransform extends PaintCommand { PaintTransform(this.matrix4); @override - void apply(EngineCanvas canvas) { - canvas.transform(matrix4); + void apply(EngineCanvas? canvas) { + canvas!.transform(matrix4); } @override @@ -803,8 +800,8 @@ class PaintSkew extends PaintCommand { PaintSkew(this.sx, this.sy); @override - void apply(EngineCanvas canvas) { - canvas.skew(sx, sy); + void apply(EngineCanvas? canvas) { + canvas!.skew(sx, sy); } @override @@ -828,8 +825,8 @@ class PaintClipRect extends DrawCommand { PaintClipRect(this.rect); @override - void apply(EngineCanvas canvas) { - canvas.clipRect(rect); + void apply(EngineCanvas? canvas) { + canvas!.clipRect(rect); } @override @@ -853,8 +850,8 @@ class PaintClipRRect extends DrawCommand { PaintClipRRect(this.rrect); @override - void apply(EngineCanvas canvas) { - canvas.clipRRect(rrect); + void apply(EngineCanvas? canvas) { + canvas!.clipRRect(rrect); } @override @@ -881,8 +878,8 @@ class PaintClipPath extends DrawCommand { PaintClipPath(this.path); @override - void apply(EngineCanvas canvas) { - canvas.clipPath(path); + void apply(EngineCanvas? canvas) { + canvas!.clipPath(path); } @override @@ -907,8 +904,8 @@ class PaintDrawColor extends DrawCommand { PaintDrawColor(this.color, this.blendMode); @override - void apply(EngineCanvas canvas) { - canvas.drawColor(color, blendMode); + void apply(EngineCanvas? canvas) { + canvas!.drawColor(color, blendMode); } @override @@ -935,8 +932,8 @@ class PaintDrawLine extends DrawCommand { PaintDrawLine(this.p1, this.p2, this.paint); @override - void apply(EngineCanvas canvas) { - canvas.drawLine(p1, p2, paint); + void apply(EngineCanvas? canvas) { + canvas!.drawLine(p1, p2, paint); } @override @@ -967,8 +964,8 @@ class PaintDrawPaint extends DrawCommand { PaintDrawPaint(this.paint); @override - void apply(EngineCanvas canvas) { - canvas.drawPaint(paint); + void apply(EngineCanvas? canvas) { + canvas!.drawPaint(paint); } @override @@ -993,8 +990,8 @@ class PaintDrawVertices extends DrawCommand { PaintDrawVertices(this.vertices, this.blendMode, this.paint); @override - void apply(EngineCanvas canvas) { - canvas.drawVertices(vertices, blendMode, paint); + void apply(EngineCanvas? canvas) { + canvas!.drawVertices(vertices as SurfaceVertices, blendMode, paint); } @override @@ -1019,8 +1016,8 @@ class PaintDrawPoints extends DrawCommand { PaintDrawPoints(this.pointMode, this.points, this.paint); @override - void apply(EngineCanvas canvas) { - canvas.drawPoints(pointMode, points, paint); + void apply(EngineCanvas? canvas) { + canvas!.drawPoints(pointMode, points, paint); } @override @@ -1045,8 +1042,8 @@ class PaintDrawRect extends DrawCommand { PaintDrawRect(this.rect, this.paint); @override - void apply(EngineCanvas canvas) { - canvas.drawRect(rect, paint); + void apply(EngineCanvas? canvas) { + canvas!.drawRect(rect, paint); } @override @@ -1075,8 +1072,8 @@ class PaintDrawRRect extends DrawCommand { PaintDrawRRect(this.rrect, this.paint); @override - void apply(EngineCanvas canvas) { - canvas.drawRRect(rrect, paint); + void apply(EngineCanvas? canvas) { + canvas!.drawRRect(rrect, paint); } @override @@ -1106,8 +1103,8 @@ class PaintDrawDRRect extends DrawCommand { PaintDrawDRRect(this.outer, this.inner, this.paint); @override - void apply(EngineCanvas canvas) { - canvas.drawDRRect(outer, inner, paint); + void apply(EngineCanvas? canvas) { + canvas!.drawDRRect(outer, inner, paint); } @override @@ -1137,8 +1134,8 @@ class PaintDrawOval extends DrawCommand { PaintDrawOval(this.rect, this.paint); @override - void apply(EngineCanvas canvas) { - canvas.drawOval(rect, paint); + void apply(EngineCanvas? canvas) { + canvas!.drawOval(rect, paint); } @override @@ -1168,8 +1165,8 @@ class PaintDrawCircle extends DrawCommand { PaintDrawCircle(this.c, this.radius, this.paint); @override - void apply(EngineCanvas canvas) { - canvas.drawCircle(c, radius, paint); + void apply(EngineCanvas? canvas) { + canvas!.drawCircle(c, radius, paint); } @override @@ -1200,8 +1197,8 @@ class PaintDrawPath extends DrawCommand { PaintDrawPath(this.path, this.paint); @override - void apply(EngineCanvas canvas) { - canvas.drawPath(path, paint); + void apply(EngineCanvas? canvas) { + canvas!.drawPath(path, paint); } @override @@ -1233,8 +1230,8 @@ class PaintDrawShadow extends DrawCommand { final bool transparentOccluder; @override - void apply(EngineCanvas canvas) { - canvas.drawShadow(path, color, elevation, transparentOccluder); + void apply(EngineCanvas? canvas) { + canvas!.drawShadow(path, color, elevation, transparentOccluder); } @override @@ -1271,8 +1268,8 @@ class PaintDrawImage extends DrawCommand { PaintDrawImage(this.image, this.offset, this.paint); @override - void apply(EngineCanvas canvas) { - canvas.drawImage(image, offset, paint); + void apply(EngineCanvas? canvas) { + canvas!.drawImage(image, offset, paint); } @override @@ -1301,8 +1298,8 @@ class PaintDrawImageRect extends DrawCommand { PaintDrawImageRect(this.image, this.src, this.dst, this.paint); @override - void apply(EngineCanvas canvas) { - canvas.drawImageRect(image, src, dst, paint); + void apply(EngineCanvas? canvas) { + canvas!.drawImageRect(image, src, dst, paint); } @override @@ -1329,8 +1326,8 @@ class PaintDrawParagraph extends DrawCommand { PaintDrawParagraph(this.paragraph, this.offset); @override - void apply(EngineCanvas canvas) { - canvas.drawParagraph(paragraph, offset); + void apply(EngineCanvas? canvas) { + canvas!.drawParagraph(paragraph, offset); } @override @@ -1351,7 +1348,7 @@ class PaintDrawParagraph extends DrawCommand { } List _serializePaintToCssPaint(SurfacePaintData paint) { - final EngineGradient engineShader = paint.shader; + final EngineGradient? engineShader = paint.shader as EngineGradient?; return [ paint.blendMode?.index, paint.style?.index, @@ -1573,11 +1570,7 @@ class Ellipse extends PathCommand { anticlockwise ? startAngle - endAngle : endAngle - startAngle, matrix4, bezierPath); - if (matrix4 != null) { - targetPath._addPathWithMatrix(bezierPath, 0, 0, matrix4); - } else { - targetPath._addPath(bezierPath, 0, 0); - } + targetPath._addPathWithMatrix(bezierPath as SurfacePath, 0, 0, matrix4); } void _drawArcWithBezier( @@ -1855,11 +1848,7 @@ class RRectCommand extends PathCommand { void transform(Float32List matrix4, SurfacePath targetPath) { final ui.Path roundRectPath = ui.Path(); _RRectToPathRenderer(roundRectPath).render(rrect); - if (matrix4 != null) { - targetPath._addPathWithMatrix(roundRectPath, 0, 0, matrix4); - } else { - targetPath._addPath(roundRectPath, 0, 0); - } + targetPath._addPathWithMatrix(roundRectPath as SurfacePath, 0, 0, matrix4); } @override @@ -1908,11 +1897,15 @@ class _PaintBounds { // Bounds of actually painted area. If _left is not set, reported paintBounds // should be empty since growLTRB calls were outside active clipping // region. - double _left, _top, _right, _bottom; + double _left = double.maxFinite; + double _top = double.maxFinite; + double _right = -double.maxFinite; + double _bottom = -double.maxFinite; + // Stack of transforms. - List _transforms; + late List _transforms = []; // Stack of clip bounds. - List _clipStack; + late List _clipStack = []; bool _currentMatrixIsIdentity = true; Matrix4 _currentMatrix = Matrix4.identity(); bool _clipRectInitialized = false; @@ -1921,7 +1914,7 @@ class _PaintBounds { _currentClipRight = 0.0, _currentClipBottom = 0.0; - _PaintBounds(this.maxPaintBounds); + _PaintBounds(ui.Rect maxPaintBounds) : maxPaintBounds = maxPaintBounds; void translate(double dx, double dy) { if (dx != 0.0 || dy != 0.0) { @@ -2100,9 +2093,7 @@ class _PaintBounds { } void saveTransformsAndClip() { - _clipStack ??= []; - _transforms ??= []; - _transforms.add(_currentMatrix?.clone()); + _transforms.add(_currentMatrix.clone()); _clipStack.add(_clipRectInitialized ? ui.Rect.fromLTRB(_currentClipLeft, _currentClipTop, _currentClipRight, _currentClipBottom) @@ -2111,7 +2102,7 @@ class _PaintBounds { void restoreTransformsAndClip() { _currentMatrix = _transforms.removeLast(); - final ui.Rect clipRect = _clipStack.removeLast(); + final ui.Rect? clipRect = _clipStack.removeLast(); if (clipRect != null) { _currentClipLeft = clipRect.left; _currentClipTop = clipRect.top; @@ -2176,14 +2167,14 @@ class _PaintBounds { /// boxes for paint operations that apply the paint. double _getPaintSpread(SurfacePaint paint) { double spread = 0.0; - final ui.MaskFilter maskFilter = paint?.maskFilter; + final ui.MaskFilter? maskFilter = paint.maskFilter; if (maskFilter != null) { // Multiply by 2 because the sigma is the standard deviation rather than // the length of the blur. // See also: https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/blur spread += maskFilter.webOnlySigma * 2.0; } - if (paint.strokeWidth != null && paint.strokeWidth != 0) { + if (paint.strokeWidth != 0) { // The multiplication by sqrt(2) is to account for line joints that // meet at 90-degree angle. Division by 2 is because only half of the // stroke is sticking out of the original shape. The other half is diff --git a/lib/web_ui/lib/src/engine/surface/render_vertices.dart b/lib/web_ui/lib/src/engine/surface/render_vertices.dart index 97ae71ec78f63..22ed41083b68b 100644 --- a/lib/web_ui/lib/src/engine/surface/render_vertices.dart +++ b/lib/web_ui/lib/src/engine/surface/render_vertices.dart @@ -2,24 +2,24 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; -_GlRenderer _glRenderer; +_GlRenderer? _glRenderer; class SurfaceVertices implements ui.Vertices { final ui.VertexMode _mode; final Float32List _positions; - final Int32List/*?*/ _colors; - final Uint16List _indices; // ignore: unused_field + final Int32List? _colors; + final Uint16List? _indices; // ignore: unused_field SurfaceVertices( ui.VertexMode mode, List positions, { - List colors, - List indices, - }) : assert(mode != null), - assert(positions != null), + List? colors, + List? indices, + }) : assert(mode != null), // ignore: unnecessary_null_comparison + assert(positions != null), // ignore: unnecessary_null_comparison _mode = mode, _colors = colors != null ? _int32ListFromColors(colors) : null, _indices = indices != null ? Uint16List.fromList(indices) : null, @@ -30,10 +30,10 @@ class SurfaceVertices implements ui.Vertices { SurfaceVertices.raw( ui.VertexMode mode, Float32List positions, { - Int32List colors, - Uint16List indices, - }) : assert(mode != null), - assert(positions != null), + Int32List? colors, + Uint16List? indices, + }) : assert(mode != null), // ignore: unnecessary_null_comparison + assert(positions != null), // ignore: unnecessary_null_comparison _mode = mode, _positions = positions, _colors = colors, @@ -61,7 +61,7 @@ void disposeWebGl() { abstract class _GlRenderer { void drawVertices( - html.CanvasRenderingContext2D context, + html.CanvasRenderingContext2D? context, int canvasWidthInPixels, int canvasHeightInPixels, Matrix4 transform, @@ -69,7 +69,7 @@ abstract class _GlRenderer { ui.BlendMode blendMode, SurfacePaintData paint); - void drawHairline(html.CanvasRenderingContext2D _ctx, Float32List positions); + void drawHairline(html.CanvasRenderingContext2D? _ctx, Float32List positions); } /// Treeshakeable backend for rendering webgl on canvas. @@ -124,7 +124,7 @@ class _WebGlRenderer implements _GlRenderer { @override void drawVertices( - html.CanvasRenderingContext2D context, + html.CanvasRenderingContext2D? context, int canvasWidthInPixels, int canvasHeightInPixels, Matrix4 transform, @@ -162,59 +162,59 @@ class _WebGlRenderer implements _GlRenderer { return; } _GlContext gl = - _OffscreenCanvas.createGlContext(widthInPixels, heightInPixels); + _OffscreenCanvas.createGlContext(widthInPixels, heightInPixels)!; final bool isWebKit = (browserEngine == BrowserEngine.webkit); _GlProgram glProgram = isWebKit ? gl.useAndCacheProgram( - _vertexShaderTriangleEs1, _fragmentShaderTriangleEs1) + _vertexShaderTriangleEs1, _fragmentShaderTriangleEs1)! : gl.useAndCacheProgram( - _vertexShaderTriangle, _fragmentShaderTriangle); + _vertexShaderTriangle, _fragmentShaderTriangle)!; - Object transformUniform = gl.getUniformLocation(glProgram.program, 'u_ctransform'); + Object? transformUniform = gl.getUniformLocation(glProgram.program, 'u_ctransform'); Matrix4 transformAtOffset = transform.clone()..translate(-offsetX, -offsetY); gl.setUniformMatrix4fv(transformUniform, false, transformAtOffset.storage); // Set uniform to scale 0..width/height pixels coordinates to -1..1 // clipspace range and flip the Y axis. - Object resolution = gl.getUniformLocation(glProgram.program, 'u_scale'); + Object? resolution = gl.getUniformLocation(glProgram.program, 'u_scale'); gl.setUniform4f(resolution, 2.0 / widthInPixels.toDouble(), -2.0 / heightInPixels.toDouble(), 1, 1); - Object shift = gl.getUniformLocation(glProgram.program, 'u_shift'); + Object? shift = gl.getUniformLocation(glProgram.program, 'u_shift'); gl.setUniform4f(shift, -1, 1, 0, 0); // Setup geometry. - Object positionsBuffer = gl.createBuffer(); - assert(positionsBuffer != null); + Object positionsBuffer = gl.createBuffer()!; + assert(positionsBuffer != null); // ignore: unnecessary_null_comparison gl.bindArrayBuffer(positionsBuffer); gl.bufferData(positions, gl.kStaticDraw); js_util.callMethod( - gl.glContext, 'vertexAttribPointer', [0, 2, gl.kFloat, false, 0, 0]); + gl.glContext!, 'vertexAttribPointer', [0, 2, gl.kFloat, false, 0, 0]); gl.enableVertexAttribArray(0); // Setup color buffer. - Object colorsBuffer = gl.createBuffer(); + Object? colorsBuffer = gl.createBuffer(); gl.bindArrayBuffer(colorsBuffer); // Buffer kBGRA_8888. gl.bufferData(vertices._colors, gl.kStaticDraw); - js_util.callMethod(gl.glContext, 'vertexAttribPointer', + js_util.callMethod(gl.glContext!, 'vertexAttribPointer', [1, 4, gl.kUnsignedByte, true, 0, 0]); gl.enableVertexAttribArray(1); gl.clear(); final int vertexCount = positions.length ~/ 2; gl.drawTriangles(vertexCount, vertices._mode); - context.save(); + context!.save(); context.resetTransform(); gl.drawImage(context, offsetX, offsetY); context.restore(); } @override - void drawHairline(html.CanvasRenderingContext2D _ctx, Float32List positions) { - assert(positions != null); + void drawHairline(html.CanvasRenderingContext2D? _ctx, Float32List positions) { + assert(positions != null); // ignore: unnecessary_null_comparison final int pointCount = positions.length ~/ 2; - _ctx.lineWidth = 1.0; + _ctx!.lineWidth = 1.0; _ctx.beginPath(); for (int i = 0, len = pointCount * 2; i < len;) { for (int triangleVertexIndex = 0; @@ -337,13 +337,13 @@ Float32List _convertVertexPositions(ui.VertexMode mode, Float32List positions) { /// Compiled and cached gl program. class _GlProgram { - final Object program; + final Object? program; _GlProgram(this.program); } /// JS Interop helper for webgl apis. class _GlContext { - final Object glContext; + final Object? glContext; final bool isOffscreen; dynamic _kCompileStatus; dynamic _kArrayBuffer; @@ -354,15 +354,15 @@ class _GlContext { dynamic _kLinkStatus; dynamic _kUnsignedByte; dynamic _kRGBA; - Object _canvas; - int _widthInPixels; - int _heightInPixels; - static Map _programCache; + Object? _canvas; + int? _widthInPixels; + int? _heightInPixels; + static late Map _programCache; _GlContext.fromOffscreenCanvas(html.OffscreenCanvas canvas) : glContext = canvas.getContext('webgl2', {'premultipliedAlpha': false}), isOffscreen = true { - _programCache = {}; + _programCache = {}; _canvas = canvas; } @@ -370,7 +370,7 @@ class _GlContext { : glContext = canvas.getContext(useWebGl1 ? 'webgl' : 'webgl2', {'premultipliedAlpha': false}), isOffscreen = false { - _programCache = {}; + _programCache = {}; _canvas = canvas; } @@ -389,17 +389,17 @@ class _GlContext { left, top, _widthInPixels, _heightInPixels]); } - _GlProgram useAndCacheProgram( + _GlProgram? useAndCacheProgram( String vertexShaderSource, String fragmentShaderSource) { String cacheKey = '$vertexShaderSource||$fragmentShaderSource'; - _GlProgram cachedProgram = _programCache[cacheKey]; + _GlProgram? cachedProgram = _programCache[cacheKey]; if (cachedProgram == null) { // Create and compile shaders. Object vertexShader = compileShader('VERTEX_SHADER', vertexShaderSource); Object fragmentShader = compileShader('FRAGMENT_SHADER', fragmentShaderSource); // Create a gl program and link shaders. - Object program = createProgram(); + Object? program = createProgram(); attachShader(program, vertexShader); attachShader(program, fragmentShader); linkProgram(program); @@ -411,61 +411,61 @@ class _GlContext { } Object compileShader(String shaderType, String source) { - Object shader = _createShader(shaderType); + Object? shader = _createShader(shaderType); if (shader == null) { throw Exception(error); } - js_util.callMethod(glContext, 'shaderSource', [shader, source]); - js_util.callMethod(glContext, 'compileShader', [shader]); + js_util.callMethod(glContext!, 'shaderSource', [shader, source]); + js_util.callMethod(glContext!, 'compileShader', [shader]); bool shaderStatus = js_util - .callMethod(glContext, 'getShaderParameter', [shader, compileStatus]); + .callMethod(glContext!, 'getShaderParameter', [shader, compileStatus]); if (!shaderStatus) { throw Exception('Shader compilation failed: ${getShaderInfoLog(shader)}'); } return shader; } - Object createProgram() => - js_util.callMethod(glContext, 'createProgram', const []); + Object? createProgram() => + js_util.callMethod(glContext!, 'createProgram', const []); - void attachShader(Object program, Object shader) { - js_util.callMethod(glContext, 'attachShader', [program, shader]); + void attachShader(Object? program, Object shader) { + js_util.callMethod(glContext!, 'attachShader', [program, shader]); } - void linkProgram(Object program) { - js_util.callMethod(glContext, 'linkProgram', [program]); + void linkProgram(Object? program) { + js_util.callMethod(glContext!, 'linkProgram', [program]); if (!js_util - .callMethod(glContext, 'getProgramParameter', [program, kLinkStatus])) { + .callMethod(glContext!, 'getProgramParameter', [program, kLinkStatus])) { throw Exception(getProgramInfoLog(program)); } } - void useProgram(Object program) { - js_util.callMethod(glContext, 'useProgram', [program]); + void useProgram(Object? program) { + js_util.callMethod(glContext!, 'useProgram', [program]); } - Object createBuffer() => - js_util.callMethod(glContext, 'createBuffer', const []); + Object? createBuffer() => + js_util.callMethod(glContext!, 'createBuffer', const []); - void bindArrayBuffer(Object buffer) { - js_util.callMethod(glContext, 'bindBuffer', [kArrayBuffer, buffer]); + void bindArrayBuffer(Object? buffer) { + js_util.callMethod(glContext!, 'bindBuffer', [kArrayBuffer, buffer]); } void deleteBuffer(Object buffer) { - js_util.callMethod(glContext, 'deleteBuffer', [buffer]); + js_util.callMethod(glContext!, 'deleteBuffer', [buffer]); } - void bufferData(TypedData data, dynamic type) { - js_util.callMethod(glContext, 'bufferData', [kArrayBuffer, data, type]); + void bufferData(TypedData? data, dynamic type) { + js_util.callMethod(glContext!, 'bufferData', [kArrayBuffer, data, type]); } void enableVertexAttribArray(int index) { - js_util.callMethod(glContext, 'enableVertexAttribArray', [index]); + js_util.callMethod(glContext!, 'enableVertexAttribArray', [index]); } /// Clear background. void clear() { - js_util.callMethod(glContext, 'clear', [kColorBufferBit]); + js_util.callMethod(glContext!, 'clear', [kColorBufferBit]); } /// Destroys gl context. @@ -474,25 +474,25 @@ class _GlContext { } void deleteProgram(Object program) { - js_util.callMethod(glContext, 'deleteProgram', [program]); + js_util.callMethod(glContext!, 'deleteProgram', [program]); } void deleteShader(Object shader) { - js_util.callMethod(glContext, 'deleteShader', [shader]); + js_util.callMethod(glContext!, 'deleteShader', [shader]); } dynamic _getExtension(String extensionName) => - js_util.callMethod(glContext, 'getExtension', [extensionName]); + js_util.callMethod(glContext!, 'getExtension', [extensionName]); void drawTriangles(int triangleCount, ui.VertexMode vertexMode) { dynamic mode = _triangleTypeFromMode(vertexMode); - js_util.callMethod(glContext, 'drawArrays', [mode, 0, triangleCount]); + js_util.callMethod(glContext!, 'drawArrays', [mode, 0, triangleCount]); } /// Sets affine transformation from normalized device coordinates /// to window coordinates void viewport(double x, double y, double width, double height) { - js_util.callMethod(glContext, 'viewport', [x, y, width, height]); + js_util.callMethod(glContext!, 'viewport', [x, y, width, height]); } dynamic _triangleTypeFromMode(ui.VertexMode mode) { @@ -509,105 +509,105 @@ class _GlContext { } } - Object _createShader(String shaderType) => js_util.callMethod( - glContext, 'createShader', [js_util.getProperty(glContext, shaderType)]); + Object? _createShader(String shaderType) => js_util.callMethod( + glContext!, 'createShader', [js_util.getProperty(glContext!, shaderType)]); /// Error state of gl context. - dynamic get error => js_util.callMethod(glContext, 'getError', const []); + dynamic get error => js_util.callMethod(glContext!, 'getError', const []); /// Shader compiler error, if this returns [kFalse], to get details use /// [getShaderInfoLog]. dynamic get compileStatus => - _kCompileStatus ??= js_util.getProperty(glContext, 'COMPILE_STATUS'); + _kCompileStatus ??= js_util.getProperty(glContext!, 'COMPILE_STATUS'); dynamic get kArrayBuffer => - _kArrayBuffer ??= js_util.getProperty(glContext, 'ARRAY_BUFFER'); + _kArrayBuffer ??= js_util.getProperty(glContext!, 'ARRAY_BUFFER'); dynamic get kLinkStatus => - _kLinkStatus ??= js_util.getProperty(glContext, 'LINK_STATUS'); + _kLinkStatus ??= js_util.getProperty(glContext!, 'LINK_STATUS'); - dynamic get kFloat => _kFloat ??= js_util.getProperty(glContext, 'FLOAT'); + dynamic get kFloat => _kFloat ??= js_util.getProperty(glContext!, 'FLOAT'); - dynamic get kRGBA => _kRGBA ??= js_util.getProperty(glContext, 'RGBA'); + dynamic get kRGBA => _kRGBA ??= js_util.getProperty(glContext!, 'RGBA'); dynamic get kUnsignedByte => - _kUnsignedByte ??= js_util.getProperty(glContext, 'UNSIGNED_BYTE'); + _kUnsignedByte ??= js_util.getProperty(glContext!, 'UNSIGNED_BYTE'); dynamic get kStaticDraw => - _kStaticDraw ??= js_util.getProperty(glContext, 'STATIC_DRAW'); + _kStaticDraw ??= js_util.getProperty(glContext!, 'STATIC_DRAW'); dynamic get kTriangles => - _kTriangles ??= js_util.getProperty(glContext, 'TRIANGLES'); + _kTriangles ??= js_util.getProperty(glContext!, 'TRIANGLES'); dynamic get kTriangleFan => - _kTriangles ??= js_util.getProperty(glContext, 'TRIANGLE_FAN'); + _kTriangles ??= js_util.getProperty(glContext!, 'TRIANGLE_FAN'); dynamic get kTriangleStrip => - _kTriangles ??= js_util.getProperty(glContext, 'TRIANGLE_STRIP'); + _kTriangles ??= js_util.getProperty(glContext!, 'TRIANGLE_STRIP'); dynamic get kColorBufferBit => - _kColorBufferBit ??= js_util.getProperty(glContext, 'COLOR_BUFFER_BIT'); + _kColorBufferBit ??= js_util.getProperty(glContext!, 'COLOR_BUFFER_BIT'); /// Returns reference to uniform in program. - Object getUniformLocation(Object program, String uniformName) { + Object? getUniformLocation(Object? program, String uniformName) { return js_util - .callMethod(glContext, 'getUniformLocation', [program, uniformName]); + .callMethod(glContext!, 'getUniformLocation', [program, uniformName]); } /// Sets vec2 uniform values. void setUniform2f(Object uniform, double value1, double value2) { return js_util - .callMethod(glContext, 'uniform2f', [uniform, value1, value2]); + .callMethod(glContext!, 'uniform2f', [uniform, value1, value2]); } /// Sets vec4 uniform values. - void setUniform4f(Object uniform, double value1, double value2, double value3, + void setUniform4f(Object? uniform, double value1, double value2, double value3, double value4) { return js_util.callMethod( - glContext, 'uniform4f', [uniform, value1, value2, value3, value4]); + glContext!, 'uniform4f', [uniform, value1, value2, value3, value4]); } /// Sets mat4 uniform values. - void setUniformMatrix4fv(Object uniform, bool transpose, Float32List value) { + void setUniformMatrix4fv(Object? uniform, bool transpose, Float32List? value) { return js_util.callMethod( - glContext, 'uniformMatrix4fv', [uniform, transpose, value]); + glContext!, 'uniformMatrix4fv', [uniform, transpose, value]); } /// Shader compile error log. dynamic getShaderInfoLog(Object glShader) { - return js_util.callMethod(glContext, 'getShaderInfoLog', [glShader]); + return js_util.callMethod(glContext!, 'getShaderInfoLog', [glShader]); } /// Errors that occurred during failed linking or validation of program /// objects. Typically called after [linkProgram]. - String getProgramInfoLog(Object glProgram) { - return js_util.callMethod(glContext, 'getProgramInfoLog', [glProgram]); + String? getProgramInfoLog(Object? glProgram) { + return js_util.callMethod(glContext!, 'getProgramInfoLog', [glProgram]); } - int get drawingBufferWidth => - js_util.getProperty(glContext, 'drawingBufferWidth'); - int get drawingBufferHeight => - js_util.getProperty(glContext, 'drawingBufferWidth'); + int? get drawingBufferWidth => + js_util.getProperty(glContext!, 'drawingBufferWidth'); + int? get drawingBufferHeight => + js_util.getProperty(glContext!, 'drawingBufferWidth'); html.ImageData readImageData() { if (browserEngine == BrowserEngine.webkit || browserEngine == BrowserEngine.firefox) { const int kBytesPerPixel = 4; - final int bufferWidth = _widthInPixels; - final int bufferHeight = _heightInPixels; + final int bufferWidth = _widthInPixels!; + final int bufferHeight = _heightInPixels!; final Uint8List pixels = Uint8List(bufferWidth * bufferHeight * kBytesPerPixel); - js_util.callMethod(glContext, 'readPixels', + js_util.callMethod(glContext!, 'readPixels', [0, 0, bufferWidth, bufferHeight, kRGBA, kUnsignedByte, pixels]); return html.ImageData( Uint8ClampedList.fromList(pixels), bufferWidth, bufferHeight); } else { const int kBytesPerPixel = 4; - final int bufferWidth = _widthInPixels; - final int bufferHeight = _heightInPixels; + final int bufferWidth = _widthInPixels!; + final int bufferHeight = _heightInPixels!; final Uint8ClampedList pixels = Uint8ClampedList(bufferWidth * bufferHeight * kBytesPerPixel); - js_util.callMethod(glContext, 'readPixels', + js_util.callMethod(glContext!, 'readPixels', [0, 0, bufferWidth, bufferHeight, kRGBA, kUnsignedByte, pixels]); return html.ImageData(pixels, bufferWidth, bufferHeight); } @@ -616,11 +616,11 @@ class _GlContext { /// Shared Cached OffscreenCanvas for webgl rendering to image. class _OffscreenCanvas { - static html.OffscreenCanvas _canvas; + static html.OffscreenCanvas? _canvas; static int _maxPixelWidth = 0; static int _maxPixelHeight = 0; - static html.CanvasElement _glCanvas; - static _GlContext _cachedContext; + static html.CanvasElement? _glCanvas; + static _GlContext? _cachedContext; _OffscreenCanvas(int width, int height) { assert(width > 0 && height > 0); @@ -642,16 +642,16 @@ class _OffscreenCanvas { _cachedContext = null; } - html.OffscreenCanvas get canvas => _canvas; + html.OffscreenCanvas? get canvas => _canvas; - static _GlContext createGlContext(int widthInPixels, int heightInPixels) { + static _GlContext? createGlContext(int widthInPixels, int heightInPixels) { final bool isWebKit = (browserEngine == BrowserEngine.webkit); if (_OffscreenCanvas.supported) { final _OffscreenCanvas offScreenCanvas = _OffscreenCanvas(widthInPixels, heightInPixels); - _cachedContext ??= _GlContext.fromOffscreenCanvas(offScreenCanvas.canvas); - _cachedContext.setViewportSize(widthInPixels, heightInPixels); + _cachedContext ??= _GlContext.fromOffscreenCanvas(offScreenCanvas.canvas!); + _cachedContext!.setViewportSize(widthInPixels, heightInPixels); return _cachedContext; } else { // Allocate new canvas element is size is larger. @@ -660,10 +660,10 @@ class _OffscreenCanvas { width: widthInPixels, height: heightInPixels, ); - _glCanvas.className = 'gl-canvas'; + _glCanvas!.className = 'gl-canvas'; final double cssWidth = widthInPixels / EngineWindow.browserDevicePixelRatio; final double cssHeight = heightInPixels / EngineWindow.browserDevicePixelRatio; - _glCanvas.style + _glCanvas!.style ..position = 'absolute' ..width = '${cssWidth}px' ..height = '${cssHeight}px'; @@ -672,8 +672,8 @@ class _OffscreenCanvas { _cachedContext?.dispose(); _cachedContext = null; } - _cachedContext ??= _GlContext.fromCanvas(_glCanvas, isWebKit); - _cachedContext.setViewportSize(widthInPixels, heightInPixels); + _cachedContext ??= _GlContext.fromCanvas(_glCanvas!, isWebKit); + _cachedContext!.setViewportSize(widthInPixels, heightInPixels); return _cachedContext; } } diff --git a/lib/web_ui/lib/src/engine/surface/scene.dart b/lib/web_ui/lib/src/engine/surface/scene.dart index 832b3fd9eb68c..f1c6afcbb98ef 100644 --- a/lib/web_ui/lib/src/engine/surface/scene.dart +++ b/lib/web_ui/lib/src/engine/surface/scene.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; class SurfaceScene implements ui.Scene { @@ -12,7 +12,7 @@ class SurfaceScene implements ui.Scene { /// To create a Scene object, use a [SceneBuilder]. SurfaceScene(this.webOnlyRootElement); - final html.Element webOnlyRootElement; + final html.Element? webOnlyRootElement; /// Creates a raster image representation of the current state of the scene. /// This is a slow operation that is performed on a background thread. @@ -28,7 +28,7 @@ class SurfaceScene implements ui.Scene { /// A surface that creates a DOM element for whole app. class PersistedScene extends PersistedContainerSurface { - PersistedScene(PersistedScene oldLayer) : super(oldLayer) { + PersistedScene(PersistedScene? oldLayer) : super(oldLayer) { _transform = Matrix4.identity(); } @@ -46,7 +46,7 @@ class PersistedScene extends PersistedContainerSurface { } @override - Matrix4 get localTransformInverse => _localTransformInverse; + Matrix4? get localTransformInverse => _localTransformInverse; @override html.Element createElement() { diff --git a/lib/web_ui/lib/src/engine/surface/scene_builder.dart b/lib/web_ui/lib/src/engine/surface/scene_builder.dart index 4a6ebaced0f72..d08d9ca07d79a 100644 --- a/lib/web_ui/lib/src/engine/surface/scene_builder.dart +++ b/lib/web_ui/lib/src/engine/surface/scene_builder.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; class SurfaceSceneBuilder implements ui.SceneBuilder { @@ -17,7 +17,7 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { /// /// This getter should only be called after all surfaces are built. PersistedScene get _persistedScene { - return _surfaceStack.first; + return _surfaceStack.first as PersistedScene; } /// The surface currently being built. @@ -27,10 +27,10 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { // Only attempt to update if the update is requested and the surface is in // the live tree. if (surface.oldLayer != null) { - assert(surface.oldLayer.runtimeType == surface.runtimeType); + assert(surface.oldLayer!.runtimeType == surface.runtimeType); assert(debugAssertSurfaceState( - surface.oldLayer, PersistedSurfaceState.active)); - surface.oldLayer.state = PersistedSurfaceState.pendingUpdate; + surface.oldLayer!, PersistedSurfaceState.active)); + surface.oldLayer!.state = PersistedSurfaceState.pendingUpdate; } _adoptSurface(surface); _surfaceStack.add(surface); @@ -63,9 +63,9 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { ui.OffsetEngineLayer pushOffset( double dx, double dy, { - ui.OffsetEngineLayer oldLayer, + ui.OffsetEngineLayer? oldLayer, }) { - return _pushSurface(PersistedOffset(oldLayer, dx, dy)); + return _pushSurface(PersistedOffset(oldLayer as PersistedOffset?, dx, dy)) as ui.OffsetEngineLayer; } /// Pushes a transform operation onto the operation stack. @@ -76,9 +76,9 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { @override ui.TransformEngineLayer pushTransform( Float64List matrix4, { - ui.TransformEngineLayer oldLayer, + ui.TransformEngineLayer? oldLayer, }) { - if (matrix4 == null) { + if (matrix4 == null) { // ignore: unnecessary_null_comparison throw ArgumentError('"matrix4" argument cannot be null'); } if (matrix4.length != 16) { @@ -86,7 +86,7 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { } // TODO(yjbanov): make this final after NNBD ships definite assignment. - /*final*/ Float32List matrix; + /*final*/ Float32List? matrix; if (_surfaceStack.length == 1) { // Top level transform contains view configuration to scale // scene to devicepixelratio. Use identity instead since CSS uses @@ -99,7 +99,7 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { } else { matrix = toMatrix32(matrix4); } - return _pushSurface(PersistedTransform(oldLayer, matrix)); + return _pushSurface(PersistedTransform(oldLayer as PersistedTransform?, matrix)) as ui.TransformEngineLayer; } /// Pushes a rectangular clip operation onto the operation stack. @@ -112,11 +112,11 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { ui.ClipRectEngineLayer pushClipRect( ui.Rect rect, { ui.Clip clipBehavior = ui.Clip.antiAlias, - ui.ClipRectEngineLayer oldLayer, + ui.ClipRectEngineLayer? oldLayer, }) { - assert(clipBehavior != null); + assert(clipBehavior != null); // ignore: unnecessary_null_comparison assert(clipBehavior != ui.Clip.none); - return _pushSurface(PersistedClipRect(oldLayer, rect)); + return _pushSurface(PersistedClipRect(oldLayer as PersistedClipRect?, rect)) as ui.ClipRectEngineLayer; } /// Pushes a rounded-rectangular clip operation onto the operation stack. @@ -127,10 +127,10 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { @override ui.ClipRRectEngineLayer pushClipRRect( ui.RRect rrect, { - ui.Clip clipBehavior, - ui.ClipRRectEngineLayer oldLayer, + ui.Clip? clipBehavior, + ui.ClipRRectEngineLayer? oldLayer, }) { - return _pushSurface(PersistedClipRRect(oldLayer, rrect, clipBehavior)); + return _pushSurface(PersistedClipRRect(oldLayer, rrect, clipBehavior)) as ui.ClipRRectEngineLayer; } /// Pushes a path clip operation onto the operation stack. @@ -142,11 +142,11 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { ui.ClipPathEngineLayer pushClipPath( ui.Path path, { ui.Clip clipBehavior = ui.Clip.antiAlias, - ui.ClipPathEngineLayer oldLayer, + ui.ClipPathEngineLayer? oldLayer, }) { - assert(clipBehavior != null); + assert(clipBehavior != null); // ignore: unnecessary_null_comparison assert(clipBehavior != ui.Clip.none); - return _pushSurface(PersistedClipPath(oldLayer, path, clipBehavior)); + return _pushSurface(PersistedClipPath(oldLayer as PersistedClipPath?, path, clipBehavior)) as ui.ClipPathEngineLayer; } /// Pushes an opacity operation onto the operation stack. @@ -161,9 +161,9 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { ui.OpacityEngineLayer pushOpacity( int alpha, { ui.Offset offset = ui.Offset.zero, - ui.OpacityEngineLayer oldLayer, + ui.OpacityEngineLayer? oldLayer, }) { - return _pushSurface(PersistedOpacity(oldLayer, alpha, offset)); + return _pushSurface(PersistedOpacity(oldLayer as PersistedOpacity?, alpha, offset)) as ui.OpacityEngineLayer; } /// Pushes a color filter operation onto the operation stack. @@ -179,9 +179,9 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { @override ui.ColorFilterEngineLayer pushColorFilter( ui.ColorFilter filter, { - ui.ColorFilterEngineLayer oldLayer, + ui.ColorFilterEngineLayer? oldLayer, }) { - assert(filter != null); + assert(filter != null); // ignore: unnecessary_null_comparison throw UnimplementedError(); } @@ -198,10 +198,10 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { @override ui.ImageFilterEngineLayer pushImageFilter( ui.ImageFilter filter, { - ui.ImageFilterEngineLayer oldLayer, + ui.ImageFilterEngineLayer? oldLayer, }) { - assert(filter != null); - return _pushSurface(PersistedImageFilter(oldLayer, filter)); + assert(filter != null); // ignore: unnecessary_null_comparison + return _pushSurface(PersistedImageFilter(oldLayer as PersistedImageFilter?, filter)) as ui.ImageFilterEngineLayer; } /// Pushes a backdrop filter operation onto the operation stack. @@ -213,9 +213,9 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { @override ui.BackdropFilterEngineLayer pushBackdropFilter( ui.ImageFilter filter, { - ui.BackdropFilterEngineLayer oldLayer, + ui.BackdropFilterEngineLayer? oldLayer, }) { - return _pushSurface(PersistedBackdropFilter(oldLayer, filter)); + return _pushSurface(PersistedBackdropFilter(oldLayer as PersistedBackdropFilter?, filter as EngineImageFilter)) as ui.BackdropFilterEngineLayer; } /// Pushes a shader mask operation onto the operation stack. @@ -229,7 +229,7 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { ui.Shader shader, ui.Rect maskRect, ui.BlendMode blendMode, { - ui.ShaderMaskEngineLayer oldLayer, + ui.ShaderMaskEngineLayer? oldLayer, }) { throw UnimplementedError(); } @@ -248,22 +248,22 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { /// See [pop] for details about the operation stack, and [Clip] for different clip modes. @override ui.PhysicalShapeEngineLayer pushPhysicalShape({ - ui.Path path, - double elevation, - ui.Color color, - ui.Color shadowColor, + required ui.Path path, + required double elevation, + required ui.Color color, + ui.Color? shadowColor, ui.Clip clipBehavior = ui.Clip.none, - ui.PhysicalShapeEngineLayer oldLayer, + ui.PhysicalShapeEngineLayer? oldLayer, }) { - assert(color != null, 'color must not be null'); + assert(color != null, 'color must not be null'); // ignore: unnecessary_null_comparison return _pushSurface(PersistedPhysicalShape( - oldLayer, - path, + oldLayer as PersistedPhysicalShape?, + path as SurfacePath, elevation, color.value, shadowColor?.value ?? 0xFF000000, clipBehavior, - )); + )) as ui.PhysicalShapeEngineLayer; } /// Add a retained engine layer subtree from previous frames. @@ -276,7 +276,7 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { /// no need to call [addToScene] for its children layers. @override void addRetained(ui.EngineLayer retainedLayer) { - final PersistedContainerSurface retainedSurface = retainedLayer; + final PersistedContainerSurface retainedSurface = retainedLayer as PersistedContainerSurface; if (assertionsEnabled) { assert(debugAssertSurfaceState(retainedSurface, PersistedSurfaceState.active, PersistedSurfaceState.released)); @@ -379,7 +379,7 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { bool freeze = false, ui.FilterQuality filterQuality = ui.FilterQuality.low, }) { - assert(offset != null, 'Offset argument was null'); + assert(offset != null, 'Offset argument was null'); // ignore: unnecessary_null_comparison _addTexture(offset.dx, offset.dy, width, height, textureId, filterQuality.index); } @@ -414,7 +414,7 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { double width = 0.0, double height = 0.0, }) { - assert(offset != null, 'Offset argument was null'); + assert(offset != null, 'Offset argument was null'); // ignore: unnecessary_null_comparison _addPlatformView(offset.dx, offset.dy, width, height, viewId); } @@ -435,7 +435,7 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { ui.Offset offset = ui.Offset.zero, double width = 0.0, double height = 0.0, - ui.SceneHost sceneHost, + ui.SceneHost? sceneHost, bool hitTestable = true, }) { _addChildScene(offset.dx, offset.dy, width, height, sceneHost, hitTestable); @@ -446,7 +446,7 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { double dy, double width, double height, - ui.SceneHost sceneHost, + ui.SceneHost? sceneHost, bool hitTestable, ) { throw UnimplementedError(); @@ -492,14 +492,14 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { /// /// This is a surface tree that holds onto the DOM elements that can be reused /// on the next frame. - static PersistedScene _lastFrameScene; + static PersistedScene? _lastFrameScene; /// Returns the computed persisted scene graph recorded in the last frame. /// /// This is only available in debug mode. It returns `null` in profile and /// release modes. - static PersistedScene get debugLastFrameScene { - PersistedScene result; + static PersistedScene? get debugLastFrameScene { + PersistedScene? result; assert(() { result = _lastFrameScene; return true; @@ -542,7 +542,7 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { if (_lastFrameScene == null) { _persistedScene.build(); } else { - _persistedScene.update(_lastFrameScene); + _persistedScene.update(_lastFrameScene!); } commitScene(_persistedScene); _lastFrameScene = _persistedScene; diff --git a/lib/web_ui/lib/src/engine/surface/surface.dart b/lib/web_ui/lib/src/engine/surface/surface.dart index dce4664e3d64b..0562f6e00ce98 100644 --- a/lib/web_ui/lib/src/engine/surface/surface.dart +++ b/lib/web_ui/lib/src/engine/surface/surface.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// When `true` prints statistics about what happened to the surface tree when @@ -165,8 +165,8 @@ class PersistedSurfaceException implements Exception { /// This function should be used inside an assertion expression. bool debugAssertSurfaceState( PersistedSurface surface, PersistedSurfaceState state1, - [PersistedSurfaceState state2, PersistedSurfaceState state3]) { - final List validStates = [state1, state2, state3]; + [PersistedSurfaceState? state2, PersistedSurfaceState? state3]) { + final List validStates = [state1, state2, state3]; if (validStates.contains(surface.state)) { return true; @@ -184,7 +184,7 @@ bool debugAssertSurfaceState( /// compute the fewest amount of mutations necessary to update the browser DOM. abstract class PersistedSurface implements ui.EngineLayer { /// Creates a persisted surface. - PersistedSurface(PersistedSurface oldLayer) + PersistedSurface(PersistedSurface? oldLayer) : _oldLayer = FrameReference( oldLayer != null && oldLayer.isActive ? oldLayer : null); @@ -193,7 +193,7 @@ abstract class PersistedSurface implements ui.EngineLayer { /// If not null this surface will reuse the old surface's HTML [element]. /// /// This value is set to null at the end of the frame. - PersistedSurface get oldLayer => _oldLayer.value; + PersistedSurface? get oldLayer => _oldLayer.value; final FrameReference _oldLayer; /// The index of this surface in its parent's [PersistedContainerSurface._children] @@ -210,7 +210,7 @@ abstract class PersistedSurface implements ui.EngineLayer { /// surface. PersistedSurfaceState get state => _state; set state(PersistedSurfaceState newState) { - assert(newState != null); + assert(newState != null); // ignore: unnecessary_null_comparison assert(newState != _state, 'Attempted to set state that the surface is already in. This likely indicates a bug in the compositor.'); assert(_debugValidateStateTransition(newState)); @@ -301,7 +301,7 @@ abstract class PersistedSurface implements ui.EngineLayer { /// /// This element can be reused across frames. See also, [childContainer], /// which is the element used to manage child nodes. - html.Element rootElement; + html.Element? rootElement; /// Whether this surface can update an existing [oldSurface]. bool canUpdateAsMatch(PersistedSurface oldSurface) { @@ -313,10 +313,10 @@ abstract class PersistedSurface implements ui.EngineLayer { /// By default this is the same as the [rootElement]. However, specialized /// surface implementations may choose to override this and provide a /// different element for nesting children. - html.Element get childContainer => rootElement; + html.Element? get childContainer => rootElement; /// This surface's immediate parent. - PersistedContainerSurface parent; + PersistedContainerSurface? parent; /// Visits immediate children. /// @@ -336,7 +336,7 @@ abstract class PersistedSurface implements ui.EngineLayer { /// compared to higher scores. For example, when matching a picture with a /// bitmap canvas the score is higher for a canvas that's bigger in size than /// a smaller canvas that also fits the picture. - double matchForUpdate(covariant PersistedSurface existingSurface); + double matchForUpdate(covariant PersistedSurface? existingSurface); /// Creates a new element and sets the necessary HTML and CSS attributes. /// @@ -347,10 +347,10 @@ abstract class PersistedSurface implements ui.EngineLayer { void build() { if (rootElement != null) { try { - throw null; + throw ''; } catch (_, stack) { print( - 'Attempted to build a $runtimeType, but it already has an HTML element ${rootElement.tagName}.'); + 'Attempted to build a $runtimeType, but it already has an HTML element ${rootElement!.tagName}.'); print(stack.toString().split('\n').take(20).join('\n')); } } @@ -379,7 +379,7 @@ abstract class PersistedSurface implements ui.EngineLayer { PersistedSurfaceState.pendingUpdate)); assert(() { if (oldSurface.isPendingUpdate) { - final PersistedContainerSurface self = this; + final PersistedContainerSurface self = this as PersistedContainerSurface; assert(identical(self.oldLayer, oldSurface)); } return true; @@ -402,7 +402,7 @@ abstract class PersistedSurface implements ui.EngineLayer { @protected @mustCallSuper void update(covariant PersistedSurface oldSurface) { - assert(oldSurface != null); + assert(oldSurface != null); // ignore: unnecessary_null_comparison assert(!identical(oldSurface, this)); assert(debugAssertSurfaceState(this, PersistedSurfaceState.created)); assert(debugAssertSurfaceState(oldSurface, PersistedSurfaceState.active, @@ -411,7 +411,7 @@ abstract class PersistedSurface implements ui.EngineLayer { adoptElements(oldSurface); if (assertionsEnabled) { - rootElement.setAttribute('flt-layer-state', 'updated'); + rootElement!.setAttribute('flt-layer-state', 'updated'); } state = PersistedSurfaceState.active; assert(rootElement != null); @@ -436,7 +436,7 @@ abstract class PersistedSurface implements ui.EngineLayer { _retainedSurfaces.add(this); } if (assertionsEnabled) { - rootElement.setAttribute('flt-layer-state', 'retained'); + rootElement!.setAttribute('flt-layer-state', 'retained'); } if (_debugExplainSurfaceStats) { _surfaceStatsFor(this).retainSurfaceCount++; @@ -466,7 +466,7 @@ abstract class PersistedSurface implements ui.EngineLayer { // the DOM, and the second method will disassociate the // surface from the DOM and release it irrespective of // whether the DOM itself gets detached or not. - rootElement.remove(); + rootElement!.remove(); rootElement = null; state = PersistedSurfaceState.released; } @@ -510,8 +510,8 @@ abstract class PersistedSurface implements ui.EngineLayer { /// transforms as well as this layer's transform (if any). /// /// The value is update by [recomputeTransformAndClip]. - Matrix4 get transform => _transform; - Matrix4 _transform; + Matrix4? get transform => _transform; + Matrix4? _transform; /// The intersection at this surface level. /// @@ -519,19 +519,19 @@ abstract class PersistedSurface implements ui.EngineLayer { /// the clip added by this layer (if any). /// /// The value is update by [recomputeTransformAndClip]. - ui.Rect _projectedClip; + ui.Rect? _projectedClip; /// Bounds of clipping performed by this layer. - ui.Rect _localClipBounds; + ui.Rect? _localClipBounds; // Cached inverse of transform on this node. Unlike transform, this // Matrix only contains local transform (not chain multiplied since root). - Matrix4 _localTransformInverse; + Matrix4? _localTransformInverse; /// The inverse of the local transform that this surface applies to its children. /// /// The default implementation is identity transform. Concrete /// implementations may override this getter to supply a different transform. - Matrix4 get localTransformInverse => + Matrix4? get localTransformInverse => _localTransformInverse ??= Matrix4.identity(); /// Recomputes [transform] and [globalClip] fields. @@ -543,7 +543,7 @@ abstract class PersistedSurface implements ui.EngineLayer { /// This method is called by the [preroll] method. @protected void recomputeTransformAndClip() { - _transform = parent._transform; + _transform = parent!._transform; _localClipBounds = null; _localTransformInverse = null; _projectedClip = null; @@ -564,7 +564,7 @@ abstract class PersistedSurface implements ui.EngineLayer { /// Prints this surface into a [buffer] in a human-readable format. void debugPrint(StringBuffer buffer, int indent) { if (rootElement != null) { - buffer.write('${' ' * indent}<${rootElement.tagName.toLowerCase()} '); + buffer.write('${' ' * indent}<${rootElement!.tagName.toLowerCase()} '); } else { buffer.write('${' ' * indent}<$runtimeType recycled '); } @@ -572,7 +572,7 @@ abstract class PersistedSurface implements ui.EngineLayer { buffer.writeln('>'); debugPrintChildren(buffer, indent); if (rootElement != null) { - buffer.writeln('${' ' * indent}'); + buffer.writeln('${' ' * indent}'); } else { buffer.writeln('${' ' * indent}'); } @@ -582,7 +582,7 @@ abstract class PersistedSurface implements ui.EngineLayer { @mustCallSuper void debugPrintAttributes(StringBuffer buffer) { if (rootElement != null) { - buffer.write('@${rootElement.hashCode} '); + buffer.write('@${rootElement!.hashCode} '); } } @@ -618,7 +618,7 @@ abstract class PersistedContainerSurface extends PersistedSurface { /// /// `oldLayer` points to the surface rendered in the previous frame that's /// being updated by this layer. - PersistedContainerSurface(PersistedSurface oldLayer) : super(oldLayer) { + PersistedContainerSurface(PersistedSurface? oldLayer) : super(oldLayer) { assert(oldLayer == null || runtimeType == oldLayer.runtimeType); } @@ -651,7 +651,7 @@ abstract class PersistedContainerSurface extends PersistedSurface { @override void recomputeTransformAndClip() { - _transform = parent._transform; + _transform = parent!._transform; _localClipBounds = null; _localTransformInverse = null; _projectedClip = null; @@ -663,32 +663,32 @@ abstract class PersistedContainerSurface extends PersistedSurface { // Memoize length for efficiency. final int len = _children.length; // Memoize container element for efficiency. [childContainer] is polymorphic - final html.Element containerElement = childContainer; + final html.Element? containerElement = childContainer; for (int i = 0; i < len; i++) { final PersistedSurface child = _children[i]; if (child.isPendingRetention) { assert(child.rootElement != null); child.retain(); } else if (child is PersistedContainerSurface && child.oldLayer != null) { - final PersistedSurface oldLayer = child.oldLayer; + final PersistedSurface oldLayer = child.oldLayer!; assert(oldLayer.rootElement != null); assert(debugAssertSurfaceState( oldLayer, PersistedSurfaceState.pendingUpdate)); - child.update(child.oldLayer); + child.update(child.oldLayer as PersistedContainerSurface); } else { assert(debugAssertSurfaceState(child, PersistedSurfaceState.created)); assert(child.rootElement == null); child.build(); } - containerElement.append(child.rootElement); + containerElement!.append(child.rootElement!); child._index = i; } _debugValidateContainerNewState(); } @override - double matchForUpdate(PersistedContainerSurface existingSurface) { - assert(existingSurface.runtimeType == runtimeType); + double matchForUpdate(PersistedContainerSurface? existingSurface) { + assert(existingSurface!.runtimeType == runtimeType); // Intermediate container nodes don't have many resources worth comparing, // so we always return 1.0 to signal that it doesn't matter which one to // choose. @@ -754,7 +754,7 @@ abstract class PersistedContainerSurface extends PersistedSurface { assert(debugAssertSurfaceState(newChild, PersistedSurfaceState.active, PersistedSurfaceState.pendingRetention)); assert(newChild.rootElement != null); - assert(newChild.rootElement.parent == childContainer); + assert(newChild.rootElement!.parent == childContainer); } return true; }()); @@ -768,7 +768,7 @@ abstract class PersistedContainerSurface extends PersistedSurface { assert(oldSurface._children.isEmpty); // Memoizing variables for efficiency. - final html.Element containerElement = childContainer; + final html.Element? containerElement = childContainer; final int length = _children.length; for (int i = 0; i < length; i++) { @@ -779,7 +779,7 @@ abstract class PersistedContainerSurface extends PersistedSurface { newChild, PersistedSurfaceState.pendingRetention)); } else if (newChild is PersistedContainerSurface && newChild.oldLayer != null) { - final PersistedContainerSurface oldLayer = newChild.oldLayer; + final PersistedContainerSurface oldLayer = newChild.oldLayer as PersistedContainerSurface; assert(debugAssertSurfaceState( oldLayer, PersistedSurfaceState.pendingUpdate)); newChild.update(oldLayer); @@ -792,7 +792,7 @@ abstract class PersistedContainerSurface extends PersistedSurface { } newChild._index = i; assert(newChild.rootElement != null); - containerElement.append(newChild.rootElement); + containerElement!.append(newChild.rootElement!); } } @@ -823,8 +823,8 @@ abstract class PersistedContainerSurface extends PersistedSurface { assert(newChild.rootElement != null); // Move the HTML node if necessary. - if (newChild.rootElement.parent != childContainer) { - childContainer.append(newChild.rootElement); + if (newChild.rootElement!.parent != childContainer) { + childContainer!.append(newChild.rootElement!); } newChild.retain(); @@ -839,15 +839,15 @@ abstract class PersistedContainerSurface extends PersistedSurface { // are released. if (newChild is PersistedContainerSurface && newChild.oldLayer != null) { assert(debugAssertSurfaceState( - newChild.oldLayer, PersistedSurfaceState.pendingUpdate)); + newChild.oldLayer!, PersistedSurfaceState.pendingUpdate)); assert(newChild.rootElement == null); - assert(newChild.oldLayer.rootElement != null); + assert(newChild.oldLayer!.rootElement != null); - final PersistedContainerSurface oldLayer = newChild.oldLayer; + final PersistedContainerSurface oldLayer = newChild.oldLayer as PersistedContainerSurface; // Move the HTML node if necessary. - if (oldLayer.rootElement.parent != childContainer) { - childContainer.append(oldLayer.rootElement); + if (oldLayer.rootElement!.parent != childContainer) { + childContainer!.append(oldLayer.rootElement!); } newChild.update(oldLayer); @@ -859,7 +859,7 @@ abstract class PersistedContainerSurface extends PersistedSurface { assert(debugAssertSurfaceState(newChild, PersistedSurfaceState.created)); - PersistedSurface bestMatch; + PersistedSurface? bestMatch; double bestScore = 2.0; for (int i = 0; i < oldSurface._children.length; i++) { final PersistedSurface candidate = oldSurface._children[i]; @@ -878,15 +878,15 @@ abstract class PersistedContainerSurface extends PersistedSurface { newChild.update(bestMatch); // Move the HTML node if necessary. - if (newChild.rootElement.parent != childContainer) { - childContainer.append(newChild.rootElement); + if (newChild.rootElement!.parent != childContainer) { + childContainer!.append(newChild.rootElement!); } assert( debugAssertSurfaceState(bestMatch, PersistedSurfaceState.released)); } else { newChild.build(); - childContainer.append(newChild.rootElement); + childContainer!.append(newChild.rootElement!); assert(debugAssertSurfaceState(newChild, PersistedSurfaceState.active)); } @@ -907,15 +907,15 @@ abstract class PersistedContainerSurface extends PersistedSurface { assert(_children.isNotEmpty && oldSurface._children.isNotEmpty); // Memoize container element for efficiency. [childContainer] is polymorphic - final html.Element containerElement = childContainer; - final Map matches = + final html.Element? containerElement = childContainer; + final Map matches = _matchChildren(oldSurface); // This pair of lists maps from _children indices to oldSurface._children indices. // These lists are initialized lazily, only when we discover that we will need to // move nodes around. Otherwise, these lists remain null. - List indexMapNew; - List indexMapOld; + List? indexMapNew; + List? indexMapOld; // Whether children need to move around the DOM. It is common for children // to be updated/retained but never move. Knowing this allows us to bypass @@ -926,7 +926,7 @@ abstract class PersistedContainerSurface extends PersistedSurface { final PersistedSurface newChild = _children[topInNew]; // The old child surface that `newChild` was updated or retained from. - PersistedSurface matchedOldChild; + PersistedSurface? matchedOldChild; // Whether the child is getting a new parent. This happens in the // following situations: // - It's a new child and is being attached for the first time. @@ -935,15 +935,15 @@ abstract class PersistedContainerSurface extends PersistedSurface { bool isReparenting = true; if (newChild.isPendingRetention) { - isReparenting = newChild.rootElement.parent != containerElement; + isReparenting = newChild.rootElement!.parent != containerElement; newChild.retain(); matchedOldChild = newChild; assert(debugAssertSurfaceState( newChild, PersistedSurfaceState.pendingRetention)); } else if (newChild is PersistedContainerSurface && newChild.oldLayer != null) { - final PersistedContainerSurface oldLayer = newChild.oldLayer; - isReparenting = oldLayer.rootElement.parent != containerElement; + final PersistedContainerSurface oldLayer = newChild.oldLayer as PersistedContainerSurface; + isReparenting = oldLayer.rootElement!.parent != containerElement; matchedOldChild = oldLayer; assert(debugAssertSurfaceState( oldLayer, PersistedSurfaceState.pendingUpdate)); @@ -956,7 +956,7 @@ abstract class PersistedContainerSurface extends PersistedSurface { if (matchedOldChild != null) { assert(debugAssertSurfaceState( matchedOldChild, PersistedSurfaceState.active)); - isReparenting = matchedOldChild.rootElement.parent != containerElement; + isReparenting = matchedOldChild.rootElement!.parent != containerElement; newChild.update(matchedOldChild); assert(debugAssertSurfaceState( matchedOldChild, PersistedSurfaceState.released)); @@ -995,8 +995,8 @@ abstract class PersistedContainerSurface extends PersistedSurface { } } if (requiresDomInserts && indexInOld != -1) { - indexMapNew.add(topInNew); - indexMapOld.add(indexInOld); + indexMapNew!.add(topInNew); + indexMapOld!.add(indexInOld); } newChild._index = topInNew; @@ -1008,8 +1008,8 @@ abstract class PersistedContainerSurface extends PersistedSurface { // Avoid calling `_insertChildDomNodes` unnecessarily. Only call it if we // actually need to move DOM nodes around. if (requiresDomInserts) { - assert(indexMapNew.length == indexMapOld.length); - _insertChildDomNodes(indexMapNew, indexMapOld); + assert(indexMapNew!.length == indexMapOld!.length); + _insertChildDomNodes(indexMapNew, indexMapOld!); } else { // The fast path, where nothing needs to move, should not intialize the // mapping lists at all. @@ -1023,35 +1023,35 @@ abstract class PersistedContainerSurface extends PersistedSurface { /// Performs the minimum number of DOM moves necessary to put all children in /// the right place in the DOM. - void _insertChildDomNodes(List indexMapNew, List indexMapOld) { - final List stationaryIndices = longestIncreasingSubsequence(indexMapOld); + void _insertChildDomNodes(List? indexMapNew, List indexMapOld) { + final List stationaryIndices = longestIncreasingSubsequence(indexMapOld); // Convert to stationary new indices for (int i = 0; i < stationaryIndices.length; i++) { - stationaryIndices[i] = indexMapNew[stationaryIndices[i]]; + stationaryIndices[i] = indexMapNew![stationaryIndices[i]!]; } - html.HtmlElement refNode; - final html.Element containerElement = childContainer; + html.HtmlElement? refNode; + final html.Element? containerElement = childContainer; for (int i = _children.length - 1; i >= 0; i -= 1) { - final int indexInNew = indexMapNew.indexOf(i); + final int indexInNew = indexMapNew!.indexOf(i); final bool isStationary = indexInNew != -1 && stationaryIndices.contains(i); final PersistedSurface child = _children[i]; - final html.HtmlElement childElement = child.rootElement; - assert(childElement != null); + final html.HtmlElement childElement = child.rootElement as html.HtmlElement; + assert(childElement != null); // ignore: unnecessary_null_comparison if (!isStationary) { if (refNode == null) { - containerElement.append(childElement); + containerElement!.append(childElement); } else { - containerElement.insertBefore(childElement, refNode); + containerElement!.insertBefore(childElement, refNode); } } refNode = childElement; - assert(child.rootElement.parent == childContainer); + assert(child.rootElement!.parent == childContainer); } } - Map _matchChildren( + Map _matchChildren( PersistedContainerSurface oldSurface) { final int newUnfilteredChildCount = _children.length; final int oldUnfilteredChildCount = oldSurface._children.length; @@ -1068,7 +1068,7 @@ abstract class PersistedContainerSurface extends PersistedSurface { } // Extract old nodes that can be matched against. - final List oldChildren = []; + final List oldChildren = []; for (int i = 0; i < oldUnfilteredChildCount; i++) { final PersistedSurface child = oldSurface._children[i]; if (child.isActive) { @@ -1095,9 +1095,9 @@ abstract class PersistedContainerSurface extends PersistedSurface { for (int indexInNew = 0; indexInNew < newChildCount; indexInNew += 1) { final PersistedSurface newChild = newChildren[indexInNew]; for (int indexInOld = 0; indexInOld < oldChildCount; indexInOld += 1) { - final PersistedSurface oldChild = oldChildren[indexInOld]; + final PersistedSurface? oldChild = oldChildren[indexInOld]; final bool childAlreadyClaimed = oldChild == null; - if (childAlreadyClaimed || !newChild.canUpdateAsMatch(oldChild)) { + if (childAlreadyClaimed || !newChild.canUpdateAsMatch(oldChild!)) { continue; } allMatches.add(_PersistedSurfaceMatch( @@ -1109,19 +1109,19 @@ abstract class PersistedContainerSurface extends PersistedSurface { } allMatches.sort((_PersistedSurfaceMatch m1, _PersistedSurfaceMatch m2) { - return m1.matchQuality.compareTo(m2.matchQuality); + return m1.matchQuality!.compareTo(m2.matchQuality!); }); - final Map result = - {}; + final Map result = + {}; for (int i = 0; i < allMatches.length; i += 1) { final _PersistedSurfaceMatch match = allMatches[i]; // This may be null if it has been claimed. - final PersistedSurface matchedChild = oldChildren[match.oldChildIndex]; + final PersistedSurface? matchedChild = oldChildren[match.oldChildIndex!]; // Whether the new child hasn't found a match yet. final bool newChildNeedsMatch = result[match.newChild] == null; if (matchedChild != null && newChildNeedsMatch) { - oldChildren[match.oldChildIndex] = null; + oldChildren[match.oldChildIndex!] = null; result[match.newChild] = matchedChild; // claim it } } @@ -1190,23 +1190,23 @@ class _PersistedSurfaceMatch { /// The child in the new scene who we are trying to match to an existing /// child. - final PersistedSurface newChild; + final PersistedSurface? newChild; /// The index pointing at the old child that matched [newChild] in the old /// child list. /// /// The indirection is intentional because when matches are traversed old /// children are claimed and nulled out in the array. - final int oldChildIndex; + final int? oldChildIndex; /// The score of how well [newChild] matched the old child as computed by /// [PersistedSurface.matchForUpdate]. - final double matchQuality; + final double? matchQuality; @override String toString() { if (assertionsEnabled) { - return '_PersistedSurfaceMatch(${newChild.runtimeType}#${newChild.hashCode}: $oldChildIndex, quality: $matchQuality)'; + return '_PersistedSurfaceMatch(${newChild!.runtimeType}#${newChild!.hashCode}: $oldChildIndex, quality: $matchQuality)'; } else { return super.toString(); } diff --git a/lib/web_ui/lib/src/engine/surface/surface_stats.dart b/lib/web_ui/lib/src/engine/surface/surface_stats.dart index 9bb6cab18a3b4..cb539752195d8 100644 --- a/lib/web_ui/lib/src/engine/surface/surface_stats.dart +++ b/lib/web_ui/lib/src/engine/surface/surface_stats.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 part of engine; /// Surfaces that were retained this frame. @@ -39,7 +38,7 @@ class _DebugSurfaceStats { _DebugSurfaceStats(this.surface); /// The surface these stats are for, or `null` if these are aggregated stats. - final PersistedSurface surface; + final PersistedSurface? surface; /// How many times a surface was retained from a previously rendered frame. int retainSurfaceCount = 0; @@ -88,7 +87,7 @@ class _DebugSurfaceStats { } } -html.CanvasRenderingContext2D _debugSurfaceStatsOverlayCtx; +html.CanvasRenderingContext2D? _debugSurfaceStatsOverlayCtx; void _debugRepaintSurfaceStatsOverlay(PersistedScene scene) { final int overlayWidth = html.window.innerWidth; @@ -115,10 +114,10 @@ void _debugRepaintSurfaceStatsOverlay(PersistedScene scene) { ..zIndex = '1000' ..opacity = '0.8'; _debugSurfaceStatsOverlayCtx = _debugSurfaceStatsOverlay.context2D; - html.document.body.append(_debugSurfaceStatsOverlay); + html.document.body!.append(_debugSurfaceStatsOverlay); } - _debugSurfaceStatsOverlayCtx + _debugSurfaceStatsOverlayCtx! ..fillStyle = 'black' ..beginPath() ..rect(0, 0, overlayWidth, overlayHeight) @@ -131,7 +130,7 @@ void _debugRepaintSurfaceStatsOverlay(PersistedScene scene) { final double physicsScreenPixelCount = physicalScreenWidth * physicalScreenHeight; - final int totalDomNodeCount = scene.rootElement.querySelectorAll('*').length; + final int totalDomNodeCount = scene.rootElement!.querySelectorAll('*').length; for (int i = 0; i < _surfaceStatsTimeline.length; i++) { final Map statsMap = @@ -141,7 +140,7 @@ void _debugRepaintSurfaceStatsOverlay(PersistedScene scene) { for (_DebugSurfaceStats oneSurfaceStats in statsMap.values) { totals.aggregate(oneSurfaceStats); if (oneSurfaceStats.surface is PersistedPicture) { - final PersistedPicture picture = oneSurfaceStats.surface; + final PersistedPicture picture = oneSurfaceStats.surface as PersistedPicture; pixelCount += picture.bitmapPixelCount; } } @@ -155,7 +154,7 @@ void _debugRepaintSurfaceStatsOverlay(PersistedScene scene) { totals.retainSurfaceCount / _surfaceStatsTimeline[i].length; // Repaints - _debugSurfaceStatsOverlayCtx + _debugSurfaceStatsOverlayCtx! ..lineWidth = strokeWidth ..strokeStyle = 'red' ..beginPath() @@ -164,7 +163,7 @@ void _debugRepaintSurfaceStatsOverlay(PersistedScene scene) { ..stroke(); // DOM allocations - _debugSurfaceStatsOverlayCtx + _debugSurfaceStatsOverlayCtx! ..lineWidth = strokeWidth ..strokeStyle = 'red' ..beginPath() @@ -173,7 +172,7 @@ void _debugRepaintSurfaceStatsOverlay(PersistedScene scene) { ..stroke(); // Bitmap allocations - _debugSurfaceStatsOverlayCtx + _debugSurfaceStatsOverlayCtx! ..lineWidth = strokeWidth ..strokeStyle = 'red' ..beginPath() @@ -182,7 +181,7 @@ void _debugRepaintSurfaceStatsOverlay(PersistedScene scene) { ..stroke(); // Surface retentions - _debugSurfaceStatsOverlayCtx + _debugSurfaceStatsOverlayCtx! ..lineWidth = strokeWidth ..strokeStyle = 'green' ..beginPath() @@ -191,7 +190,7 @@ void _debugRepaintSurfaceStatsOverlay(PersistedScene scene) { ..stroke(); } - _debugSurfaceStatsOverlayCtx + _debugSurfaceStatsOverlayCtx! ..font = 'normal normal 14px sans-serif' ..fillStyle = 'white' ..fillText('Repaint rate', 5, rowHeight - 5) @@ -200,7 +199,7 @@ void _debugRepaintSurfaceStatsOverlay(PersistedScene scene) { ..fillText('Retain rate', 5, 4 * rowHeight - 5); for (int i = 1; i <= rowCount; i++) { - _debugSurfaceStatsOverlayCtx + _debugSurfaceStatsOverlayCtx! ..lineWidth = 1 ..strokeStyle = 'blue' ..beginPath() @@ -231,7 +230,7 @@ void _debugPrintSurfaceStats(PersistedScene scene, int frameNumber) { void countReusesRecursively(PersistedSurface surface) { final _DebugSurfaceStats stats = _surfaceStatsFor(surface); - assert(stats != null); + assert(stats != null); // ignore: unnecessary_null_comparison surfaceRetainCount += stats.retainSurfaceCount; elementReuseCount += stats.reuseElementCount; diff --git a/lib/web_ui/lib/src/engine/surface/transform.dart b/lib/web_ui/lib/src/engine/surface/transform.dart index 470c4a8b74725..716090bc2e545 100644 --- a/lib/web_ui/lib/src/engine/surface/transform.dart +++ b/lib/web_ui/lib/src/engine/surface/transform.dart @@ -2,26 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 part of engine; /// A surface that transforms its children using CSS transform. class PersistedTransform extends PersistedContainerSurface implements ui.TransformEngineLayer { - PersistedTransform(PersistedTransform oldLayer, this.matrix4) + PersistedTransform(PersistedTransform? oldLayer, this.matrix4) : super(oldLayer); final Float32List matrix4; @override void recomputeTransformAndClip() { - _transform = parent._transform.multiplied(Matrix4.fromFloat32List(matrix4)); + _transform = parent!._transform!.multiplied(Matrix4.fromFloat32List(matrix4)); _localTransformInverse = null; _projectedClip = null; } @override - Matrix4 get localTransformInverse { + Matrix4? get localTransformInverse { _localTransformInverse ??= Matrix4.tryInvert(Matrix4.fromFloat32List(matrix4)); return _localTransformInverse; @@ -35,7 +34,7 @@ class PersistedTransform extends PersistedContainerSurface @override void apply() { - rootElement.style.transform = float64ListToCssTransform(matrix4); + rootElement!.style.transform = float64ListToCssTransform(matrix4); } @override diff --git a/lib/web_ui/lib/src/engine/test_embedding.dart b/lib/web_ui/lib/src/engine/test_embedding.dart index c1295a2ff0921..9f55594399530 100644 --- a/lib/web_ui/lib/src/engine/test_embedding.dart +++ b/lib/web_ui/lib/src/engine/test_embedding.dart @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; const bool _debugLogHistoryActions = false; class TestHistoryEntry { final dynamic state; - final String title; + final String? title; final String url; const TestHistoryEntry(this.state, this.title, this.url); @@ -77,7 +77,7 @@ class TestLocationStrategy extends LocationStrategy { } @override - void replaceState(dynamic state, String title, String url) { + void replaceState(dynamic state, String title, String? url) { assert(withinAppHistory); if (url == null || url == '') { url = currentEntry.url; @@ -157,10 +157,10 @@ class TestLocationStrategy extends LocationStrategy { @override String toString() { - final List lines = List(history.length); + final List lines = []; for (int i = 0; i < history.length; i++) { final TestHistoryEntry entry = history[i]; - lines[i] = _currentEntryIndex == i ? '* $entry' : ' $entry'; + lines.add(_currentEntryIndex == i ? '* $entry' : ' $entry'); } return '$runtimeType: [\n${lines.join('\n')}\n]'; } diff --git a/lib/web_ui/lib/src/engine/text/font_collection.dart b/lib/web_ui/lib/src/engine/text/font_collection.dart index e68880fda8efc..91b1909964f4c 100644 --- a/lib/web_ui/lib/src/engine/text/font_collection.dart +++ b/lib/web_ui/lib/src/engine/text/font_collection.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; const String _ahemFontFamily = 'Ahem'; @@ -17,8 +17,8 @@ const String _robotoFontUrl = 'packages/ui/assets/Roboto-Regular.ttf'; /// font manifest. If test fonts are enabled, then call /// [registerTestFonts] as well. class FontCollection { - FontManager _assetFontManager; - FontManager _testFontManager; + FontManager? _assetFontManager; + FontManager? _testFontManager; /// Reads the font manifest using the [assetManager] and registers all of the /// fonts declared within. @@ -37,12 +37,7 @@ class FontCollection { } } - if (byteData == null) { - throw AssertionError( - 'There was a problem trying to load FontManifest.json'); - } - - final List fontManifest = + final List? fontManifest = json.decode(utf8.decode(byteData.buffer.asUint8List())); if (fontManifest == null) { throw AssertionError( @@ -55,8 +50,8 @@ class FontCollection { _assetFontManager = _PolyfillFontManager(); } - for (Map fontFamily in fontManifest) { - final String family = fontFamily['family']; + for (Map fontFamily in fontManifest.cast>()) { + final String? family = fontFamily['family']; final List fontAssets = fontFamily['fonts']; for (dynamic fontAssetItem in fontAssets) { @@ -68,22 +63,22 @@ class FontCollection { descriptors[descriptor] = '${fontAsset[descriptor]}'; } } - _assetFontManager.registerAsset( - family, 'url(${assetManager.getAssetUrl(asset)})', descriptors); + _assetFontManager!.registerAsset( + family!, 'url(${assetManager.getAssetUrl(asset)})', descriptors); } } } - Future loadFontFromList(Uint8List list, {String fontFamily}) { - return _assetFontManager._loadFontFaceBytes(fontFamily, list); + Future loadFontFromList(Uint8List list, {required String fontFamily}) { + return _assetFontManager!._loadFontFaceBytes(fontFamily, list); } /// Registers fonts that are used by tests. void debugRegisterTestFonts() { _testFontManager = FontManager(); - _testFontManager.registerAsset( + _testFontManager!.registerAsset( _ahemFontFamily, 'url($_ahemFontUrl)', const {}); - _testFontManager.registerAsset( + _testFontManager!.registerAsset( _robotoFontFamily, 'url($_robotoFontUrl)', const {}); } @@ -256,14 +251,14 @@ class _PolyfillFontManager extends FontManager { } paragraph.text = _testString; - html.document.body.append(paragraph); + html.document.body!.append(paragraph); final int sansSerifWidth = paragraph.offsetWidth; paragraph.style.fontFamily = "'$family', $fallbackFontName"; final Completer completer = Completer(); - DateTime _fontLoadStart; + late DateTime _fontLoadStart; void _watchWidth() { if (paragraph.offsetWidth != sansSerifWidth) { @@ -281,7 +276,7 @@ class _PolyfillFontManager extends FontManager { } } - final Map fontStyleMap = {}; + final Map fontStyleMap = {}; fontStyleMap['font-family'] = "'$family'"; fontStyleMap['src'] = asset; if (descriptors['style'] != null) { @@ -296,7 +291,7 @@ class _PolyfillFontManager extends FontManager { final html.StyleElement fontLoadStyle = html.StyleElement(); fontLoadStyle.type = 'text/css'; fontLoadStyle.innerHtml = '@font-face { $fontFaceDeclaration }'; - html.document.head.append(fontLoadStyle); + html.document.head!.append(fontLoadStyle); // HACK: If this is an icon font, then when it loads it won't change the // width of our test string. So we just have to hope it loads before the @@ -314,4 +309,4 @@ class _PolyfillFontManager extends FontManager { } final bool supportsFontLoadingApi = js_util.hasProperty(html.window, 'FontFace'); -final bool supportsFontsClearApi = html.document.fonts != null && js_util.hasProperty(html.document.fonts, 'clear'); +final bool supportsFontsClearApi = js_util.hasProperty(html.document, 'fonts') && js_util.hasProperty(html.document.fonts, 'clear'); diff --git a/lib/web_ui/lib/src/engine/text/line_break_properties.dart b/lib/web_ui/lib/src/engine/text/line_break_properties.dart index 291736d2438d6..d475a3bcb9961 100644 --- a/lib/web_ui/lib/src/engine/text/line_break_properties.dart +++ b/lib/web_ui/lib/src/engine/text/line_break_properties.dart @@ -12,7 +12,7 @@ // # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. // # For terms of use, see http://www.unicode.org/terms_of_use.html -// @dart = 2.6 + part of engine; /// For an explanation of these enum values, see: diff --git a/lib/web_ui/lib/src/engine/text/line_breaker.dart b/lib/web_ui/lib/src/engine/text/line_breaker.dart index dff40c10a7764..eac5430ae5419 100644 --- a/lib/web_ui/lib/src/engine/text/line_breaker.dart +++ b/lib/web_ui/lib/src/engine/text/line_breaker.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Various types of line breaks as defined by the Unicode spec. @@ -29,7 +29,7 @@ class LineBreakResult { } /// Normalizes properties that behave the same way into one common property. -LineCharProperty _normalizeLineProperty(LineCharProperty prop) { +LineCharProperty? _normalizeLineProperty(LineCharProperty? prop) { // LF and NL behave exactly the same as BK. // See: https://www.unicode.org/reports/tr14/tr14-22.html#ExplicitBreaks if (prop == LineCharProperty.LF || prop == LineCharProperty.NL) { @@ -56,11 +56,11 @@ LineCharProperty _normalizeLineProperty(LineCharProperty prop) { /// * https://www.unicode.org/Public/11.0.0/ucd/LineBreak.txt LineBreakResult nextLineBreak(String text, int index) { // "raw" refers to the property before normalization. - LineCharProperty rawCurr = lineLookup.find(text, index); - LineCharProperty curr = _normalizeLineProperty(rawCurr); + LineCharProperty? rawCurr = lineLookup.find(text, index); + LineCharProperty? curr = _normalizeLineProperty(rawCurr); - LineCharProperty rawPrev; - LineCharProperty prev; + LineCharProperty? rawPrev; + LineCharProperty? prev; bool hasSpaces = false; diff --git a/lib/web_ui/lib/src/engine/text/measurement.dart b/lib/web_ui/lib/src/engine/text/measurement.dart index eb625144d72da..7d844f913418a 100644 --- a/lib/web_ui/lib/src/engine/text/measurement.dart +++ b/lib/web_ui/lib/src/engine/text/measurement.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; // TODO(yjbanov): this is a hack we use to compute ideographic baseline; this @@ -17,7 +17,7 @@ const double _baselineRatioHack = 1.1662499904632568; typedef CharPredicate = bool Function(int char); bool _whitespacePredicate(int char) { - final LineCharProperty prop = + final LineCharProperty? prop = _normalizeLineProperty(lineLookup.findForChar(char)); return prop == LineCharProperty.SP || prop == LineCharProperty.BK || @@ -25,7 +25,7 @@ bool _whitespacePredicate(int char) { } bool _newlinePredicate(int char) { - final LineCharProperty prop = + final LineCharProperty? prop = _normalizeLineProperty(lineLookup.findForChar(char)); return prop == LineCharProperty.BK || prop == LineCharProperty.CR; } @@ -35,7 +35,7 @@ bool _newlinePredicate(int char) { /// /// All instances of [ParagraphRuler] should be created through this class. class RulerManager { - RulerManager({@required this.rulerCacheCapacity}) { + RulerManager({required this.rulerCacheCapacity}) { _rulerHost.style ..position = 'fixed' ..visibility = 'hidden' @@ -44,7 +44,7 @@ class RulerManager { ..left = '0' ..width = '0' ..height = '0'; - html.document.body.append(_rulerHost); + html.document.body!.append(_rulerHost); registerHotRestartListener(dispose); } @@ -89,7 +89,7 @@ class RulerManager { /// /// After this is called, this object is no longer usable. void dispose() { - _rulerHost?.remove(); + _rulerHost.remove(); } // Evicts all rulers from the cache. @@ -148,7 +148,7 @@ class RulerManager { /// elsewhere. @visibleForTesting ParagraphRuler findOrCreateRuler(ParagraphGeometricStyle style) { - ParagraphRuler ruler = _rulers[style]; + ParagraphRuler? ruler = _rulers[style]; if (ruler == null) { if (assertionsEnabled) { domRenderer.debugRulerCacheMiss(); @@ -177,14 +177,14 @@ abstract class TextMeasurementService { /// Initializes the text measurement service with a specific /// [rulerCacheCapacity] that gets passed to the [RulerManager]. - static void initialize({@required int rulerCacheCapacity}) { + static void initialize({required int rulerCacheCapacity}) { rulerManager?.dispose(); rulerManager = null; rulerManager = RulerManager(rulerCacheCapacity: rulerCacheCapacity); } @visibleForTesting - static RulerManager rulerManager; + static RulerManager? rulerManager; /// The DOM-based text measurement service. @visibleForTesting @@ -208,8 +208,8 @@ abstract class TextMeasurementService { // Skip using canvas measurements until the iframe becomes visible. // see: https://github.com/flutter/flutter/issues/36341 if (!window.physicalSize.isEmpty && - WebExperiments.instance.useCanvasText && - _canUseCanvasMeasurement(paragraph)) { + WebExperiments.instance!.useCanvasText && + _canUseCanvasMeasurement(paragraph as EngineParagraph)) { return canvasInstance; } return domInstance; @@ -233,14 +233,14 @@ abstract class TextMeasurementService { } /// Measures the paragraph and returns a [MeasurementResult] object. - MeasurementResult measure( + MeasurementResult? measure( EngineParagraph paragraph, ui.ParagraphConstraints constraints, ) { assert(rulerManager != null); final ParagraphGeometricStyle style = paragraph._geometricStyle; final ParagraphRuler ruler = - TextMeasurementService.rulerManager.findOrCreateRuler(style); + TextMeasurementService.rulerManager!.findOrCreateRuler(style); if (assertionsEnabled) { if (paragraph._plainText == null) { @@ -250,7 +250,7 @@ abstract class TextMeasurementService { } } - MeasurementResult result = ruler.cacheLookup(paragraph, constraints); + MeasurementResult? result = ruler.cacheLookup(paragraph, constraints); if (result != null) { return result; } @@ -266,24 +266,24 @@ abstract class TextMeasurementService { /// Returns text position given a paragraph, constraints and offset. ui.TextPosition getTextPositionForOffset(EngineParagraph paragraph, - ui.ParagraphConstraints constraints, ui.Offset offset); + ui.ParagraphConstraints? constraints, ui.Offset offset); /// Delegates to a [ParagraphRuler] to measure a list of text boxes that /// enclose the given range of text. List measureBoxesForRange( EngineParagraph paragraph, ui.ParagraphConstraints constraints, { - int start, - int end, - double alignOffset, - ui.TextDirection textDirection, + required int start, + required int end, + required double alignOffset, + required ui.TextDirection textDirection, }) { final ParagraphGeometricStyle style = paragraph._geometricStyle; final ParagraphRuler ruler = - TextMeasurementService.rulerManager.findOrCreateRuler(style); + TextMeasurementService.rulerManager!.findOrCreateRuler(style); return ruler.measureBoxesForRange( - paragraph._plainText, + paragraph._plainText!, constraints, start: start, end: end, @@ -328,7 +328,7 @@ class DomTextMeasurementService extends TextMeasurementService { static DomTextMeasurementService get instance => _instance ??= DomTextMeasurementService(); - static DomTextMeasurementService _instance; + static DomTextMeasurementService? _instance; @override MeasurementResult _doMeasure( @@ -337,7 +337,7 @@ class DomTextMeasurementService extends TextMeasurementService { ParagraphRuler ruler, ) { ruler.willMeasure(paragraph); - final String plainText = paragraph._plainText; + final String? plainText = paragraph._plainText; ruler.measureAll(constraints); @@ -361,12 +361,12 @@ class DomTextMeasurementService extends TextMeasurementService { assert(paragraph._plainText != null); final ParagraphGeometricStyle style = paragraph._geometricStyle; final ParagraphRuler ruler = - TextMeasurementService.rulerManager.findOrCreateRuler(style); + TextMeasurementService.rulerManager!.findOrCreateRuler(style); - final String text = paragraph._plainText.substring(start, end); + final String text = paragraph._plainText!.substring(start, end); final ui.Paragraph substringParagraph = paragraph._cloneWithText(text); - ruler.willMeasure(substringParagraph); + ruler.willMeasure(substringParagraph as EngineParagraph); ruler.measureAsSingleLine(); final TextDimensions dimensions = ruler.singleLineDimensions; ruler.didMeasure(); @@ -375,17 +375,17 @@ class DomTextMeasurementService extends TextMeasurementService { @override ui.TextPosition getTextPositionForOffset(EngineParagraph paragraph, - ui.ParagraphConstraints constraints, ui.Offset offset) { + ui.ParagraphConstraints? constraints, ui.Offset offset) { assert( - paragraph._measurementResult.lines == null, + paragraph._measurementResult!.lines == null, 'should only be called when the faster lines-based approach is not possible', ); final ParagraphGeometricStyle style = paragraph._geometricStyle; final ParagraphRuler ruler = - TextMeasurementService.rulerManager.findOrCreateRuler(style); + TextMeasurementService.rulerManager!.findOrCreateRuler(style); ruler.willMeasure(paragraph); - final int position = ruler.hitTest(constraints, offset); + final int position = ruler.hitTest(constraints!, offset); ruler.didMeasure(); return ui.TextPosition(offset: position); } @@ -418,8 +418,8 @@ class DomTextMeasurementService extends TextMeasurementService { _applySubPixelRoundingHack(minIntrinsicWidth, maxIntrinsicWidth); final double ideographicBaseline = alphabeticBaseline * _baselineRatioHack; - final String text = paragraph._plainText; - List lines; + final String? text = paragraph._plainText; + List? lines; if (text != null) { final double lineWidth = maxIntrinsicWidth; final double alignOffset = _calculateAlignOffsetForLine( @@ -478,13 +478,13 @@ class DomTextMeasurementService extends TextMeasurementService { final double naturalHeight = ruler.constrainedDimensions.height; double height; - double lineHeight; - final int maxLines = paragraph._geometricStyle.maxLines; + double? lineHeight; + final int? maxLines = paragraph._geometricStyle.maxLines; if (maxLines == null) { height = naturalHeight; } else { // Lazily compute [lineHeight] when [maxLines] is not null. - lineHeight = ruler.lineHeightDimensions.height; + lineHeight = ruler.lineHeightDimensions!.height; height = math.min(naturalHeight, maxLines * lineHeight); } @@ -546,7 +546,7 @@ class CanvasTextMeasurementService extends TextMeasurementService { static CanvasTextMeasurementService get instance => _instance ??= CanvasTextMeasurementService(); - static CanvasTextMeasurementService _instance; + static CanvasTextMeasurementService? _instance; final html.CanvasRenderingContext2D _canvasContext = html.CanvasElement().context2D; @@ -557,9 +557,9 @@ class CanvasTextMeasurementService extends TextMeasurementService { ui.ParagraphConstraints constraints, ParagraphRuler ruler, ) { - final String text = paragraph._plainText; + final String text = paragraph._plainText!; final ParagraphGeometricStyle style = paragraph._geometricStyle; - assert(text != null); + assert(text != null); // ignore: unnecessary_null_comparison // TODO(mdebbar): Check if the whole text can fit in a single-line. Then avoid all this ceremony. _canvasContext.font = style.cssFontString; @@ -592,12 +592,12 @@ class CanvasTextMeasurementService extends TextMeasurementService { } final int lineCount = linesCalculator.lines.length; - final double lineHeight = ruler.lineHeightDimensions.height; + final double lineHeight = ruler.lineHeightDimensions!.height; final double naturalHeight = lineCount * lineHeight; - - final double height = style.maxLines == null + final int? maxLines = style.maxLines; + final double height = maxLines == null ? naturalHeight - : math.min(lineCount, style.maxLines) * lineHeight; + : math.min(lineCount, maxLines) * lineHeight; final MeasurementResult result = MeasurementResult( constraints.width, @@ -624,7 +624,7 @@ class CanvasTextMeasurementService extends TextMeasurementService { @override double measureSubstringWidth(EngineParagraph paragraph, int start, int end) { assert(paragraph._plainText != null); - final String text = paragraph._plainText; + final String text = paragraph._plainText!; final ParagraphGeometricStyle style = paragraph._geometricStyle; _canvasContext.font = style.cssFontString; return _measureSubstring( @@ -638,7 +638,7 @@ class CanvasTextMeasurementService extends TextMeasurementService { @override ui.TextPosition getTextPositionForOffset(EngineParagraph paragraph, - ui.ParagraphConstraints constraints, ui.Offset offset) { + ui.ParagraphConstraints? constraints, ui.Offset offset) { // TODO(flutter_web): implement. return const ui.TextPosition(offset: 0); } @@ -651,7 +651,7 @@ class CanvasTextMeasurementService extends TextMeasurementService { int _lastStart = -1; int _lastEnd = -1; String _lastText = ''; -ParagraphGeometricStyle _lastStyle; +ParagraphGeometricStyle? _lastStyle; double _lastWidth = -1; /// Measures the width of the substring of [text] starting from the index @@ -690,7 +690,7 @@ double _measureSubstring( final String sub = start == 0 && end == text.length ? text : text.substring(start, end); final double width = - _canvasContext.measureText(sub).width + letterSpacing * sub.length; + _canvasContext.measureText(sub).width + letterSpacing * sub.length as double; // What we are doing here is we are rounding to the nearest 2nd decimal // point. So 39.999423 becomes 40, and 11.243982 becomes 11.24. @@ -731,7 +731,7 @@ class LinesCalculator { final EngineParagraph _paragraph; final double _maxWidth; - String get _text => _paragraph._plainText; + String? get _text => _paragraph._plainText; ParagraphGeometricStyle get _style => _paragraph._geometricStyle; /// The lines that have been consumed so far. @@ -741,9 +741,9 @@ class LinesCalculator { int _chunkStart = 0; bool _reachedMaxLines = false; - double _cachedEllipsisWidth; + double? _cachedEllipsisWidth; double get _ellipsisWidth => _cachedEllipsisWidth ??= - _roundWidth(_canvasContext.measureText(_style.ellipsis).width); + _roundWidth(_canvasContext.measureText(_style.ellipsis!).width as double); bool get hasEllipsis => _style.ellipsis != null; bool get unlimitedLines => _style.maxLines == null; @@ -757,7 +757,7 @@ class LinesCalculator { brk.type == LineBreakType.endOfText; final int chunkEnd = brk.index; final int chunkEndWithoutSpace = - _excludeTrailing(_text, _chunkStart, chunkEnd, _whitespacePredicate); + _excludeTrailing(_text!, _chunkStart, chunkEnd, _whitespacePredicate); // A single chunk of text could be force-broken into multiple lines if it // doesn't fit in a single line. That's why we need a loop. @@ -798,11 +798,11 @@ class LinesCalculator { maxWidth: _maxWidth, ); lines.add(EngineLineMetrics.withText( - _text.substring(_lineStart, breakingPoint) + _style.ellipsis, + _text!.substring(_lineStart, breakingPoint) + _style.ellipsis!, startIndex: _lineStart, endIndex: chunkEnd, endIndexWithoutNewlines: - _excludeTrailing(_text, _chunkStart, chunkEnd, _newlinePredicate), + _excludeTrailing(_text!, _chunkStart, chunkEnd, _newlinePredicate), hardBreak: false, width: widthOfResultingLine, left: alignOffset, @@ -842,17 +842,17 @@ class LinesCalculator { } void _addLineBreak({ - @required int lineEnd, - @required bool isHardBreak, + required int lineEnd, + required bool isHardBreak, }) { final int endWithoutNewlines = _excludeTrailing( - _text, + _text!, _lineStart, lineEnd, _newlinePredicate, ); final int endWithoutSpace = _excludeTrailing( - _text, + _text!, _lineStart, endWithoutNewlines, _whitespacePredicate, @@ -865,7 +865,7 @@ class LinesCalculator { maxWidth: _maxWidth, ); final EngineLineMetrics metrics = EngineLineMetrics.withText( - _text.substring(_lineStart, endWithoutNewlines), + _text!.substring(_lineStart, endWithoutNewlines), startIndex: _lineStart, endIndex: lineEnd, endIndexWithoutNewlines: endWithoutNewlines, @@ -887,7 +887,7 @@ class LinesCalculator { /// This method uses [_text], [_style] and [_canvasContext] to perform the /// measurement. double measureSubstring(int start, int end) { - return _measureSubstring(_canvasContext, _style, _text, start, end); + return _measureSubstring(_canvasContext, _style, _text!, start, end); } /// In a continuous block of text, finds the point where text can be broken to @@ -896,13 +896,13 @@ class LinesCalculator { /// This always returns at least one character even if there isn't enough /// space for it. int forceBreakSubstring({ - @required double maxWidth, - @required int start, - @required int end, + required double maxWidth, + required int start, + required int end, }) { assert(0 <= start); assert(start < end); - assert(end <= _text.length); + assert(end <= _text!.length); // When there's no ellipsis, the breaking point should be at least one // character away from [start]. @@ -1001,9 +1001,9 @@ class MaxIntrinsicCalculator { /// Calculates the offset necessary for the given line to be correctly aligned. double _calculateAlignOffsetForLine({ - @required EngineParagraph paragraph, - @required double lineWidth, - @required double maxWidth, + required EngineParagraph paragraph, + required double lineWidth, + required double maxWidth, }) { final double emptySpace = maxWidth - lineWidth; // WARNING: the [paragraph] may not be laid out yet at this point. This diff --git a/lib/web_ui/lib/src/engine/text/paragraph.dart b/lib/web_ui/lib/src/engine/text/paragraph.dart index c02a81c308032..4903f330eaa87 100644 --- a/lib/web_ui/lib/src/engine/text/paragraph.dart +++ b/lib/web_ui/lib/src/engine/text/paragraph.dart @@ -2,50 +2,49 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 part of engine; class EngineLineMetrics implements ui.LineMetrics { EngineLineMetrics({ - this.hardBreak, - this.ascent, - this.descent, - this.unscaledAscent, - this.height, - this.width, - this.left, - this.baseline, - this.lineNumber, + required this.hardBreak, + required this.ascent, + required this.descent, + required this.unscaledAscent, + required this.height, + required this.width, + required this.left, + required this.baseline, + required this.lineNumber, }) : displayText = null, startIndex = -1, endIndex = -1, endIndexWithoutNewlines = -1; EngineLineMetrics.withText( - this.displayText, { - @required this.startIndex, - @required this.endIndex, - @required this.endIndexWithoutNewlines, - @required this.hardBreak, - this.ascent, - this.descent, - this.unscaledAscent, - this.height, - @required this.width, - @required this.left, - this.baseline, - @required this.lineNumber, - }) : assert(displayText != null), - assert(startIndex != null), - assert(endIndex != null), - assert(endIndexWithoutNewlines != null), - assert(hardBreak != null), - assert(width != null), - assert(left != null), - assert(lineNumber != null && lineNumber >= 0); + String this.displayText, { + required this.startIndex, + required this.endIndex, + required this.endIndexWithoutNewlines, + required this.hardBreak, + required this.width, + required this.left, + required this.lineNumber, + }) : assert(displayText != null), // ignore: unnecessary_null_comparison + assert(startIndex != null), // ignore: unnecessary_null_comparison + assert(endIndex != null), // ignore: unnecessary_null_comparison + assert(endIndexWithoutNewlines != null), // ignore: unnecessary_null_comparison + assert(hardBreak != null), // ignore: unnecessary_null_comparison + assert(width != null), // ignore: unnecessary_null_comparison + assert(left != null), // ignore: unnecessary_null_comparison + assert(lineNumber != null && lineNumber >= 0), // ignore: unnecessary_null_comparison + ascent = double.infinity, + descent = double.infinity, + unscaledAscent = double.infinity, + height = double.infinity, + baseline = double.infinity; /// The text to be rendered on the screen representing this line. - final String displayText; + final String? displayText; /// The index (inclusive) in the text where this line begins. final int startIndex; @@ -126,6 +125,23 @@ class EngineLineMetrics implements ui.LineMetrics { baseline == typedOther.baseline && lineNumber == typedOther.lineNumber; } + + @override + String toString() { + if (assertionsEnabled) { + return 'LineMetrics(hardBreak: $hardBreak, ' + 'ascent: $ascent, ' + 'descent: $descent, ' + 'unscaledAscent: $unscaledAscent, ' + 'height: $height, ' + 'width: $width, ' + 'left: $left, ' + 'baseline: $baseline, ' + 'lineNumber: $lineNumber)'; + } else { + return super.toString(); + } + } } /// The web implementation of [ui.Paragraph]. @@ -135,13 +151,13 @@ class EngineParagraph implements ui.Paragraph { /// /// To create a [ui.Paragraph] object, use a [ui.ParagraphBuilder]. EngineParagraph({ - @required html.HtmlElement paragraphElement, - @required ParagraphGeometricStyle geometricStyle, - @required String plainText, - @required ui.Paint paint, - @required ui.TextAlign textAlign, - @required ui.TextDirection textDirection, - @required ui.Paint background, + required html.HtmlElement paragraphElement, + required ParagraphGeometricStyle geometricStyle, + required String? plainText, + required ui.Paint? paint, + required ui.TextAlign textAlign, + required ui.TextDirection textDirection, + required ui.Paint? background, }) : assert((plainText == null && paint == null) || (plainText != null && paint != null)), _paragraphElement = paragraphElement, @@ -149,19 +165,19 @@ class EngineParagraph implements ui.Paragraph { _plainText = plainText, _textAlign = textAlign, _textDirection = textDirection, - _paint = paint, - _background = background; + _paint = paint as SurfacePaint?, + _background = background as SurfacePaint?; final html.HtmlElement _paragraphElement; final ParagraphGeometricStyle _geometricStyle; - final String _plainText; - final SurfacePaint _paint; + final String? _plainText; + final SurfacePaint? _paint; final ui.TextAlign _textAlign; final ui.TextDirection _textDirection; - final SurfacePaint _background; + final SurfacePaint? _background; @visibleForTesting - String get plainText => _plainText; + String? get plainText => _plainText; @visibleForTesting html.HtmlElement get paragraphElement => _paragraphElement; @@ -175,7 +191,7 @@ class EngineParagraph implements ui.Paragraph { TextMeasurementService.forParagraph(this); /// The measurement result of the last layout operation. - MeasurementResult _measurementResult; + MeasurementResult? _measurementResult; bool get _hasLineMetrics => _measurementResult?.lines != null; @@ -202,7 +218,7 @@ class EngineParagraph implements ui.Paragraph { double get longestLine { if (_hasLineMetrics) { double maxWidth = 0.0; - for (ui.LineMetrics metrics in _measurementResult.lines) { + for (ui.LineMetrics metrics in _measurementResult!.lines!) { if (maxWidth < metrics.width) { maxWidth = metrics.width; } @@ -232,7 +248,7 @@ class EngineParagraph implements ui.Paragraph { bool get didExceedMaxLines => _didExceedMaxLines; bool _didExceedMaxLines = false; - ui.ParagraphConstraints _lastUsedConstraints; + ui.ParagraphConstraints? _lastUsedConstraints; /// Returns horizontal alignment offset for single line text when rendering /// directly into a canvas without css text alignment styling. @@ -255,14 +271,14 @@ class EngineParagraph implements ui.Paragraph { return; } - Stopwatch stopwatch; + late Stopwatch stopwatch; if (Profiler.isBenchmarkMode) { stopwatch = Stopwatch()..start(); } _measurementResult = _measurementService.measure(this, constraints); if (Profiler.isBenchmarkMode) { stopwatch.stop(); - Profiler.instance.benchmark('text_layout', stopwatch.elapsedMicroseconds); + Profiler.instance.benchmark('text_layout', stopwatch.elapsedMicroseconds.toDouble()); } _lastUsedConstraints = constraints; @@ -273,7 +289,7 @@ class EngineParagraph implements ui.Paragraph { _didExceedMaxLines = false; } - if (_measurementResult.isSingleLine && constraints != null) { + if (_measurementResult!.isSingleLine) { switch (_textAlign) { case ui.TextAlign.center: _alignOffset = (constraints.width - maxIntrinsicWidth) / 2.0; @@ -357,8 +373,8 @@ class EngineParagraph implements ui.Paragraph { ui.BoxHeightStyle boxHeightStyle = ui.BoxHeightStyle.tight, ui.BoxWidthStyle boxWidthStyle = ui.BoxWidthStyle.tight, }) { - assert(boxHeightStyle != null); - assert(boxWidthStyle != null); + assert(boxHeightStyle != null); // ignore: unnecessary_null_comparison + assert(boxWidthStyle != null); // ignore: unnecessary_null_comparison // Zero-length ranges and invalid ranges return an empty list. if (start == end || start < 0 || end < 0) { return []; @@ -369,11 +385,11 @@ class EngineParagraph implements ui.Paragraph { // https://github.com/flutter/flutter/issues/55587 if (_plainText == null) { return [ - ui.TextBox.fromLTRBD(0, 0, 0, _lineHeight, _textDirection) + ui.TextBox.fromLTRBD(0, 0, 0, _lineHeight, _textDirection), ]; } - final int length = _plainText.length; + final int length = _plainText!.length; // Ranges that are out of bounds should return an empty list. if (start > length || end > length) { return []; @@ -384,7 +400,7 @@ class EngineParagraph implements ui.Paragraph { if (!_hasLineMetrics) { return _measurementService.measureBoxesForRange( this, - _lastUsedConstraints, + _lastUsedConstraints!, start: start, end: end, alignOffset: _alignOffset, @@ -392,7 +408,7 @@ class EngineParagraph implements ui.Paragraph { ); } - final List lines = _measurementResult.lines; + final List lines = _measurementResult!.lines!; if (start >= lines.last.endIndex) { return []; } @@ -444,7 +460,7 @@ class EngineParagraph implements ui.Paragraph { ui.Paragraph _cloneWithText(String plainText) { return EngineParagraph( plainText: plainText, - paragraphElement: _paragraphElement.clone(true), + paragraphElement: _paragraphElement.clone(true) as html.HtmlElement, geometricStyle: _geometricStyle, paint: _paint, textAlign: _textAlign, @@ -455,7 +471,7 @@ class EngineParagraph implements ui.Paragraph { @override ui.TextPosition getPositionForOffset(ui.Offset offset) { - final List lines = _measurementResult.lines; + final List? lines = _measurementResult!.lines; if (!_hasLineMetrics) { return getPositionForMultiSpanOffset(offset); } @@ -468,12 +484,12 @@ class EngineParagraph implements ui.Paragraph { ); } - final int lineNumber = offset.dy ~/ _measurementResult.lineHeight; + final int lineNumber = offset.dy ~/ _measurementResult!.lineHeight!; // [offset] is below all the lines. - if (lineNumber >= lines.length) { + if (lineNumber >= lines!.length) { return ui.TextPosition( - offset: _plainText.length, + offset: _plainText!.length, affinity: ui.TextAffinity.upstream, ); } @@ -562,7 +578,7 @@ class EngineParagraph implements ui.Paragraph { EngineLineMetrics _getLineForIndex(int index) { assert(_hasLineMetrics); - final List lines = _measurementResult.lines; + final List lines = _measurementResult!.lines!; assert(index >= 0); for (int i = 0; i < lines.length; i++) { @@ -586,7 +602,7 @@ class EngineParagraph implements ui.Paragraph { @override List computeLineMetrics() { - return _measurementResult.lines; + return _measurementResult!.lines!; } } @@ -594,18 +610,18 @@ class EngineParagraph implements ui.Paragraph { class EngineParagraphStyle implements ui.ParagraphStyle { /// Creates a new instance of [EngineParagraphStyle]. EngineParagraphStyle({ - ui.TextAlign textAlign, - ui.TextDirection textDirection, - int maxLines, - String fontFamily, - double fontSize, - double height, - ui.TextHeightBehavior textHeightBehavior, - ui.FontWeight fontWeight, - ui.FontStyle fontStyle, - ui.StrutStyle strutStyle, - String ellipsis, - ui.Locale locale, + ui.TextAlign? textAlign, + ui.TextDirection? textDirection, + int? maxLines, + String? fontFamily, + double? fontSize, + double? height, + ui.TextHeightBehavior? textHeightBehavior, + ui.FontWeight? fontWeight, + ui.FontStyle? fontStyle, + ui.StrutStyle? strutStyle, + String? ellipsis, + ui.Locale? locale, }) : _textAlign = textAlign, _textDirection = textDirection, _fontWeight = fontWeight, @@ -616,22 +632,26 @@ class EngineParagraphStyle implements ui.ParagraphStyle { _height = height, _textHeightBehavior = textHeightBehavior, // TODO(b/128317744): add support for strut style. - _strutStyle = strutStyle, + _strutStyle = strutStyle as EngineStrutStyle?, _ellipsis = ellipsis, _locale = locale; - final ui.TextAlign _textAlign; - final ui.TextDirection _textDirection; - final ui.FontWeight _fontWeight; - final ui.FontStyle _fontStyle; - final int _maxLines; - final String _fontFamily; - final double _fontSize; - final double _height; - final ui.TextHeightBehavior _textHeightBehavior; - final EngineStrutStyle _strutStyle; - final String _ellipsis; - final ui.Locale _locale; + final ui.TextAlign? _textAlign; + final ui.TextDirection? _textDirection; + final ui.FontWeight? _fontWeight; + final ui.FontStyle? _fontStyle; + final int? _maxLines; + final String? _fontFamily; + final double? _fontSize; + final double? _height; + final ui.TextHeightBehavior? _textHeightBehavior; + final EngineStrutStyle? _strutStyle; + final String? _ellipsis; + final ui.Locale? _locale; + + // The effective style attributes should be consistent with paragraph_style.h. + ui.TextAlign get _effectiveTextAlign => _textAlign ?? ui.TextAlign.start; + ui.TextDirection get _effectiveTextDirection => _textDirection ?? ui.TextDirection.ltr; String get _effectiveFontFamily { if (assertionsEnabled) { @@ -641,28 +661,29 @@ class EngineParagraphStyle implements ui.ParagraphStyle { return 'Ahem'; } } - if (_fontFamily == null || _fontFamily.isEmpty) { + final String? fontFamily = _fontFamily; + if (fontFamily == null || fontFamily.isEmpty) { return DomRenderer.defaultFontFamily; } - return _fontFamily; + return fontFamily; } - double get _lineHeight { + double? get _lineHeight { // TODO(mdebbar): Implement proper support for strut styles. // https://github.com/flutter/flutter/issues/32243 if (_strutStyle == null || - _strutStyle._height == null || - _strutStyle._height == 0) { + _strutStyle!._height == null || + _strutStyle!._height == 0) { // When there's no strut height, always use paragraph style height. return _height; } - if (_strutStyle._forceStrutHeight == true) { + if (_strutStyle!._forceStrutHeight == true) { // When strut height is forced, ignore paragraph style height. - return _strutStyle._height; + return _strutStyle!._height; } // In this case, strut height acts as a minimum height for all parts of the // paragraph. So we take the max of strut height and paragraph style height. - return math.max(_strutStyle._height, _height ?? 0.0); + return math.max(_strutStyle!._height!, _height ?? 0.0); } @override @@ -714,8 +735,8 @@ class EngineParagraphStyle implements ui.ParagraphStyle { 'maxLines: ${_maxLines ?? "unspecified"}, ' 'textHeightBehavior: ${_textHeightBehavior ?? "unspecified"}, ' 'fontFamily: ${_fontFamily ?? "unspecified"}, ' - 'fontSize: ${_fontSize != null ? _fontSize.toStringAsFixed(1) : "unspecified"}, ' - 'height: ${_height != null ? "${_height.toStringAsFixed(1)}x" : "unspecified"}, ' + 'fontSize: ${_fontSize != null ? _fontSize!.toStringAsFixed(1) : "unspecified"}, ' + 'height: ${_height != null ? "${_height!.toStringAsFixed(1)}x" : "unspecified"}, ' 'ellipsis: ${_ellipsis != null ? "\"$_ellipsis\"" : "unspecified"}, ' 'locale: ${_locale ?? "unspecified"}' ')'; @@ -728,25 +749,25 @@ class EngineParagraphStyle implements ui.ParagraphStyle { /// The web implementation of [ui.TextStyle]. class EngineTextStyle implements ui.TextStyle { EngineTextStyle({ - ui.Color color, - ui.TextDecoration decoration, - ui.Color decorationColor, - ui.TextDecorationStyle decorationStyle, - double decorationThickness, - ui.FontWeight fontWeight, - ui.FontStyle fontStyle, - ui.TextBaseline textBaseline, - String fontFamily, - List fontFamilyFallback, - double fontSize, - double letterSpacing, - double wordSpacing, - double height, - ui.Locale locale, - ui.Paint background, - ui.Paint foreground, - List shadows, - List fontFeatures, + ui.Color? color, + ui.TextDecoration? decoration, + ui.Color? decorationColor, + ui.TextDecorationStyle? decorationStyle, + double? decorationThickness, + ui.FontWeight? fontWeight, + ui.FontStyle? fontStyle, + ui.TextBaseline? textBaseline, + String? fontFamily, + List? fontFamilyFallback, + double? fontSize, + double? letterSpacing, + double? wordSpacing, + double? height, + ui.Locale? locale, + ui.Paint? background, + ui.Paint? foreground, + List? shadows, + List? fontFeatures, }) : assert( color == null || foreground == null, 'Cannot provide both a color and a foreground\n' @@ -773,26 +794,26 @@ class EngineTextStyle implements ui.TextStyle { _foreground = foreground, _shadows = shadows; - final ui.Color _color; - final ui.TextDecoration _decoration; - final ui.Color _decorationColor; - final ui.TextDecorationStyle _decorationStyle; - final double _decorationThickness; - final ui.FontWeight _fontWeight; - final ui.FontStyle _fontStyle; - final ui.TextBaseline _textBaseline; + final ui.Color? _color; + final ui.TextDecoration? _decoration; + final ui.Color? _decorationColor; + final ui.TextDecorationStyle? _decorationStyle; + final double? _decorationThickness; + final ui.FontWeight? _fontWeight; + final ui.FontStyle? _fontStyle; + final ui.TextBaseline? _textBaseline; final bool _isFontFamilyProvided; final String _fontFamily; - final List _fontFamilyFallback; - final List _fontFeatures; - final double _fontSize; - final double _letterSpacing; - final double _wordSpacing; - final double _height; - final ui.Locale _locale; - final ui.Paint _background; - final ui.Paint _foreground; - final List _shadows; + final List? _fontFamilyFallback; + final List? _fontFeatures; + final double? _fontSize; + final double? _letterSpacing; + final double? _wordSpacing; + final double? _height; + final ui.Locale? _locale; + final ui.Paint? _background; + final ui.Paint? _foreground; + final List? _shadows; String get _effectiveFontFamily { if (assertionsEnabled) { @@ -802,7 +823,7 @@ class EngineTextStyle implements ui.TextStyle { return 'Ahem'; } } - if (_fontFamily == null || _fontFamily.isEmpty) { + if (_fontFamily.isEmpty) { return DomRenderer.defaultFontFamily; } return _fontFamily; @@ -871,12 +892,12 @@ class EngineTextStyle implements ui.TextStyle { 'fontWeight: ${_fontWeight ?? "unspecified"}, ' 'fontStyle: ${_fontStyle ?? "unspecified"}, ' 'textBaseline: ${_textBaseline ?? "unspecified"}, ' - 'fontFamily: ${_isFontFamilyProvided && _fontFamily != null ? _fontFamily : "unspecified"}, ' - 'fontFamilyFallback: ${_isFontFamilyProvided && _fontFamilyFallback != null && _fontFamilyFallback.isNotEmpty ? _fontFamilyFallback : "unspecified"}, ' - 'fontSize: ${_fontSize != null ? _fontSize.toStringAsFixed(1) : "unspecified"}, ' + 'fontFamily: ${_isFontFamilyProvided && _fontFamily != '' ? _fontFamily : "unspecified"}, ' + 'fontFamilyFallback: ${_isFontFamilyProvided && _fontFamilyFallback != null && _fontFamilyFallback!.isNotEmpty ? _fontFamilyFallback : "unspecified"}, ' + 'fontSize: ${_fontSize != null ? _fontSize!.toStringAsFixed(1) : "unspecified"}, ' 'letterSpacing: ${_letterSpacing != null ? "${_letterSpacing}x" : "unspecified"}, ' 'wordSpacing: ${_wordSpacing != null ? "${_wordSpacing}x" : "unspecified"}, ' - 'height: ${_height != null ? "${_height.toStringAsFixed(1)}x" : "unspecified"}, ' + 'height: ${_height != null ? "${_height!.toStringAsFixed(1)}x" : "unspecified"}, ' 'locale: ${_locale ?? "unspecified"}, ' 'background: ${_background ?? "unspecified"}, ' 'foreground: ${_foreground ?? "unspecified"}, ' @@ -927,14 +948,14 @@ class EngineStrutStyle implements ui.StrutStyle { /// of the [fontFamily] and `(lineHeight + leading) * fontSize`. Otherwise, it /// will be determined by the Ascent + half-leading of the first text. EngineStrutStyle({ - String fontFamily, - List fontFamilyFallback, - double fontSize, - double height, - double leading, - ui.FontWeight fontWeight, - ui.FontStyle fontStyle, - bool forceStrutHeight, + String? fontFamily, + List? fontFamilyFallback, + double? fontSize, + double? height, + double? leading, + ui.FontWeight? fontWeight, + ui.FontStyle? fontStyle, + bool? forceStrutHeight, }) : _fontFamily = fontFamily, _fontFamilyFallback = fontFamilyFallback, _fontSize = fontSize, @@ -944,14 +965,14 @@ class EngineStrutStyle implements ui.StrutStyle { _fontStyle = fontStyle, _forceStrutHeight = forceStrutHeight; - final String _fontFamily; - final List _fontFamilyFallback; - final double _fontSize; - final double _height; - final double _leading; - final ui.FontWeight _fontWeight; - final ui.FontStyle _fontStyle; - final bool _forceStrutHeight; + final String? _fontFamily; + final List? _fontFamilyFallback; + final double? _fontSize; + final double? _height; + final double? _leading; + final ui.FontWeight? _fontWeight; + final ui.FontStyle? _fontStyle; + final bool? _forceStrutHeight; @override bool operator ==(dynamic other) { @@ -991,7 +1012,7 @@ class EngineParagraphBuilder implements ui.ParagraphBuilder { /// Marks a call to the [pop] method in the [_ops] list. static final Object _paragraphBuilderPop = Object(); - final html.HtmlElement _paragraphElement = domRenderer.createElement('p'); + final html.HtmlElement _paragraphElement = domRenderer.createElement('p') as html.HtmlElement; final EngineParagraphStyle _paragraphStyle; final List _ops = []; @@ -999,14 +1020,14 @@ class EngineParagraphBuilder implements ui.ParagraphBuilder { /// [EngineParagraph]. EngineParagraphBuilder(EngineParagraphStyle style) : _paragraphStyle = style { // TODO(b/128317744): Implement support for strut font families. - List strutFontFamilies; + List strutFontFamilies; if (style._strutStyle != null) { - strutFontFamilies = []; - if (style._strutStyle._fontFamily != null) { - strutFontFamilies.add(style._strutStyle._fontFamily); + strutFontFamilies = []; + if (style._strutStyle!._fontFamily != null) { + strutFontFamilies.add(style._strutStyle!._fontFamily); } - if (style._strutStyle._fontFamilyFallback != null) { - strutFontFamilies.addAll(style._strutStyle._fontFamilyFallback); + if (style._strutStyle!._fontFamilyFallback != null) { + strutFontFamilies.addAll(style._strutStyle!._fontFamilyFallback!); } } _applyParagraphStyleToElement( @@ -1023,7 +1044,7 @@ class EngineParagraphBuilder implements ui.ParagraphBuilder { @override int get placeholderCount => _placeholderCount; - int _placeholderCount; + late int _placeholderCount; @override List get placeholderScales => _placeholderScales; @@ -1035,8 +1056,8 @@ class EngineParagraphBuilder implements ui.ParagraphBuilder { double height, ui.PlaceholderAlignment alignment, { double scale = 1.0, - double baselineOffset, - ui.TextBaseline baseline, + double? baselineOffset, + ui.TextBaseline? baseline, }) { // TODO(garyq): Implement stub_ui version of this. throw UnimplementedError(); @@ -1090,25 +1111,25 @@ class EngineParagraphBuilder implements ui.ParagraphBuilder { /// arbitrarily. However, it may not mix multiple styles in the same /// paragraph. Plain text is more efficient to lay out and measure than rich /// text. - EngineParagraph _tryBuildPlainText() { - ui.Color color; - ui.TextDecoration decoration; - ui.Color decorationColor; - ui.TextDecorationStyle decorationStyle; - ui.FontWeight fontWeight = _paragraphStyle._fontWeight; - ui.FontStyle fontStyle = _paragraphStyle._fontStyle; - ui.TextBaseline textBaseline; - String fontFamily = _paragraphStyle._fontFamily; - double fontSize = _paragraphStyle._fontSize; - final ui.TextAlign textAlign = _paragraphStyle._textAlign; - final ui.TextDirection textDirection = _paragraphStyle._textDirection; - double letterSpacing; - double wordSpacing; - double height; - ui.Locale locale = _paragraphStyle._locale; - ui.Paint background; - ui.Paint foreground; - List shadows; + EngineParagraph? _tryBuildPlainText() { + ui.Color? color; + ui.TextDecoration? decoration; + ui.Color? decorationColor; + ui.TextDecorationStyle? decorationStyle; + ui.FontWeight? fontWeight = _paragraphStyle._fontWeight; + ui.FontStyle? fontStyle = _paragraphStyle._fontStyle; + ui.TextBaseline? textBaseline; + String? fontFamily = _paragraphStyle._fontFamily; + double? fontSize = _paragraphStyle._fontSize; + final ui.TextAlign textAlign = _paragraphStyle._effectiveTextAlign; + final ui.TextDirection textDirection = _paragraphStyle._effectiveTextDirection; + double? letterSpacing; + double? wordSpacing; + double? height; + ui.Locale? locale = _paragraphStyle._locale; + ui.Paint? background; + ui.Paint? foreground; + List? shadows; int i = 0; @@ -1139,9 +1160,7 @@ class EngineParagraphBuilder implements ui.ParagraphBuilder { if (style._textBaseline != null) { textBaseline = style._textBaseline; } - if (style._fontFamily != null) { - fontFamily = style._fontFamily; - } + fontFamily = style._fontFamily; if (style._fontSize != null) { fontSize = style._fontSize; } @@ -1287,7 +1306,7 @@ class EngineParagraphBuilder implements ui.ParagraphBuilder { for (int i = 0; i < _ops.length; i++) { final dynamic op = _ops[i]; if (op is EngineTextStyle) { - final html.SpanElement span = domRenderer.createElement('span'); + final html.SpanElement span = domRenderer.createElement('span') as html.SpanElement; _applyTextStyleToElement(element: span, style: op, isSpan: true); if (op._background != null) { _applyTextBackgroundToElement(element: span, style: op); @@ -1316,15 +1335,15 @@ class EngineParagraphBuilder implements ui.ParagraphBuilder { ), plainText: null, paint: null, - textAlign: _paragraphStyle._textAlign, - textDirection: _paragraphStyle._textDirection, + textAlign: _paragraphStyle._effectiveTextAlign, + textDirection: _paragraphStyle._effectiveTextDirection, background: null, ); } } /// Converts [fontWeight] to its CSS equivalent value. -String fontWeightToCss(ui.FontWeight fontWeight) { +String? fontWeightToCss(ui.FontWeight? fontWeight) { if (fontWeight == null) { return null; } @@ -1367,12 +1386,12 @@ String fontWeightIndexToCss({int fontWeightIndex = 3}) { /// /// If [previousStyle] is not null, updates only the mismatching attributes. void _applyParagraphStyleToElement({ - @required html.HtmlElement element, - @required EngineParagraphStyle style, - EngineParagraphStyle previousStyle, + required html.HtmlElement element, + required EngineParagraphStyle style, + EngineParagraphStyle? previousStyle, }) { - assert(element != null); - assert(style != null); + assert(element != null); // ignore: unnecessary_null_comparison + assert(style != null); // ignore: unnecessary_null_comparison // TODO(yjbanov): What do we do about ParagraphStyle._locale and ellipsis? final html.CssStyleDeclaration cssStyle = element.style; if (previousStyle == null) { @@ -1387,7 +1406,7 @@ void _applyParagraphStyleToElement({ cssStyle.direction = _textDirectionToCss(style._textDirection); } if (style._fontSize != null) { - cssStyle.fontSize = '${style._fontSize.floor()}px'; + cssStyle.fontSize = '${style._fontSize!.floor()}px'; } if (style._fontWeight != null) { cssStyle.fontWeight = fontWeightToCss(style._fontWeight); @@ -1396,9 +1415,7 @@ void _applyParagraphStyleToElement({ cssStyle.fontStyle = style._fontStyle == ui.FontStyle.normal ? 'normal' : 'italic'; } - if (style._effectiveFontFamily != null) { - cssStyle.fontFamily = canonicalizeFontFamily(style._effectiveFontFamily); - } + cssStyle.fontFamily = canonicalizeFontFamily(style._effectiveFontFamily); } else { if (style._textAlign != previousStyle._textAlign) { cssStyle.textAlign = textAlignToCssValue( @@ -1412,7 +1429,7 @@ void _applyParagraphStyleToElement({ } if (style._fontSize != previousStyle._fontSize) { cssStyle.fontSize = - style._fontSize != null ? '${style._fontSize.floor()}px' : null; + style._fontSize != null ? '${style._fontSize!.floor()}px' : null; } if (style._fontWeight != previousStyle._fontWeight) { cssStyle.fontWeight = fontWeightToCss(style._fontWeight); @@ -1435,22 +1452,22 @@ void _applyParagraphStyleToElement({ /// If [isSpan] is true, the text element is a span within richtext and /// should not assign effectiveFontFamily if fontFamily was not specified. void _applyTextStyleToElement({ - @required html.HtmlElement element, - @required EngineTextStyle style, - EngineTextStyle previousStyle, + required html.HtmlElement element, + required EngineTextStyle style, + EngineTextStyle? previousStyle, bool isSpan = false, }) { - assert(element != null); - assert(style != null); + assert(element != null); // ignore: unnecessary_null_comparison + assert(style != null); // ignore: unnecessary_null_comparison bool updateDecoration = false; final html.CssStyleDeclaration cssStyle = element.style; if (previousStyle == null) { - final ui.Color color = style._foreground?.color ?? style._color; + final ui.Color? color = style._foreground?.color ?? style._color; if (color != null) { cssStyle.color = colorToCssString(color); } if (style._fontSize != null) { - cssStyle.fontSize = '${style._fontSize.floor()}px'; + cssStyle.fontSize = '${style._fontSize!.floor()}px'; } if (style._fontWeight != null) { cssStyle.fontWeight = fontWeightToCss(style._fontWeight); @@ -1462,14 +1479,10 @@ void _applyTextStyleToElement({ // For test environment use effectiveFontFamily since we need to // consistently use Ahem font. if (isSpan && !ui.debugEmulateFlutterTesterEnvironment) { - if (style._fontFamily != null) { - cssStyle.fontFamily = canonicalizeFontFamily(style._fontFamily); - } + cssStyle.fontFamily = canonicalizeFontFamily(style._fontFamily); } else { - if (style._effectiveFontFamily != null) { - cssStyle.fontFamily = - canonicalizeFontFamily(style._effectiveFontFamily); - } + cssStyle.fontFamily = + canonicalizeFontFamily(style._effectiveFontFamily); } if (style._letterSpacing != null) { cssStyle.letterSpacing = '${style._letterSpacing}px'; @@ -1481,18 +1494,18 @@ void _applyTextStyleToElement({ updateDecoration = true; } if (style._shadows != null) { - cssStyle.textShadow = _shadowListToCss(style._shadows); + cssStyle.textShadow = _shadowListToCss(style._shadows!); } } else { if (style._color != previousStyle._color || style._foreground != previousStyle._foreground) { - final ui.Color color = style._foreground?.color ?? style._color; + final ui.Color? color = style._foreground?.color ?? style._color; cssStyle.color = colorToCssString(color); } if (style._fontSize != previousStyle._fontSize) { cssStyle.fontSize = - style._fontSize != null ? '${style._fontSize.floor()}px' : null; + style._fontSize != null ? '${style._fontSize!.floor()}px' : null; } if (style._fontWeight != previousStyle._fontWeight) { @@ -1519,13 +1532,13 @@ void _applyTextStyleToElement({ updateDecoration = true; } if (style._shadows != previousStyle._shadows) { - cssStyle.textShadow = _shadowListToCss(style._shadows); + cssStyle.textShadow = _shadowListToCss(style._shadows!); } } if (updateDecoration) { if (style._decoration != null) { - final String textDecoration = + final String? textDecoration = _textDecorationToCssString(style._decoration, style._decorationStyle); if (textDecoration != null) { if (browserEngine == BrowserEngine.webkit) { @@ -1534,9 +1547,9 @@ void _applyTextStyleToElement({ } else { cssStyle.textDecoration = textDecoration; } - final ui.Color decorationColor = style._decorationColor; + final ui.Color? decorationColor = style._decorationColor; if (decorationColor != null) { - cssStyle.textDecorationColor = colorToCssString(decorationColor); + cssStyle.textDecorationColor = colorToCssString(decorationColor)!; } } } @@ -1567,11 +1580,11 @@ String _shadowListToCss(List shadows) { /// Applies background color properties in text style to paragraph or span /// elements. void _applyTextBackgroundToElement({ - @required html.HtmlElement element, - @required EngineTextStyle style, - EngineTextStyle previousStyle, + required html.HtmlElement element, + required EngineTextStyle style, + EngineTextStyle? previousStyle, }) { - final ui.Paint newBackground = style._background; + final ui.Paint? newBackground = style._background; if (previousStyle == null) { if (newBackground != null) { domRenderer.setElementStyle( @@ -1580,14 +1593,14 @@ void _applyTextBackgroundToElement({ } else { if (newBackground != previousStyle._background) { domRenderer.setElementStyle( - element, 'background-color', colorToCssString(newBackground.color)); + element, 'background-color', colorToCssString(newBackground!.color)); } } } /// Converts text decoration style to CSS text-decoration-style value. -String _textDecorationToCssString( - ui.TextDecoration decoration, ui.TextDecorationStyle decorationStyle) { +String? _textDecorationToCssString( + ui.TextDecoration? decoration, ui.TextDecorationStyle? decorationStyle) { final StringBuffer decorations = StringBuffer(); if (decoration != null) { if (decoration.contains(ui.TextDecoration.underline)) { @@ -1606,7 +1619,7 @@ String _textDecorationToCssString( return decorations.isEmpty ? null : decorations.toString(); } -String _decorationStyleToCssString(ui.TextDecorationStyle decorationStyle) { +String? _decorationStyleToCssString(ui.TextDecorationStyle decorationStyle) { switch (decorationStyle) { case ui.TextDecorationStyle.dashed: return 'dashed'; @@ -1630,14 +1643,14 @@ String _decorationStyleToCssString(ui.TextDecorationStyle decorationStyle) { /// ```css /// direction: rtl; /// ``` -String _textDirectionToCss(ui.TextDirection textDirection) { +String? _textDirectionToCss(ui.TextDirection? textDirection) { if (textDirection == null) { return null; } return textDirectionIndexToCss(textDirection.index); } -String textDirectionIndexToCss(int textDirectionIndex) { +String? textDirectionIndexToCss(int textDirectionIndex) { switch (textDirectionIndex) { case 0: return 'rtl'; @@ -1661,7 +1674,7 @@ String textDirectionIndexToCss(int textDirectionIndex) { /// ```css /// text-align: right; /// ``` -String textAlignToCssValue(ui.TextAlign align, ui.TextDirection textDirection) { +String? textAlignToCssValue(ui.TextAlign? align, ui.TextDirection textDirection) { switch (align) { case ui.TextAlign.left: return 'left'; @@ -1671,24 +1684,23 @@ String textAlignToCssValue(ui.TextAlign align, ui.TextDirection textDirection) { return 'center'; case ui.TextAlign.justify: return 'justify'; - case ui.TextAlign.start: + case ui.TextAlign.end: switch (textDirection) { case ui.TextDirection.ltr: - return null; // it's the default + return 'end'; case ui.TextDirection.rtl: - return 'right'; + return 'left'; } break; - case ui.TextAlign.end: + default: // including ui.TextAlign.start switch (textDirection) { case ui.TextDirection.ltr: - return 'end'; + return null; // it's the default case ui.TextDirection.rtl: - return 'left'; + return 'right'; } break; } - throw AssertionError('Unsupported TextAlign value $align'); } /// Determines if lists [a] and [b] are deep equivalent. @@ -1696,7 +1708,7 @@ String textAlignToCssValue(ui.TextAlign align, ui.TextDirection textDirection) { /// Returns true if the lists are both null, or if they are both non-null, have /// the same length, and contain the same elements in the same order. Returns /// false otherwise. -bool _listEquals(List a, List b) { +bool _listEquals(List? a, List? b) { if (a == null) { return b == null; } diff --git a/lib/web_ui/lib/src/engine/text/ruler.dart b/lib/web_ui/lib/src/engine/text/ruler.dart index 38655a528d861..74080b0659e6f 100644 --- a/lib/web_ui/lib/src/engine/text/ruler.dart +++ b/lib/web_ui/lib/src/engine/text/ruler.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Contains the subset of [ui.ParagraphStyle] properties that affect layout. @@ -21,28 +21,28 @@ class ParagraphGeometricStyle { this.shadows, }); - final ui.FontWeight fontWeight; - final ui.FontStyle fontStyle; - final String fontFamily; - final double fontSize; - final double lineHeight; - final int maxLines; - final double letterSpacing; - final double wordSpacing; - final String decoration; - final String ellipsis; - final List shadows; + final ui.FontWeight? fontWeight; + final ui.FontStyle? fontStyle; + final String? fontFamily; + final double? fontSize; + final double? lineHeight; + final int? maxLines; + final double? letterSpacing; + final double? wordSpacing; + final String? decoration; + final String? ellipsis; + final List? shadows; // Since all fields above are primitives, cache hashcode since ruler lookups // use this style as key. - int _cachedHashCode; + int? _cachedHashCode; /// Returns the font-family that should be used to style the paragraph. It may /// or may not be different from [fontFamily]: /// /// - Always returns "Ahem" in tests. /// - Provides correct defaults when [fontFamily] doesn't have a value. - String get effectiveFontFamily { + String? get effectiveFontFamily { if (assertionsEnabled) { // In widget tests we use a predictable-size font "Ahem". This makes // widget tests predictable and less flaky. @@ -50,13 +50,13 @@ class ParagraphGeometricStyle { return 'Ahem'; } } - if (fontFamily == null || fontFamily.isEmpty) { + if (fontFamily == null || fontFamily!.isEmpty) { return DomRenderer.defaultFontFamily; } return fontFamily; } - String _cssFontString; + String? _cssFontString; /// Cached font string that can be used in CSS. /// @@ -83,7 +83,7 @@ class ParagraphGeometricStyle { result.write(' '); if (fontSize != null) { - result.write(fontSize.floor()); + result.write(fontSize!.floor()); result.write('px'); } else { result.write(DomRenderer.defaultFontSize); @@ -163,15 +163,15 @@ class TextDimensions { TextDimensions(this._element); final html.HtmlElement _element; - html.Rectangle _cachedBoundingClientRect; + html.Rectangle? _cachedBoundingClientRect; /// Attempts to efficiently copy text from [from]. /// /// The primary efficiency gain is from rare occurrence of rich text in /// typical apps. void updateText(EngineParagraph from, ParagraphGeometricStyle style) { - assert(from != null); - assert(_element != null); + assert(from != null); // ignore: unnecessary_null_comparison + assert(_element != null); // ignore: unnecessary_null_comparison assert(from._debugHasSameRootStyle(style)); assert(() { final bool wasEmptyOrPlainText = _element.childNodes.isEmpty || @@ -188,7 +188,7 @@ class TextDimensions { }()); _invalidateBoundsCache(); - final String plainText = from._plainText; + final String? plainText = from._plainText; if (plainText != null) { // Plain text: just set the string. The paragraph's style is assumed to // match the style set on the `element`. Setting text as plain string is @@ -205,13 +205,13 @@ class TextDimensions { } else { // Rich text: deeply copy contents. This is the slow case that should be // avoided if fast layout performance is desired. - final html.Element copy = from._paragraphElement.clone(true); + final html.Element copy = from._paragraphElement.clone(true) as html.Element; _element.nodes.addAll(copy.nodes); } } /// Updated element style width. - void updateConstraintWidth(double width, String ellipsis) { + void updateConstraintWidth(double width, String? ellipsis) { _invalidateBoundsCache(); if (width.isInfinite) { @@ -246,7 +246,7 @@ class TextDimensions { void applyStyle(ParagraphGeometricStyle style) { final html.CssStyleDeclaration elementStyle = _element.style; elementStyle - ..fontSize = style.fontSize != null ? '${style.fontSize.floor()}px' : null + ..fontSize = style.fontSize != null ? '${style.fontSize!.floor()}px' : null ..fontFamily = canonicalizeFontFamily(style.effectiveFontFamily) ..fontWeight = style.fontWeight != null ? fontWeightToCss(style.fontWeight) : null @@ -257,7 +257,7 @@ class TextDimensions { style.letterSpacing != null ? '${style.letterSpacing}px' : null ..wordSpacing = style.wordSpacing != null ? '${style.wordSpacing}px' : null; - final String decoration = style.decoration; + final String? decoration = style.decoration; if (browserEngine == BrowserEngine.webkit) { domRenderer.setElementStyle( _element, '-webkit-text-decoration', decoration); @@ -265,7 +265,7 @@ class TextDimensions { elementStyle.textDecoration = decoration; } if (style.lineHeight != null) { - elementStyle.lineHeight = style.lineHeight.toString(); + elementStyle.lineHeight = style.lineHeight!.toString(); } _invalidateBoundsCache(); } @@ -281,11 +281,11 @@ class TextDimensions { _cachedBoundingClientRect ??= _element.getBoundingClientRect(); /// The width of the paragraph being measured. - double get width => _readAndCacheMetrics().width; + double get width => _readAndCacheMetrics().width as double; /// The height of the paragraph being measured. double get height { - double cachedHeight = _readAndCacheMetrics().height; + double cachedHeight = _readAndCacheMetrics().height as double; if (browserEngine == BrowserEngine.firefox && // In the flutter tester environment, we use a predictable-size for font // measurement tests. @@ -356,7 +356,7 @@ class ParagraphRuler { final html.HtmlElement _probe = html.DivElement(); /// Cached value of alphabetic base line. - double _cachedAlphabeticBaseline; + double? _cachedAlphabeticBaseline; ParagraphRuler(this.style, this.rulerManager) { _configureSingleLineHostElements(); @@ -370,7 +370,7 @@ class ParagraphRuler { /// The alphabetic baseline of the paragraph being measured. double get alphabeticBaseline => - _cachedAlphabeticBaseline ??= _probe.getBoundingClientRect().bottom; + (_cachedAlphabeticBaseline ??= _probe.getBoundingClientRect().bottom as double?)!; // Elements used to measure single-line metrics. final html.DivElement _singleLineHost = html.DivElement(); @@ -388,16 +388,16 @@ class ParagraphRuler { TextDimensions(html.ParagraphElement()); // Elements used to measure the line-height metric. - html.DivElement _lineHeightHost; - TextDimensions _lineHeightDimensions; - TextDimensions get lineHeightDimensions { + html.DivElement? _lineHeightHost; + TextDimensions? _lineHeightDimensions; + TextDimensions? get lineHeightDimensions { // Lazily create the elements for line-height measurement since they are not // always needed. if (_lineHeightDimensions == null) { _lineHeightHost = html.DivElement(); _lineHeightDimensions = TextDimensions(html.ParagraphElement()); _configureLineHeightHostElements(); - _lineHeightHost.append(_probe); + _lineHeightHost!.append(_probe); } return _lineHeightDimensions; } @@ -523,7 +523,7 @@ class ParagraphRuler { } void _configureLineHeightHostElements() { - _lineHeightHost.style + _lineHeightHost!.style ..visibility = 'hidden' ..position = 'absolute' ..top = '0' @@ -536,29 +536,29 @@ class ParagraphRuler { ..padding = '0'; if (assertionsEnabled) { - _lineHeightHost.setAttribute('data-ruler', 'line-height'); + _lineHeightHost!.setAttribute('data-ruler', 'line-height'); } - lineHeightDimensions.applyStyle(style); + lineHeightDimensions!.applyStyle(style); // Force single-line (even if wider than screen) and preserve whitespaces. - lineHeightDimensions._element.style.whiteSpace = 'pre'; + lineHeightDimensions!._element.style.whiteSpace = 'pre'; // To measure line-height, all we need is a whitespace. - lineHeightDimensions.updateTextToSpace(); + lineHeightDimensions!.updateTextToSpace(); - lineHeightDimensions.appendToHost(_lineHeightHost); - rulerManager.addHostElement(_lineHeightHost); + lineHeightDimensions!.appendToHost(_lineHeightHost!); + rulerManager.addHostElement(_lineHeightHost!); } /// The paragraph being measured. - EngineParagraph _paragraph; + EngineParagraph? _paragraph; /// Prepares this ruler for measuring the given [paragraph]. /// /// This method must be called before calling any of the `measure*` methods. void willMeasure(EngineParagraph paragraph) { - assert(paragraph != null); + assert(paragraph != null); // ignore: unnecessary_null_comparison assert(() { if (_paragraph != null) { throw Exception( @@ -593,10 +593,10 @@ class ParagraphRuler { // which doesn't work. So we need to replace it with a whitespace. The // correct fix would be to do line height and baseline measurements and // cache them separately. - if (_paragraph._plainText == '') { + if (_paragraph!._plainText == '') { singleLineDimensions.updateTextToSpace(); } else { - singleLineDimensions.updateText(_paragraph, style); + singleLineDimensions.updateText(_paragraph!, style); } } @@ -608,7 +608,7 @@ class ParagraphRuler { assert(!_debugIsDisposed); assert(_paragraph != null); - minIntrinsicDimensions.updateText(_paragraph, style); + minIntrinsicDimensions.updateText(_paragraph!, style); } /// Lays out the paragraph giving it a width constraint. @@ -618,7 +618,7 @@ class ParagraphRuler { assert(!_debugIsDisposed); assert(_paragraph != null); - constrainedDimensions.updateText(_paragraph, style); + constrainedDimensions.updateText(_paragraph!, style); // The extra 0.5 is because sometimes the browser needs slightly more space // than the size it reports back. When that happens the text may be wrap @@ -645,7 +645,7 @@ class ParagraphRuler { final html.Node node = textNodes[i]; // Check if offset is within client rect bounds of text node's // parent element. - final html.Element parent = node.parentNode; + final html.Element parent = node.parentNode as html.Element; final html.Rectangle bounds = parent.getBoundingClientRect(); final double dx = offset.dx; final double dy = offset.dy; @@ -685,7 +685,7 @@ class ParagraphRuler { break; } if (node.nodeType == html.Node.TEXT_NODE) { - position += node.text.length; + position += node.text!.length; } } return position; @@ -709,7 +709,7 @@ class ParagraphRuler { // // We do not do this for plain text, because replacing plain text is more // expensive than paying the cost of the DOM mutation to clean it. - if (_paragraph._plainText == null) { + if (_paragraph!._plainText == null) { domRenderer ..clearDom(singleLineDimensions._element) ..clearDom(minIntrinsicDimensions._element) @@ -725,10 +725,10 @@ class ParagraphRuler { List measureBoxesForRange( String plainText, ui.ParagraphConstraints constraints, { - int start, - int end, - double alignOffset, - ui.TextDirection textDirection, + required int start, + required int end, + required double alignOffset, + required ui.TextDirection textDirection, }) { assert(!_debugIsDisposed); assert(start >= 0 && start <= plainText.length); @@ -755,9 +755,9 @@ class ParagraphRuler { final double maxLinesLimit = style.maxLines == null ? double.infinity - : style.maxLines * lineHeightDimensions.height; + : style.maxLines! * lineHeightDimensions!.height; - html.Rectangle previousRect; + html.Rectangle? previousRect; for (html.Rectangle rect in clientRects) { // If [rect] is an empty box on the same line as the previous box, don't // include it in the result. @@ -770,10 +770,10 @@ class ParagraphRuler { } boxes.add(ui.TextBox.fromLTRBD( - rect.left + alignOffset, - rect.top, - rect.right + alignOffset, - rect.bottom, + rect.left + alignOffset as double, + rect.top as double, + rect.right + alignOffset as double, + rect.bottom as double, textDirection, )); previousRect = rect; @@ -807,10 +807,10 @@ class ParagraphRuler { } // Bounded cache for text measurement for a particular width constraint. - Map> _measurementCache = - >{}; + Map> _measurementCache = + >{}; // Mru list for cache. - final List _mruList = []; + final List _mruList = []; static const int _cacheLimit = 2400; // Number of items to evict when cache limit is reached. static const int _cacheBlockFactor = 100; @@ -819,10 +819,10 @@ class ParagraphRuler { // is changing. static const int _constraintCacheSize = 8; - void cacheMeasurement(EngineParagraph paragraph, MeasurementResult item) { - final String plainText = paragraph._plainText; - final List constraintCache = - _measurementCache[plainText] ??= []; + void cacheMeasurement(EngineParagraph paragraph, MeasurementResult? item) { + final String? plainText = paragraph._plainText; + final List constraintCache = + _measurementCache[plainText] ??= []; constraintCache.add(item); if (constraintCache.length > _constraintCacheSize) { constraintCache.removeAt(0); @@ -837,21 +837,21 @@ class ParagraphRuler { } } - MeasurementResult cacheLookup( + MeasurementResult? cacheLookup( EngineParagraph paragraph, ui.ParagraphConstraints constraints) { - final String plainText = paragraph._plainText; + final String? plainText = paragraph._plainText; if (plainText == null) { // Multi span paragraph, do not use cache item. return null; } - final List constraintCache = + final List? constraintCache = _measurementCache[plainText]; if (constraintCache == null) { return null; } final int len = constraintCache.length; for (int i = 0; i < len; i++) { - final MeasurementResult item = constraintCache[i]; + final MeasurementResult item = constraintCache[i]!; if (item.constraintWidth == constraints.width && item.textAlign == paragraph._textAlign && item.textDirection == paragraph._textDirection) { @@ -888,7 +888,7 @@ class MeasurementResult { /// /// In some cases, measuring [lineHeight] is unnecessary, so it's nullable. If /// present, it should be equal to [height] when [isSingleLine] is true. - final double lineHeight; + final double? lineHeight; /// {@macro dart.ui.paragraph.minIntrinsicWidth} final double minIntrinsicWidth; @@ -904,7 +904,7 @@ class MeasurementResult { /// The full list of [EngineLineMetrics] that describe in detail the various metrics /// of each laid out line. - final List lines; + final List? lines; /// The text align value of the paragraph. final ui.TextAlign textAlign; @@ -914,27 +914,27 @@ class MeasurementResult { MeasurementResult( this.constraintWidth, { - @required this.isSingleLine, - @required this.width, - @required this.height, - @required this.naturalHeight, - @required this.lineHeight, - @required this.minIntrinsicWidth, - @required this.maxIntrinsicWidth, - @required this.alphabeticBaseline, - @required this.ideographicBaseline, - @required this.lines, - @required ui.TextAlign textAlign, - @required ui.TextDirection textDirection, - }) : assert(constraintWidth != null), - assert(isSingleLine != null), - assert(width != null), - assert(height != null), - assert(naturalHeight != null), - assert(minIntrinsicWidth != null), - assert(maxIntrinsicWidth != null), - assert(alphabeticBaseline != null), - assert(ideographicBaseline != null), + required this.isSingleLine, + required this.width, + required this.height, + required this.naturalHeight, + required this.lineHeight, + required this.minIntrinsicWidth, + required this.maxIntrinsicWidth, + required this.alphabeticBaseline, + required this.ideographicBaseline, + required this.lines, + required ui.TextAlign? textAlign, + required ui.TextDirection? textDirection, + }) : assert(constraintWidth != null), // ignore: unnecessary_null_comparison + assert(isSingleLine != null), // ignore: unnecessary_null_comparison + assert(width != null), // ignore: unnecessary_null_comparison + assert(height != null), // ignore: unnecessary_null_comparison + assert(naturalHeight != null), // ignore: unnecessary_null_comparison + assert(minIntrinsicWidth != null), // ignore: unnecessary_null_comparison + assert(maxIntrinsicWidth != null), // ignore: unnecessary_null_comparison + assert(alphabeticBaseline != null), // ignore: unnecessary_null_comparison + assert(ideographicBaseline != null), // ignore: unnecessary_null_comparison this.textAlign = textAlign ?? ui.TextAlign.start, this.textDirection = textDirection ?? ui.TextDirection.ltr; } diff --git a/lib/web_ui/lib/src/engine/text/unicode_range.dart b/lib/web_ui/lib/src/engine/text/unicode_range.dart index 10263195ac80f..ada988e60c743 100644 --- a/lib/web_ui/lib/src/engine/text/unicode_range.dart +++ b/lib/web_ui/lib/src/engine/text/unicode_range.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; const int _kChar_0 = 48; @@ -88,8 +88,8 @@ class UnicodePropertyLookup

{ /// located at that [index]. /// /// If the [index] is out of range, null will be returned. - P find(String text, int index) { - if (index < 0 || index >= text.length) { + P? find(String? text, int index) { + if (index < 0 || index >= text!.length) { return null; } return findForChar(text.codeUnitAt(index)); @@ -99,7 +99,7 @@ class UnicodePropertyLookup

{ /// /// If a property can't be found for the given character, null will be /// returned. - P findForChar(int char) { + P? findForChar(int char) { final int rangeIndex = _binarySearch(char); return rangeIndex == -1 ? null : ranges[rangeIndex].property; } diff --git a/lib/web_ui/lib/src/engine/text/word_break_properties.dart b/lib/web_ui/lib/src/engine/text/word_break_properties.dart index ab8b9746fc6ee..3b634e59bb422 100644 --- a/lib/web_ui/lib/src/engine/text/word_break_properties.dart +++ b/lib/web_ui/lib/src/engine/text/word_break_properties.dart @@ -12,7 +12,7 @@ // # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. // # For terms of use, see http://www.unicode.org/terms_of_use.html -// @dart = 2.6 + part of engine; /// For an explanation of these enum values, see: diff --git a/lib/web_ui/lib/src/engine/text/word_breaker.dart b/lib/web_ui/lib/src/engine/text/word_breaker.dart index 6df70db3f1a50..037cf058aab25 100644 --- a/lib/web_ui/lib/src/engine/text/word_breaker.dart +++ b/lib/web_ui/lib/src/engine/text/word_breaker.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; enum _FindBreakDirection { @@ -16,28 +16,28 @@ enum _FindBreakDirection { /// [WordBreaker] exposes static methods to identify word boundaries. abstract class WordBreaker { /// It starts from [index] and tries to find the next word boundary in [text]. - static int nextBreakIndex(String text, int index) => + static int nextBreakIndex(String? text, int index) => _findBreakIndex(_FindBreakDirection.forward, text, index); /// It starts from [index] and tries to find the previous word boundary in /// [text]. - static int prevBreakIndex(String text, int index) => + static int prevBreakIndex(String? text, int index) => _findBreakIndex(_FindBreakDirection.backward, text, index); static int _findBreakIndex( _FindBreakDirection direction, - String text, + String? text, int index, ) { int step, min, max; if (direction == _FindBreakDirection.forward) { step = 1; min = 0; - max = text.length - 1; + max = text!.length - 1; } else { step = -1; min = 1; - max = text.length; + max = text!.length; } int i = index; @@ -52,11 +52,11 @@ abstract class WordBreaker { /// Find out if there's a word break between [index - 1] and [index]. /// http://unicode.org/reports/tr29/#Word_Boundary_Rules - static bool _isBreak(String text, int index) { + static bool _isBreak(String? text, int index) { // Break at the start and end of text. // WB1: sot ÷ Any // WB2: Any ÷ eot - if (index <= 0 || index >= text.length) { + if (index <= 0 || index >= text!.length) { return true; } @@ -65,8 +65,8 @@ abstract class WordBreaker { return false; } - final WordCharProperty immediateRight = wordLookup.find(text, index); - WordCharProperty immediateLeft = wordLookup.find(text, index - 1); + final WordCharProperty? immediateRight = wordLookup.find(text, index); + WordCharProperty? immediateLeft = wordLookup.find(text, index - 1); // Do not break within CRLF. // WB3: CR × LF @@ -145,7 +145,7 @@ abstract class WordBreaker { // Skip all Format, Extend and ZWJ to the right. int r = 0; - WordCharProperty nextRight; + WordCharProperty? nextRight; do { r++; nextRight = wordLookup.find(text, index + r); @@ -157,7 +157,7 @@ abstract class WordBreaker { )); // Skip all Format, Extend and ZWJ to the left. - WordCharProperty nextLeft; + WordCharProperty? nextLeft; do { l++; nextLeft = wordLookup.find(text, index - l - 1); @@ -306,12 +306,12 @@ abstract class WordBreaker { } static bool _oneOf( - WordCharProperty value, + WordCharProperty? value, WordCharProperty choice1, WordCharProperty choice2, [ - WordCharProperty choice3, - WordCharProperty choice4, - WordCharProperty choice5, + WordCharProperty? choice3, + WordCharProperty? choice4, + WordCharProperty? choice5, ]) { if (value == choice1) { return true; @@ -331,7 +331,7 @@ abstract class WordBreaker { return false; } - static bool _isAHLetter(WordCharProperty property) { + static bool _isAHLetter(WordCharProperty? property) { return _oneOf(property, WordCharProperty.ALetter, WordCharProperty.HebrewLetter); } } diff --git a/lib/web_ui/lib/src/engine/text_editing/autofill_hint.dart b/lib/web_ui/lib/src/engine/text_editing/autofill_hint.dart index 2b28aee67773e..5e95b45f75f72 100644 --- a/lib/web_ui/lib/src/engine/text_editing/autofill_hint.dart +++ b/lib/web_ui/lib/src/engine/text_editing/autofill_hint.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Maps AutofillHints from the framework to the autofill hints that is used for diff --git a/lib/web_ui/lib/src/engine/text_editing/input_type.dart b/lib/web_ui/lib/src/engine/text_editing/input_type.dart index a3b46ee6db3e3..f4a84b3c65551 100644 --- a/lib/web_ui/lib/src/engine/text_editing/input_type.dart +++ b/lib/web_ui/lib/src/engine/text_editing/input_type.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Various types of inputs used in text fields. @@ -57,7 +57,7 @@ abstract class EngineInputType { /// /// For various `inputmode` values supported by browsers, see: /// . - String get inputmodeAttribute; + String? get inputmodeAttribute; /// Whether this input type allows the "Enter" key to submit the input action. bool get submitActionOnEnter => true; @@ -75,7 +75,7 @@ abstract class EngineInputType { // keyboard shows up. if (operatingSystem == OperatingSystem.iOs || operatingSystem == OperatingSystem.android) { - domElement.setAttribute('inputmode', inputmodeAttribute); + domElement.setAttribute('inputmode', inputmodeAttribute!); } } } @@ -125,7 +125,7 @@ class MultilineInputType extends EngineInputType { const MultilineInputType(); @override - final String inputmodeAttribute = null; + final String? inputmodeAttribute = null; @override bool get submitActionOnEnter => false; diff --git a/lib/web_ui/lib/src/engine/text_editing/text_editing.dart b/lib/web_ui/lib/src/engine/text_editing/text_editing.dart index 607bffc766fe1..abc9f4c50231c 100644 --- a/lib/web_ui/lib/src/engine/text_editing/text_editing.dart +++ b/lib/web_ui/lib/src/engine/text_editing/text_editing.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Make the content editable span visible to facilitate debugging. @@ -84,15 +84,15 @@ void _hideAutofillElements(html.HtmlElement domElement) { class EngineAutofillForm { EngineAutofillForm({this.formElement, this.elements, this.items}); - final html.FormElement formElement; + final html.FormElement? formElement; - final Map elements; + final Map? elements; - final Map items; + final Map? items; - factory EngineAutofillForm.fromFrameworkMessage( - Map focusedElementAutofill, - List fields, + static EngineAutofillForm? fromFrameworkMessage( + Map? focusedElementAutofill, + List? fields, ) { // Autofill value can be null if focused text element does not have an // autofill hint set. @@ -103,9 +103,6 @@ class EngineAutofillForm { // If there is only one text field in the autofill model, `fields` will be // null. `focusedElementAutofill` contains the information about the one // text field. - final bool singleElement = (fields == null); - final AutofillInfo focusedElement = - AutofillInfo.fromFrameworkMessage(focusedElementAutofill); final Map elements = {}; final Map items = {}; final html.FormElement formElement = html.FormElement(); @@ -115,13 +112,15 @@ class EngineAutofillForm { _hideAutofillElements(formElement); - if (!singleElement) { - for (Map field in fields) { + if (fields != null) { + for (Map field in fields.cast>()) { final Map autofillInfo = field['autofill']; final AutofillInfo autofill = AutofillInfo.fromFrameworkMessage(autofillInfo); // The focused text editing element will not be created here. + final AutofillInfo focusedElement = + AutofillInfo.fromFrameworkMessage(focusedElementAutofill); if (autofill.uniqueIdentifier != focusedElement.uniqueIdentifier) { EngineInputType engineInputType = EngineInputType.fromName(field['inputType']['name']); @@ -146,12 +145,12 @@ class EngineAutofillForm { } void placeForm(html.HtmlElement mainTextEditingElement) { - formElement.append(mainTextEditingElement); - domRenderer.glassPaneElement.append(formElement); + formElement!.append(mainTextEditingElement); + domRenderer.glassPaneElement!.append(formElement!); } void removeForm() { - formElement.remove(); + formElement!.remove(); } /// Listens to `onInput` event on the form fields. @@ -165,11 +164,11 @@ class EngineAutofillForm { /// [TextEditingStrategy.addEventHandlers] method call and all /// listeners are removed during [TextEditingStrategy.disable] method call. List> addInputEventListeners() { - Iterable keys = elements.keys; + Iterable keys = elements!.keys; List> subscriptions = >[]; keys.forEach((String key) { - final html.Element element = elements[key]; + final html.Element element = elements![key]!; subscriptions.add(element.onInput.listen((html.Event e) { _handleChange(element, key); })); @@ -177,14 +176,14 @@ class EngineAutofillForm { return subscriptions; } - void _handleChange(html.Element domElement, String tag) { - EditingState newEditingState = EditingState.fromDomElement(domElement); + void _handleChange(html.Element domElement, String? tag) { + EditingState newEditingState = EditingState.fromDomElement(domElement as html.HtmlElement?); _sendAutofillEditingState(tag, newEditingState); } /// Sends the 'TextInputClient.updateEditingStateWithTag' message to the framework. - void _sendAutofillEditingState(String tag, EditingState editingState) { + void _sendAutofillEditingState(String? tag, EditingState editingState) { if (window._onPlatformMessage != null) { window.invokeOnPlatformMessage( 'flutter/textinput', @@ -193,7 +192,7 @@ class EngineAutofillForm { 'TextInputClient.updateEditingStateWithTag', [ 0, - {tag: editingState.toFlutter()} + {tag: editingState.toFlutter()} ], ), ), @@ -208,7 +207,7 @@ class EngineAutofillForm { /// These values are to be used when a text field have autofill enabled. @visibleForTesting class AutofillInfo { - AutofillInfo({this.editingState, this.uniqueIdentifier, this.hint}); + AutofillInfo({required this.editingState, required this.uniqueIdentifier, required this.hint}); /// The current text and selection state of a text field. final EditingState editingState; @@ -226,12 +225,8 @@ class AutofillInfo { final String hint; factory AutofillInfo.fromFrameworkMessage(Map autofill) { - // Autofill value can be null if no TextFields is set with autofill hint. - if (autofill == null) { - return null; - } - - final String uniqueIdentifier = autofill['uniqueIdentifier']; + assert(autofill != null); // ignore: unnecessary_null_comparison + final String uniqueIdentifier = autofill['uniqueIdentifier']!; final List hintsList = autofill['hints']; final EditingState editingState = EditingState.fromFrameworkMessage(autofill['editingValue']); @@ -294,7 +289,7 @@ class EditingState { Map flutterEditingState) { final int selectionBase = flutterEditingState['selectionBase']; final int selectionExtent = flutterEditingState['selectionExtent']; - final String text = flutterEditingState['text']; + final String? text = flutterEditingState['text']; return EditingState( text: text, @@ -307,7 +302,7 @@ class EditingState { /// /// [domElement] can be a [InputElement] or a [TextAreaElement] depending on /// the [InputType] of the text field. - factory EditingState.fromDomElement(html.HtmlElement domElement) { + factory EditingState.fromDomElement(html.HtmlElement? domElement) { if (domElement is html.InputElement) { html.InputElement element = domElement; return EditingState( @@ -335,16 +330,16 @@ class EditingState { }; /// The current text being edited. - final String text; + final String? text; /// The offset at which the text selection originates. - final int baseOffset; + final int? baseOffset; /// The offset at which the text selection terminates. - final int extentOffset; + final int? extentOffset; /// Whether the current editing state is valid or not. - bool get isValid => baseOffset >= 0 && extentOffset >= 0; + bool get isValid => baseOffset! >= 0 && extentOffset! >= 0; @override int get hashCode => ui.hashValues(text, baseOffset, extentOffset); @@ -374,15 +369,15 @@ class EditingState { /// /// [domElement] can be a [InputElement] or a [TextAreaElement] depending on /// the [InputType] of the text field. - void applyToDomElement(html.HtmlElement domElement) { + void applyToDomElement(html.HtmlElement? domElement) { if (domElement is html.InputElement) { html.InputElement element = domElement; element.value = text; - element.setSelectionRange(baseOffset, extentOffset); + element.setSelectionRange(baseOffset!, extentOffset!); } else if (domElement is html.TextAreaElement) { html.TextAreaElement element = domElement; element.value = text; - element.setSelectionRange(baseOffset, extentOffset); + element.setSelectionRange(baseOffset!, extentOffset!); } else { throw UnsupportedError('Unsupported DOM element type'); } @@ -397,13 +392,14 @@ class EditingState { /// This corresponds to Flutter's [TextInputConfiguration]. class InputConfiguration { InputConfiguration({ - @required this.inputType, - @required this.inputAction, - @required this.obscureText, - @required this.autocorrect, + required this.inputType, + required this.inputAction, + required this.obscureText, + required this.autocorrect, this.autofill, this.autofillGroup, }); + InputConfiguration.fromFrameworkMessage( Map flutterInputConfiguration) : inputType = EngineInputType.fromName( @@ -411,8 +407,9 @@ class InputConfiguration { inputAction = flutterInputConfiguration['inputAction'], obscureText = flutterInputConfiguration['obscureText'], autocorrect = flutterInputConfiguration['autocorrect'], - autofill = AutofillInfo.fromFrameworkMessage( - flutterInputConfiguration['autofill']), + autofill = flutterInputConfiguration.containsKey('autofill') + ? AutofillInfo.fromFrameworkMessage(flutterInputConfiguration['autofill']) + : null, autofillGroup = EngineAutofillForm.fromFrameworkMessage( flutterInputConfiguration['autofill'], flutterInputConfiguration['fields']); @@ -421,10 +418,10 @@ class InputConfiguration { final EngineInputType inputType; /// The default action for the input field. - final String inputAction; + final String? inputAction; /// Whether to hide the text being edited. - final bool obscureText; + final bool? obscureText; /// Whether to enable autocorrection. /// @@ -433,15 +430,15 @@ class InputConfiguration { /// /// For future manual tests, note that autocorrect is an attribute only /// supported by Safari. - final bool autocorrect; + final bool? autocorrect; - final AutofillInfo autofill; + final AutofillInfo? autofill; - final EngineAutofillForm autofillGroup; + final EngineAutofillForm? autofillGroup; } -typedef _OnChangeCallback = void Function(EditingState editingState); -typedef _OnActionCallback = void Function(String inputAction); +typedef _OnChangeCallback = void Function(EditingState? editingState); +typedef _OnActionCallback = void Function(String? inputAction); /// Provides HTML DOM functionality for editable text. /// @@ -450,8 +447,8 @@ typedef _OnActionCallback = void Function(String inputAction); abstract class TextEditingStrategy { void initializeTextEditing( InputConfiguration inputConfig, { - @required _OnChangeCallback onChange, - @required _OnActionCallback onAction, + required _OnChangeCallback onChange, + required _OnActionCallback onAction, }); /// Sets the initial placement of the DOM element on the UI. @@ -503,7 +500,7 @@ class GloballyPositionedTextEditingStrategy extends DefaultTextEditingStrategy { void placeElement() { super.placeElement(); if (hasAutofillGroup) { - _geometry?.applyToDomElement(focusedFormElement); + _geometry?.applyToDomElement(focusedFormElement!); placeForm(); // On Chrome, when a form is focused, it opens an autofill menu // immeddiately. @@ -514,7 +511,7 @@ class GloballyPositionedTextEditingStrategy extends DefaultTextEditingStrategy { // `setEditableSizeAndTransform` method is called and focus on the form // only after placing it to the correct position. Hence autofill menu // does not appear on top-left of the page. - focusedFormElement.focus(); + focusedFormElement!.focus(); } else { _geometry?.applyToDomElement(domElement); } @@ -550,45 +547,50 @@ abstract class DefaultTextEditingStrategy implements TextEditingStrategy { @visibleForTesting bool isEnabled = false; - html.HtmlElement domElement; - InputConfiguration _inputConfiguration; - EditingState _lastEditingState; + html.HtmlElement get domElement => _domElement!; + set domElement(html.HtmlElement element) { + _domElement = element; + } + html.HtmlElement? _domElement; + + late InputConfiguration _inputConfiguration; + EditingState? _lastEditingState; /// Styles associated with the editable text. - EditableTextStyle _style; + EditableTextStyle? _style; /// Size and transform of the editable text on the page. - EditableTextGeometry _geometry; + EditableTextGeometry? _geometry; - _OnChangeCallback _onChange; - _OnActionCallback _onAction; + _OnChangeCallback? _onChange; + _OnActionCallback? _onAction; final List> _subscriptions = >[]; bool get hasAutofillGroup => _inputConfiguration.autofillGroup != null; - html.FormElement get focusedFormElement => - _inputConfiguration.autofillGroup.formElement; + html.FormElement? get focusedFormElement => + _inputConfiguration.autofillGroup?.formElement; @override void initializeTextEditing( InputConfiguration inputConfig, { - @required _OnChangeCallback onChange, - @required _OnActionCallback onAction, + required _OnChangeCallback onChange, + required _OnActionCallback onAction, }) { assert(!isEnabled); this._inputConfiguration = inputConfig; - domElement = inputConfig.inputType.createDomElement(); - if (inputConfig.obscureText) { + _domElement = inputConfig.inputType.createDomElement(); + if (inputConfig.obscureText!) { domElement.setAttribute('type', 'password'); } inputConfig.autofill?.applyToDomElement(domElement, focusedElement: true); - final String autocorrectValue = inputConfig.autocorrect ? 'on' : 'off'; + final String autocorrectValue = inputConfig.autocorrect! ? 'on' : 'off'; domElement.setAttribute('autocorrect', autocorrectValue); _setStaticStyleAttributes(domElement); @@ -598,7 +600,7 @@ abstract class DefaultTextEditingStrategy implements TextEditingStrategy { // DOM later, when the first location information arrived. // Otherwise, on Blink based Desktop browsers, the autofill menu appears // on top left of the screen. - domRenderer.glassPaneElement.append(domElement); + domRenderer.glassPaneElement!.append(domElement); } initializeElementPlacement(); @@ -617,7 +619,7 @@ abstract class DefaultTextEditingStrategy implements TextEditingStrategy { void addEventHandlers() { if (_inputConfiguration.autofillGroup != null) { _subscriptions - .addAll(_inputConfiguration.autofillGroup.addInputEventListeners()); + .addAll(_inputConfiguration.autofillGroup!.addInputEventListeners()); } // Subscribe to text and selection changes. @@ -649,7 +651,7 @@ abstract class DefaultTextEditingStrategy implements TextEditingStrategy { void updateElementStyle(EditableTextStyle style) { _style = style; if (isEnabled) { - _style.applyToDomElement(domElement); + _style!.applyToDomElement(domElement); } } @@ -667,18 +669,18 @@ abstract class DefaultTextEditingStrategy implements TextEditingStrategy { } _subscriptions.clear(); domElement.remove(); - domElement = null; + _domElement = null; _inputConfiguration.autofillGroup?.removeForm(); } @mustCallSuper @override - void setEditingState(EditingState editingState) { + void setEditingState(EditingState? editingState) { _lastEditingState = editingState; - if (!isEnabled || !editingState.isValid) { + if (!isEnabled || !editingState!.isValid) { return; } - _lastEditingState.applyToDomElement(domElement); + _lastEditingState!.applyToDomElement(domElement); } void placeElement() { @@ -686,20 +688,17 @@ abstract class DefaultTextEditingStrategy implements TextEditingStrategy { } void placeForm() { - _inputConfiguration.autofillGroup.placeForm(domElement); + _inputConfiguration.autofillGroup!.placeForm(domElement); } void _handleChange(html.Event event) { assert(isEnabled); - assert(domElement != null); EditingState newEditingState = EditingState.fromDomElement(domElement); - assert(newEditingState != null); - if (newEditingState != _lastEditingState) { _lastEditingState = newEditingState; - _onChange(_lastEditingState); + _onChange!(_lastEditingState); } } @@ -708,7 +707,7 @@ abstract class DefaultTextEditingStrategy implements TextEditingStrategy { if (_inputConfiguration.inputType.submitActionOnEnter && event.keyCode == _kReturnKeyCode) { event.preventDefault(); - _onAction(_inputConfiguration.inputAction); + _onAction!(_inputConfiguration.inputAction); } } } @@ -723,8 +722,8 @@ abstract class DefaultTextEditingStrategy implements TextEditingStrategy { /// - Selection changes. void enable( InputConfiguration inputConfig, { - @required _OnChangeCallback onChange, - @required _OnActionCallback onAction, + required _OnChangeCallback onChange, + required _OnActionCallback onAction, }) { assert(!isEnabled); @@ -788,7 +787,7 @@ class IOSTextEditingStrategy extends GloballyPositionedTextEditingStrategy { /// focus is called we are positioning it offscreen. The location of the input /// in iOS is set to correct place, 100ms after focus. We use this timer for /// timing this delay. - Timer _positionInputElementTimer; + Timer? _positionInputElementTimer; static const Duration _delayBeforePlacement = const Duration(milliseconds: 100); @@ -808,8 +807,8 @@ class IOSTextEditingStrategy extends GloballyPositionedTextEditingStrategy { @override void initializeTextEditing( InputConfiguration inputConfig, { - @required _OnChangeCallback onChange, - @required _OnActionCallback onAction, + required _OnChangeCallback onChange, + required _OnActionCallback onAction, }) { super.initializeTextEditing(inputConfig, onChange: onChange, onAction: onAction); @@ -817,7 +816,7 @@ class IOSTextEditingStrategy extends GloballyPositionedTextEditingStrategy { if (hasAutofillGroup) { placeForm(); } else { - domRenderer.glassPaneElement.append(domElement); + domRenderer.glassPaneElement!.append(domElement); } } @@ -835,7 +834,7 @@ class IOSTextEditingStrategy extends GloballyPositionedTextEditingStrategy { void addEventHandlers() { if (_inputConfiguration.autofillGroup != null) { _subscriptions - .addAll(_inputConfiguration.autofillGroup.addInputEventListeners()); + .addAll(_inputConfiguration.autofillGroup!.addInputEventListeners()); } // Subscribe to text and selection changes. @@ -938,8 +937,8 @@ class AndroidTextEditingStrategy extends GloballyPositionedTextEditingStrategy { @override void initializeTextEditing( InputConfiguration inputConfig, { - @required _OnChangeCallback onChange, - @required _OnActionCallback onAction, + required _OnChangeCallback onChange, + required _OnActionCallback onAction, }) { super.initializeTextEditing(inputConfig, onChange: onChange, onAction: onAction); @@ -947,7 +946,7 @@ class AndroidTextEditingStrategy extends GloballyPositionedTextEditingStrategy { if (hasAutofillGroup) { placeForm(); } else { - domRenderer.glassPaneElement.append(domElement); + domRenderer.glassPaneElement!.append(domElement); } } @@ -955,7 +954,7 @@ class AndroidTextEditingStrategy extends GloballyPositionedTextEditingStrategy { void addEventHandlers() { if (_inputConfiguration.autofillGroup != null) { _subscriptions - .addAll(_inputConfiguration.autofillGroup.addInputEventListeners()); + .addAll(_inputConfiguration.autofillGroup!.addInputEventListeners()); } // Subscribe to text and selection changes. @@ -966,7 +965,7 @@ class AndroidTextEditingStrategy extends GloballyPositionedTextEditingStrategy { _subscriptions.add(html.document.onSelectionChange.listen(_handleChange)); _subscriptions.add(domElement.onBlur.listen((_) { - if (domRenderer.windowHasFocus) { + if (domRenderer.windowHasFocus!) { // Chrome on Android will hide the onscreen keyboard when you tap outside // the text box. Instead, we want the framework to tell us to hide the // keyboard via `TextInput.clearClient` or `TextInput.hide`. Therefore @@ -995,15 +994,15 @@ class FirefoxTextEditingStrategy extends GloballyPositionedTextEditingStrategy { @override void initializeTextEditing( InputConfiguration inputConfig, { - @required _OnChangeCallback onChange, - @required _OnActionCallback onAction, + required _OnChangeCallback onChange, + required _OnActionCallback onAction, }) { super.initializeTextEditing(inputConfig, onChange: onChange, onAction: onAction); if (hasAutofillGroup) { placeForm(); } else { - domRenderer.glassPaneElement.append(domElement); + domRenderer.glassPaneElement!.append(domElement); } } @@ -1011,7 +1010,7 @@ class FirefoxTextEditingStrategy extends GloballyPositionedTextEditingStrategy { void addEventHandlers() { if (_inputConfiguration.autofillGroup != null) { _subscriptions - .addAll(_inputConfiguration.autofillGroup.addInputEventListeners()); + .addAll(_inputConfiguration.autofillGroup!.addInputEventListeners()); } // Subscribe to text and selection changes. @@ -1069,7 +1068,7 @@ class TextEditingChannel { /// Handles "flutter/textinput" platform messages received from the framework. void handleTextInput( - ByteData data, ui.PlatformMessageResponseCallback callback) { + ByteData? data, ui.PlatformMessageResponseCallback? callback) { const JSONMethodCodec codec = JSONMethodCodec(); final MethodCall call = codec.decodeMethodCall(data); switch (call.method) { @@ -1120,14 +1119,14 @@ class TextEditingChannel { } /// Sends the 'TextInputClient.updateEditingState' message to the framework. - void updateEditingState(int clientId, EditingState editingState) { + void updateEditingState(int? clientId, EditingState? editingState) { if (window._onPlatformMessage != null) { window.invokeOnPlatformMessage( 'flutter/textinput', const JSONMethodCodec().encodeMethodCall( MethodCall('TextInputClient.updateEditingState', [ clientId, - editingState.toFlutter(), + editingState!.toFlutter(), ]), ), _emptyCallback, @@ -1136,7 +1135,7 @@ class TextEditingChannel { } /// Sends the 'TextInputClient.performAction' message to the framework. - void performAction(int clientId, String inputAction) { + void performAction(int? clientId, String? inputAction) { if (window._onPlatformMessage != null) { window.invokeOnPlatformMessage( 'flutter/textinput', @@ -1152,7 +1151,7 @@ class TextEditingChannel { } /// Sends the 'TextInputClient.onConnectionClosed' message to the framework. - void onConnectionClosed(int clientId) { + void onConnectionClosed(int? clientId) { if (window._onPlatformMessage != null) { window.invokeOnPlatformMessage( 'flutter/textinput', @@ -1199,22 +1198,22 @@ class HybridTextEditing { channel = TextEditingChannel(this); } - TextEditingChannel channel; + late TextEditingChannel channel; /// The text editing stategy used. It can change depending on the /// formfactor/browser. /// /// It uses an HTML element to manage editing state when a custom element is /// not provided via [useCustomEditableElement] - DefaultTextEditingStrategy _defaultEditingElement; + DefaultTextEditingStrategy? _defaultEditingElement; /// The HTML element used to manage editing state. /// /// This field is populated using [useCustomEditableElement]. If `null` the /// [_defaultEditingElement] is used instead. - DefaultTextEditingStrategy _customEditingElement; + DefaultTextEditingStrategy? _customEditingElement; - DefaultTextEditingStrategy get editingElement { + DefaultTextEditingStrategy? get editingElement { if (_customEditingElement != null) { return _customEditingElement; } @@ -1222,7 +1221,7 @@ class HybridTextEditing { } /// Responds to the 'TextInput.setClient' message. - void setClient(int clientId, InputConfiguration configuration) { + void setClient(int? clientId, InputConfiguration configuration) { final bool clientIdChanged = _clientId != null && _clientId != clientId; if (clientIdChanged && isEditing) { stopEditing(); @@ -1233,7 +1232,7 @@ class HybridTextEditing { /// Responds to the 'TextInput.setEditingState' message. void setEditingState(EditingState state) { - editingElement.setEditingState(state); + editingElement!.setEditingState(state); } /// Responds to the 'TextInput.show' message. @@ -1245,12 +1244,12 @@ class HybridTextEditing { /// Responds to the 'TextInput.setEditableSizeAndTransform' message. void setEditableSizeAndTransform(EditableTextGeometry geometry) { - editingElement.updateElementPlacement(geometry); + editingElement!.updateElementPlacement(geometry); } /// Responds to the 'TextInput.setStyle' message. void setStyle(EditableTextStyle style) { - editingElement.updateElementStyle(style); + editingElement!.updateElementStyle(style); } /// Responds to the 'TextInput.clearClient' message. @@ -1279,7 +1278,7 @@ class HybridTextEditing { /// /// Use [stopUsingCustomEditableElement] to switch back to default element. void useCustomEditableElement( - DefaultTextEditingStrategy customEditingElement) { + DefaultTextEditingStrategy? customEditingElement) { if (isEditing && customEditingElement != _customEditingElement) { stopEditing(); } @@ -1292,7 +1291,7 @@ class HybridTextEditing { useCustomEditableElement(null); } - int _clientId; + int? _clientId; /// Flag which shows if there is an ongoing editing. /// @@ -1300,17 +1299,17 @@ class HybridTextEditing { @visibleForTesting bool isEditing = false; - InputConfiguration _configuration; + late InputConfiguration _configuration; void _startEditing() { assert(!isEditing); isEditing = true; - editingElement.enable( + editingElement!.enable( _configuration, - onChange: (EditingState editingState) { + onChange: (EditingState? editingState) { channel.updateEditingState(_clientId, editingState); }, - onAction: (String inputAction) { + onAction: (String? inputAction) { channel.performAction(_clientId, inputAction); }, ); @@ -1319,7 +1318,7 @@ class HybridTextEditing { void stopEditing() { assert(isEditing); isEditing = false; - editingElement.disable(); + editingElement!.disable(); } void sendTextConnectionClosedToFrameworkIfAny() { @@ -1335,11 +1334,11 @@ class HybridTextEditing { /// This information is received via TextInput.setStyle message. class EditableTextStyle { EditableTextStyle({ - @required this.textDirection, - @required this.fontSize, - @required this.textAlign, - @required this.fontFamily, - @required this.fontWeight, + required this.textDirection, + required this.fontSize, + required this.textAlign, + required this.fontFamily, + required this.fontWeight, }); factory EditableTextStyle.fromFrameworkMessage( @@ -1351,7 +1350,7 @@ class EditableTextStyle { final int textAlignIndex = flutterStyle['textAlignIndex']; final int textDirectionIndex = flutterStyle['textDirectionIndex']; - final int fontWeightIndex = flutterStyle['fontWeightIndex']; + final int? fontWeightIndex = flutterStyle['fontWeightIndex']; // Convert [fontWeightIndex] to its CSS equivalent value. final String fontWeight = fontWeightIndex != null @@ -1372,13 +1371,13 @@ class EditableTextStyle { /// This information will be used for changing the style of the hidden input /// element, which will match it's size to the size of the editable widget. - final double fontSize; + final double? fontSize; final String fontWeight; - final String fontFamily; + final String? fontFamily; final ui.TextAlign textAlign; final ui.TextDirection textDirection; - String get align => textAlignToCssValue(textAlign, textDirection); + String? get align => textAlignToCssValue(textAlign, textDirection); String get cssFont => '${fontWeight} ${fontSize}px ${fontFamily}'; @@ -1396,9 +1395,9 @@ class EditableTextStyle { @immutable class EditableTextGeometry { EditableTextGeometry({ - @required this.width, - @required this.height, - @required this.globalTransform, + required this.width, + required this.height, + required this.globalTransform, }); /// Parses the geometry from a message sent by the framework. diff --git a/lib/web_ui/lib/src/engine/util.dart b/lib/web_ui/lib/src/engine/util.dart index 1f4e5c386aab5..67f991eccadb2 100644 --- a/lib/web_ui/lib/src/engine/util.dart +++ b/lib/web_ui/lib/src/engine/util.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// Generic callback signature, used by [_futurize]. @@ -12,7 +12,7 @@ typedef Callback = void Function(T result); /// /// Return value should be null on success, and a string error message on /// failure. -typedef Callbacker = String/*?*/ Function(Callback callback); +typedef Callbacker = String? Function(Callback callback); /// Converts a method that receives a value-returning callback to a method that /// returns a Future. @@ -35,9 +35,9 @@ typedef Callbacker = String/*?*/ Function(Callback callback); /// return _futurize(_doSomethingAndCallback); /// } /// ``` -Future/*!*/ futurize(Callbacker callbacker) { +Future futurize(Callbacker callbacker) { final Completer completer = Completer.sync(); - final String error = callbacker((T t) { + final String? error = callbacker((T t) { if (t == null) { completer.completeError(Exception('operation failed')); } else { @@ -319,13 +319,13 @@ String _pathToSvgClipPath(ui.Path path, sb.write(''); sb.write(' operatingSystem == OperatingSystem.iOs || /// /// If the given [fontFamily] is a generic font-family, then just return it. /// Otherwise, wrap the family name in quotes and add a fallback font family. -String canonicalizeFontFamily(String fontFamily) { +String? canonicalizeFontFamily(String? fontFamily) { if (_genericFontFamilies.contains(fontFamily)) { return fontFamily; } @@ -449,9 +449,6 @@ String canonicalizeFontFamily(String fontFamily) { /// Converts a list of [Offset] to a typed array of floats. Float32List offsetListToFloat32List(List offsetList) { - if (offsetList == null) { - return null; - } final int length = offsetList.length; final floatList = Float32List(length * 2); for (int i = 0, destIndex = 0; i < length; i++, destIndex += 2) { @@ -471,13 +468,13 @@ Float32List offsetListToFloat32List(List offsetList) { /// /// * Use 3D transform instead of 2D: this does not work because it causes text /// blurriness: https://github.com/flutter/flutter/issues/32274 -void applyWebkitClipFix(html.Element containerElement) { +void applyWebkitClipFix(html.Element? containerElement) { if (browserEngine == BrowserEngine.webkit) { - containerElement.style.zIndex = '0'; + containerElement!.style.zIndex = '0'; } } -final ByteData _fontChangeMessage = JSONMessageCodec().encodeMessage({'type': 'fontsChange'}); +final ByteData? _fontChangeMessage = JSONMessageCodec().encodeMessage({'type': 'fontsChange'}); // Font load callbacks will typically arrive in sequence, we want to prevent // sendFontChangeMessage of causing multiple synchronous rebuilds. @@ -520,3 +517,13 @@ class _FastMatrix64 { double convertSigmaToRadius(double sigma) { return sigma * 2.0; } + +/// Used to check for null values that are non-nullable. +/// +/// This is useful when some external API (e.g. HTML DOM) disagrees with +/// Dart type declarations (e.g. `dart:html`). Where `dart:html` may believe +/// something to be non-null, it may actually be null (e.g. old browsers do +/// not implement a feature, such as clipboard). +bool isUnsoundNull(dynamic object) { + return object == null; +} diff --git a/lib/web_ui/lib/src/engine/validators.dart b/lib/web_ui/lib/src/engine/validators.dart index ec1c0bb5a999c..243e1326c9009 100644 --- a/lib/web_ui/lib/src/engine/validators.dart +++ b/lib/web_ui/lib/src/engine/validators.dart @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; bool rectIsValid(ui.Rect rect) { - assert(rect != null, 'Rect argument was null.'); + assert(rect != null, 'Rect argument was null.'); // ignore: unnecessary_null_comparison assert( !(rect.left.isNaN || rect.right.isNaN || @@ -17,7 +17,7 @@ bool rectIsValid(ui.Rect rect) { } bool rrectIsValid(ui.RRect rrect) { - assert(rrect != null, 'RRect argument was null.'); + assert(rrect != null, 'RRect argument was null.'); // ignore: unnecessary_null_comparison assert( !(rrect.left.isNaN || rrect.right.isNaN || @@ -28,20 +28,20 @@ bool rrectIsValid(ui.RRect rrect) { } bool offsetIsValid(ui.Offset offset) { - assert(offset != null, 'Offset argument was null.'); + assert(offset != null, 'Offset argument was null.'); // ignore: unnecessary_null_comparison assert(!offset.dx.isNaN && !offset.dy.isNaN, 'Offset argument contained a NaN value.'); return true; } bool matrix4IsValid(Float32List matrix4) { - assert(matrix4 != null, 'Matrix4 argument was null.'); + assert(matrix4 != null, 'Matrix4 argument was null.'); // ignore: unnecessary_null_comparison assert(matrix4.length == 16, 'Matrix4 must have 16 entries.'); return true; } bool radiusIsValid(ui.Radius radius) { - assert(radius != null, 'Radius argument was null.'); + assert(radius != null, 'Radius argument was null.'); // ignore: unnecessary_null_comparison assert(!radius.x.isNaN && !radius.y.isNaN, 'Radius argument contained a NaN value.'); return true; diff --git a/lib/web_ui/lib/src/engine/vector_math.dart b/lib/web_ui/lib/src/engine/vector_math.dart index 721e4ed3c9004..9dfe164091605 100644 --- a/lib/web_ui/lib/src/engine/vector_math.dart +++ b/lib/web_ui/lib/src/engine/vector_math.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 part of engine; class Matrix4 { @@ -13,7 +12,7 @@ class Matrix4 { /// Returns a matrix that is the inverse of [other] if [other] is invertible, /// otherwise `null`. - static Matrix4 tryInvert(Matrix4 other) { + static Matrix4? tryInvert(Matrix4 other) { final Matrix4 r = Matrix4.zero(); final double determinant = r.copyInverse(other); if (determinant == 0.0) { @@ -243,7 +242,7 @@ class Matrix4 { } /// Scale this matrix by a [Vector3], [Vector4], or x,y,z - void scale(double x, [double y, double z]) { + void scale(double x, [double? y, double? z]) { final double sx = x; final double sy = y ?? x; final double sz = z ?? x; @@ -268,7 +267,7 @@ class Matrix4 { /// Create a copy of [this] scaled by a [Vector3], [Vector4] or [x],[y], and /// [z]. - Matrix4 scaled(double x, [double y, double z]) => clone()..scale(x, y, z); + Matrix4 scaled(double x, [double? y, double? z]) => clone()..scale(x, y, z); /// Zeros [this]. void setZero() { @@ -963,7 +962,7 @@ class Matrix4 { /// Rotate a copy of [arg] of type [Vector3] using the rotation defined by /// [this]. If a [out] parameter is supplied, the copy is stored in [out]. - Vector3 rotated3(Vector3 arg, [Vector3 out]) { + Vector3 rotated3(Vector3 arg, [Vector3? out]) { if (out == null) { out = Vector3.copy(arg); } else { @@ -1132,7 +1131,7 @@ class Vector3 { /// Generate random vector in the range (0, 0, 0) to (1, 1, 1). You can /// optionally pass your own random number generator. - factory Vector3.random([math.Random rng]) { + factory Vector3.random([math.Random? rng]) { rng ??= math.Random(); return Vector3(rng.nextDouble(), rng.nextDouble(), rng.nextDouble()); } diff --git a/lib/web_ui/lib/src/engine/web_experiments.dart b/lib/web_ui/lib/src/engine/web_experiments.dart index 2e2050938e8df..34e7047e21e27 100644 --- a/lib/web_ui/lib/src/engine/web_experiments.dart +++ b/lib/web_ui/lib/src/engine/web_experiments.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 part of engine; /// A bag of all experiment flags in the web engine. @@ -18,35 +17,34 @@ class WebExperiments { } static WebExperiments ensureInitialized() { - if (WebExperiments.instance == null) { - WebExperiments.instance = WebExperiments._(); - } - return WebExperiments.instance; + return WebExperiments.instance ?? (WebExperiments.instance = WebExperiments._()); } - static WebExperiments instance; + static WebExperiments? instance; /// Experiment flag for using canvas-based text measurement. - bool get useCanvasText => _useCanvasText ?? false; - set useCanvasText(bool enabled) { - _useCanvasText = enabled; + bool get useCanvasText => _useCanvasText; + set useCanvasText(bool? enabled) { + _useCanvasText = enabled ?? _defaultUseCanvasText; } - bool _useCanvasText = const bool.fromEnvironment( + static const bool _defaultUseCanvasText = const bool.fromEnvironment( 'FLUTTER_WEB_USE_EXPERIMENTAL_CANVAS_TEXT', - defaultValue: null, + defaultValue: false, ); + bool _useCanvasText = _defaultUseCanvasText; + /// Reset all experimental flags to their default values. void reset() { - _useCanvasText = null; + _useCanvasText = _defaultUseCanvasText; } /// Used to enable/disable experimental flags in the web engine. void updateExperiment(String name, bool enabled) { switch (name) { case 'useCanvasText': - _useCanvasText = enabled; + useCanvasText = enabled; break; } } diff --git a/lib/web_ui/lib/src/engine/window.dart b/lib/web_ui/lib/src/engine/window.dart index dc764de1e76ee..9c76e50c80dba 100644 --- a/lib/web_ui/lib/src/engine/window.dart +++ b/lib/web_ui/lib/src/engine/window.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.6 + part of engine; /// When set to true, all platform messages will be printed to the console. @@ -11,7 +11,7 @@ const bool _debugPrintPlatformMessages = false; /// Requests that the browser schedule a frame. /// /// This may be overridden in tests, for example, to pump fake frames. -ui.VoidCallback scheduleFrameCallback; +ui.VoidCallback? scheduleFrameCallback; /// The Web implementation of [ui.Window]. class EngineWindow extends ui.Window { @@ -26,14 +26,12 @@ class EngineWindow extends ui.Window { } @override - double get devicePixelRatio => _debugDevicePixelRatio != null - ? _debugDevicePixelRatio - : browserDevicePixelRatio; + double get devicePixelRatio => _debugDevicePixelRatio ?? browserDevicePixelRatio; /// Returns device pixel ratio returned by browser. static double get browserDevicePixelRatio { - double ratio = html.window.devicePixelRatio; - // Guard against WebOS returning 0. + double? ratio = html.window.devicePixelRatio as double?; + // Guard against WebOS returning 0 and other browsers returning null. return (ratio == null || ratio == 0.0) ? 1.0 : ratio; } @@ -44,7 +42,7 @@ class EngineWindow extends ui.Window { _debugDevicePixelRatio = value; } - double _debugDevicePixelRatio; + double? _debugDevicePixelRatio; @override ui.Size get physicalSize { @@ -52,7 +50,7 @@ class EngineWindow extends ui.Window { _computePhysicalSize(); } assert(_physicalSize != null); - return _physicalSize; + return _physicalSize!; } /// Computes the physical size of the screen from [html.window]. @@ -73,10 +71,10 @@ class EngineWindow extends ui.Window { if (!override) { double windowInnerWidth; double windowInnerHeight; - final html.VisualViewport viewport = html.window.visualViewport; + final html.VisualViewport? viewport = html.window.visualViewport; if (viewport != null) { - windowInnerWidth = viewport.width * devicePixelRatio; - windowInnerHeight = viewport.height * devicePixelRatio; + windowInnerWidth = viewport.width * devicePixelRatio as double; + windowInnerHeight = viewport.height * devicePixelRatio as double; } else { windowInnerWidth = html.window.innerWidth * devicePixelRatio; windowInnerHeight = html.window.innerHeight * devicePixelRatio; @@ -90,13 +88,13 @@ class EngineWindow extends ui.Window { void computeOnScreenKeyboardInsets() { double windowInnerHeight; - final html.VisualViewport viewport = html.window.visualViewport; + final html.VisualViewport? viewport = html.window.visualViewport; if (viewport != null) { - windowInnerHeight = viewport.height * devicePixelRatio; + windowInnerHeight = viewport.height * devicePixelRatio as double; } else { windowInnerHeight = html.window.innerHeight * devicePixelRatio; } - final double bottomPadding = _physicalSize.height - windowInnerHeight; + final double bottomPadding = _physicalSize!.height - windowInnerHeight; _viewInsets = WindowPadding(bottom: bottomPadding, left: 0, right: 0, top: 0); } @@ -119,18 +117,18 @@ class EngineWindow extends ui.Window { double height = 0; double width = 0; if (html.window.visualViewport != null) { - height = html.window.visualViewport.height * devicePixelRatio; - width = html.window.visualViewport.width * devicePixelRatio; + height = html.window.visualViewport!.height * devicePixelRatio as double; + width = html.window.visualViewport!.width * devicePixelRatio as double; } else { height = html.window.innerHeight * devicePixelRatio; width = html.window.innerWidth * devicePixelRatio; } // First confirm both heught and width is effected. - if (_physicalSize.height != height && _physicalSize.width != width) { + if (_physicalSize!.height != height && _physicalSize!.width != width) { // If prior to rotation height is bigger than width it should be the // opposite after the rotation and vice versa. - if ((_physicalSize.height > _physicalSize.width && height < width) || - (_physicalSize.width > _physicalSize.height && width < height)) { + if ((_physicalSize!.height > _physicalSize!.width && height < width) || + (_physicalSize!.width > _physicalSize!.height && width < height)) { // Rotation detected return true; } @@ -140,13 +138,13 @@ class EngineWindow extends ui.Window { @override WindowPadding get viewInsets => _viewInsets; - WindowPadding _viewInsets = ui.WindowPadding.zero; + WindowPadding _viewInsets = ui.WindowPadding.zero as WindowPadding; /// Lazily populated and cleared at the end of the frame. - ui.Size _physicalSize; + ui.Size? _physicalSize; /// Overrides the value of [physicalSize] in tests. - ui.Size webOnlyDebugPhysicalSizeOverride; + ui.Size? webOnlyDebugPhysicalSizeOverride; @override double get physicalDepth => double.maxFinite; @@ -162,10 +160,10 @@ class EngineWindow extends ui.Window { /// /// The reason for the lazy initialization is to give enough time for the app to set [locationStrategy] /// in `lib/src/ui/initialization.dart`. - String _defaultRouteName; + String? _defaultRouteName; @override - String/*!*/ get defaultRouteName => _defaultRouteName ??= _browserHistory.currentPath; + String get defaultRouteName => _defaultRouteName ??= _browserHistory.currentPath; @override void scheduleFrame() { @@ -173,27 +171,27 @@ class EngineWindow extends ui.Window { throw new Exception( 'scheduleFrameCallback must be initialized first.'); } - scheduleFrameCallback(); + scheduleFrameCallback!(); } /// Change the strategy to use for handling browser history location. /// Setting this member will automatically update [_browserHistory]. /// /// By setting this to null, the browser history will be disabled. - set locationStrategy(LocationStrategy strategy) { + set locationStrategy(LocationStrategy? strategy) { _browserHistory.locationStrategy = strategy; } /// Returns the currently active location strategy. @visibleForTesting - LocationStrategy get locationStrategy => _browserHistory.locationStrategy; + LocationStrategy? get locationStrategy => _browserHistory.locationStrategy; @override - ui.VoidCallback get onTextScaleFactorChanged => _onTextScaleFactorChanged; - ui.VoidCallback _onTextScaleFactorChanged; - Zone _onTextScaleFactorChangedZone; + ui.VoidCallback? get onTextScaleFactorChanged => _onTextScaleFactorChanged; + ui.VoidCallback? _onTextScaleFactorChanged; + Zone? _onTextScaleFactorChangedZone; @override - set onTextScaleFactorChanged(ui.VoidCallback callback) { + set onTextScaleFactorChanged(ui.VoidCallback? callback) { _onTextScaleFactorChanged = callback; _onTextScaleFactorChangedZone = Zone.current; } @@ -205,12 +203,12 @@ class EngineWindow extends ui.Window { } @override - ui.VoidCallback get onPlatformBrightnessChanged => + ui.VoidCallback? get onPlatformBrightnessChanged => _onPlatformBrightnessChanged; - ui.VoidCallback _onPlatformBrightnessChanged; - Zone _onPlatformBrightnessChangedZone; + ui.VoidCallback? _onPlatformBrightnessChanged; + Zone? _onPlatformBrightnessChangedZone; @override - set onPlatformBrightnessChanged(ui.VoidCallback callback) { + set onPlatformBrightnessChanged(ui.VoidCallback? callback) { _onPlatformBrightnessChanged = callback; _onPlatformBrightnessChangedZone = Zone.current; } @@ -222,11 +220,11 @@ class EngineWindow extends ui.Window { } @override - ui.VoidCallback/*?*/ get onMetricsChanged => _onMetricsChanged; - ui.VoidCallback/*?*/ _onMetricsChanged; - Zone/*!*/ _onMetricsChangedZone = Zone.root; + ui.VoidCallback? get onMetricsChanged => _onMetricsChanged; + ui.VoidCallback? _onMetricsChanged; + Zone _onMetricsChangedZone = Zone.root; @override - set onMetricsChanged(ui.VoidCallback callback) { + set onMetricsChanged(ui.VoidCallback? callback) { _onMetricsChanged = callback; _onMetricsChangedZone = Zone.current; } @@ -240,11 +238,11 @@ class EngineWindow extends ui.Window { } @override - ui.VoidCallback get onLocaleChanged => _onLocaleChanged; - ui.VoidCallback _onLocaleChanged; - Zone _onLocaleChangedZone; + ui.VoidCallback? get onLocaleChanged => _onLocaleChanged; + ui.VoidCallback? _onLocaleChanged; + Zone? _onLocaleChangedZone; @override - set onLocaleChanged(ui.VoidCallback callback) { + set onLocaleChanged(ui.VoidCallback? callback) { _onLocaleChanged = callback; _onLocaleChangedZone = Zone.current; } @@ -261,11 +259,11 @@ class EngineWindow extends ui.Window { /// * https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/languages, /// which explains browser quirks in the implementation notes. @override - ui.Locale get locale => _locales.first; + ui.Locale get locale => _locales!.first; @override - List get locales => _locales; - List _locales = parseBrowserLanguages(); + List? get locales => _locales; + List? _locales = parseBrowserLanguages(); /// Sets locales to `null`. /// @@ -310,11 +308,11 @@ class EngineWindow extends ui.Window { } @override - ui.FrameCallback get onBeginFrame => _onBeginFrame; - ui.FrameCallback _onBeginFrame; - Zone _onBeginFrameZone; + ui.FrameCallback? get onBeginFrame => _onBeginFrame; + ui.FrameCallback? _onBeginFrame; + Zone? _onBeginFrameZone; @override - set onBeginFrame(ui.FrameCallback callback) { + set onBeginFrame(ui.FrameCallback? callback) { _onBeginFrame = callback; _onBeginFrameZone = Zone.current; } @@ -326,11 +324,11 @@ class EngineWindow extends ui.Window { } @override - ui.TimingsCallback get onReportTimings => _onReportTimings; - ui.TimingsCallback _onReportTimings; - Zone _onReportTimingsZone; + ui.TimingsCallback? get onReportTimings => _onReportTimings; + ui.TimingsCallback? _onReportTimings; + Zone? _onReportTimingsZone; @override - set onReportTimings(ui.TimingsCallback callback) { + set onReportTimings(ui.TimingsCallback? callback) { _onReportTimings = callback; _onReportTimingsZone = Zone.current; } @@ -343,11 +341,11 @@ class EngineWindow extends ui.Window { } @override - ui.VoidCallback get onDrawFrame => _onDrawFrame; - ui.VoidCallback _onDrawFrame; - Zone _onDrawFrameZone; + ui.VoidCallback? get onDrawFrame => _onDrawFrame; + ui.VoidCallback? _onDrawFrame; + Zone? _onDrawFrameZone; @override - set onDrawFrame(ui.VoidCallback callback) { + set onDrawFrame(ui.VoidCallback? callback) { _onDrawFrame = callback; _onDrawFrameZone = Zone.current; } @@ -359,11 +357,11 @@ class EngineWindow extends ui.Window { } @override - ui.PointerDataPacketCallback get onPointerDataPacket => _onPointerDataPacket; - ui.PointerDataPacketCallback _onPointerDataPacket; - Zone _onPointerDataPacketZone; + ui.PointerDataPacketCallback? get onPointerDataPacket => _onPointerDataPacket; + ui.PointerDataPacketCallback? _onPointerDataPacket; + Zone? _onPointerDataPacketZone; @override - set onPointerDataPacket(ui.PointerDataPacketCallback callback) { + set onPointerDataPacket(ui.PointerDataPacketCallback? callback) { _onPointerDataPacket = callback; _onPointerDataPacketZone = Zone.current; } @@ -376,11 +374,11 @@ class EngineWindow extends ui.Window { } @override - ui.VoidCallback get onSemanticsEnabledChanged => _onSemanticsEnabledChanged; - ui.VoidCallback _onSemanticsEnabledChanged; - Zone _onSemanticsEnabledChangedZone; + ui.VoidCallback? get onSemanticsEnabledChanged => _onSemanticsEnabledChanged; + ui.VoidCallback? _onSemanticsEnabledChanged; + Zone? _onSemanticsEnabledChangedZone; @override - set onSemanticsEnabledChanged(ui.VoidCallback callback) { + set onSemanticsEnabledChanged(ui.VoidCallback? callback) { _onSemanticsEnabledChanged = callback; _onSemanticsEnabledChangedZone = Zone.current; } @@ -392,11 +390,11 @@ class EngineWindow extends ui.Window { } @override - ui.SemanticsActionCallback get onSemanticsAction => _onSemanticsAction; - ui.SemanticsActionCallback _onSemanticsAction; - Zone _onSemanticsActionZone; + ui.SemanticsActionCallback? get onSemanticsAction => _onSemanticsAction; + ui.SemanticsActionCallback? _onSemanticsAction; + Zone? _onSemanticsActionZone; @override - set onSemanticsAction(ui.SemanticsActionCallback callback) { + set onSemanticsAction(ui.SemanticsActionCallback? callback) { _onSemanticsAction = callback; _onSemanticsActionZone = Zone.current; } @@ -404,18 +402,18 @@ class EngineWindow extends ui.Window { /// Engine code should use this method instead of the callback directly. /// Otherwise zones won't work properly. void invokeOnSemanticsAction( - int id, ui.SemanticsAction action, ByteData args) { - _invoke3( + int id, ui.SemanticsAction action, ByteData? args) { + _invoke3( _onSemanticsAction, _onSemanticsActionZone, id, action, args); } @override - ui.VoidCallback get onAccessibilityFeaturesChanged => + ui.VoidCallback? get onAccessibilityFeaturesChanged => _onAccessibilityFeaturesChanged; - ui.VoidCallback _onAccessibilityFeaturesChanged; - Zone _onAccessibilityFeaturesChangedZone; + ui.VoidCallback? _onAccessibilityFeaturesChanged; + Zone? _onAccessibilityFeaturesChangedZone; @override - set onAccessibilityFeaturesChanged(ui.VoidCallback callback) { + set onAccessibilityFeaturesChanged(ui.VoidCallback? callback) { _onAccessibilityFeaturesChanged = callback; _onAccessibilityFeaturesChangedZone = Zone.current; } @@ -428,11 +426,11 @@ class EngineWindow extends ui.Window { } @override - ui.PlatformMessageCallback get onPlatformMessage => _onPlatformMessage; - ui.PlatformMessageCallback _onPlatformMessage; - Zone _onPlatformMessageZone; + ui.PlatformMessageCallback? get onPlatformMessage => _onPlatformMessage; + ui.PlatformMessageCallback? _onPlatformMessage; + Zone? _onPlatformMessageZone; @override - set onPlatformMessage(ui.PlatformMessageCallback callback) { + set onPlatformMessage(ui.PlatformMessageCallback? callback) { _onPlatformMessage = callback; _onPlatformMessageZone = Zone.current; } @@ -440,8 +438,8 @@ class EngineWindow extends ui.Window { /// Engine code should use this method instead of the callback directly. /// Otherwise zones won't work properly. void invokeOnPlatformMessage( - String name, ByteData data, ui.PlatformMessageResponseCallback callback) { - _invoke3( + String name, ByteData? data, ui.PlatformMessageResponseCallback callback) { + _invoke3( _onPlatformMessage, _onPlatformMessageZone, name, @@ -452,9 +450,9 @@ class EngineWindow extends ui.Window { @override void sendPlatformMessage( - String/*!*/ name, - ByteData/*?*/ data, - ui.PlatformMessageResponseCallback/*?*/ callback, + String name, + ByteData? data, + ui.PlatformMessageResponseCallback? callback, ) { _sendPlatformMessage( name, data, _zonedPlatformMessageResponseCallback(callback)); @@ -462,7 +460,7 @@ class EngineWindow extends ui.Window { /// Wraps the given [callback] in another callback that ensures that the /// original callback is called in the zone it was registered in. - static ui.PlatformMessageResponseCallback/*?*/ _zonedPlatformMessageResponseCallback(ui.PlatformMessageResponseCallback/*?*/ callback) { + static ui.PlatformMessageResponseCallback? _zonedPlatformMessageResponseCallback(ui.PlatformMessageResponseCallback? callback) { if (callback == null) { return null; } @@ -470,15 +468,15 @@ class EngineWindow extends ui.Window { // Store the zone in which the callback is being registered. final Zone registrationZone = Zone.current; - return (ByteData data) { + return (ByteData? data) { registrationZone.runUnaryGuarded(callback, data); }; } void _sendPlatformMessage( - String/*!*/ name, - ByteData/*?*/ data, - ui.PlatformMessageResponseCallback/*?*/ callback, + String name, + ByteData? data, + ui.PlatformMessageResponseCallback? callback, ) { // In widget tests we want to bypass processing of platform messages. if (assertionsEnabled && ui.debugEmulateFlutterTesterEnvironment) { @@ -497,8 +495,8 @@ class EngineWindow extends ui.Window { switch (name) { case 'flutter/assets': - assert(ui.webOnlyAssetManager != null); - final String url = utf8.decode(data.buffer.asUint8List()); + assert(ui.webOnlyAssetManager != null); // ignore: unnecessary_null_comparison + final String url = utf8.decode(data!.buffer.asUint8List()); ui.webOnlyAssetManager.load(url).then((ByteData assetData) { _replyToPlatformMessage(callback, assetData); }, onError: (dynamic error) { @@ -519,7 +517,7 @@ class EngineWindow extends ui.Window { }); return; case 'HapticFeedback.vibrate': - final String type = decoded.arguments; + final String? type = decoded.arguments; domRenderer.vibrate(_getHapticFeedbackDuration(type)); _replyToPlatformMessage( callback, codec.encodeSuccessEnvelope(true)); @@ -532,7 +530,7 @@ class EngineWindow extends ui.Window { callback, codec.encodeSuccessEnvelope(true)); return; case 'SystemChrome.setPreferredOrientations': - final List arguments = decoded.arguments; + final List? arguments = decoded.arguments; domRenderer.setPreferredOrientation(arguments).then((bool success) { _replyToPlatformMessage(callback, codec.encodeSuccessEnvelope(success)); @@ -559,10 +557,10 @@ class EngineWindow extends ui.Window { case 'flutter/mousecursor': const MethodCodec codec = StandardMethodCodec(); final MethodCall decoded = codec.decodeMethodCall(data); - final Map arguments = decoded.arguments; + final Map? arguments = decoded.arguments; switch (decoded.method) { case 'activateSystemCursor': - MouseCursor.instance.activateSystemCursor(arguments['kind']); + MouseCursor.instance!.activateSystemCursor(arguments!['kind']); } return; @@ -576,9 +574,9 @@ class EngineWindow extends ui.Window { case 'flutter/platform_views': if (experimentalUseSkia) { - rasterizer.viewEmbedder.handlePlatformViewCall(data, callback); + rasterizer!.surface.viewEmbedder.handlePlatformViewCall(data, callback); } else { - ui.handlePlatformViewCall(data, callback); + ui.handlePlatformViewCall(data!, callback!); } return; @@ -592,17 +590,17 @@ class EngineWindow extends ui.Window { case 'flutter/navigation': const MethodCodec codec = JSONMethodCodec(); final MethodCall decoded = codec.decodeMethodCall(data); - final Map message = decoded.arguments; + final Map? message = decoded.arguments; switch (decoded.method) { case 'routeUpdated': case 'routePushed': case 'routeReplaced': - _browserHistory.setRouteName(message['routeName']); + _browserHistory.setRouteName(message!['routeName']); _replyToPlatformMessage( callback, codec.encodeSuccessEnvelope(true)); break; case 'routePopped': - _browserHistory.setRouteName(message['previousRouteName']); + _browserHistory.setRouteName(message!['previousRouteName']); _replyToPlatformMessage( callback, codec.encodeSuccessEnvelope(true)); break; @@ -615,7 +613,7 @@ class EngineWindow extends ui.Window { } if (pluginMessageCallHandler != null) { - pluginMessageCallHandler(name, data, callback); + pluginMessageCallHandler!(name, data, callback); return; } @@ -629,7 +627,7 @@ class EngineWindow extends ui.Window { // callback(null); } - int _getHapticFeedbackDuration(String type) { + int _getHapticFeedbackDuration(String? type) { switch (type) { case 'HapticFeedbackType.lightImpact': return DomRenderer.vibrateLightImpact; @@ -648,8 +646,8 @@ class EngineWindow extends ui.Window { /// messages and responses have to be exchanged asynchronously. We simulate /// that by adding a zero-length delay to the reply. void _replyToPlatformMessage( - ui.PlatformMessageResponseCallback callback, - ByteData data, + ui.PlatformMessageResponseCallback? callback, + ByteData? data, ) { Future.delayed(Duration.zero).then((_) { if (callback != null) { @@ -681,7 +679,7 @@ class EngineWindow extends ui.Window { /// A callback that is invoked whenever [_brightnessMediaQuery] changes value. /// /// Updates the [_platformBrightness] with the new user preference. - html.EventListener _brightnessMediaQueryListener; + html.EventListener? _brightnessMediaQueryListener; /// Set the callback function for listening changes in [_brightnessMediaQuery] value. void _addBrightnessMediaQueryListener() { @@ -690,7 +688,7 @@ class EngineWindow extends ui.Window { : ui.Brightness.light); _brightnessMediaQueryListener = (html.Event event) { - final html.MediaQueryListEvent mqEvent = event; + final html.MediaQueryListEvent mqEvent = event as html.MediaQueryListEvent; _updatePlatformBrightness( mqEvent.matches ? ui.Brightness.dark : ui.Brightness.light); }; @@ -707,34 +705,34 @@ class EngineWindow extends ui.Window { } @override - void render(ui.Scene/*!*/ scene) { + void render(ui.Scene scene) { if (experimentalUseSkia) { - final LayerScene layerScene = scene; - rasterizer.draw(layerScene.layerTree); + final LayerScene layerScene = scene as LayerScene; + rasterizer!.draw(layerScene.layerTree); } else { - final SurfaceScene surfaceScene = scene; + final SurfaceScene surfaceScene = scene as SurfaceScene; domRenderer.renderScene(surfaceScene.webOnlyRootElement); } } @visibleForTesting - Rasterizer rasterizer = experimentalUseSkia ? Rasterizer(Surface()) : null; + late Rasterizer? rasterizer = experimentalUseSkia ? Rasterizer(Surface(HtmlViewEmbedder())) : null; } -bool _handleWebTestEnd2EndMessage(MethodCodec codec, ByteData data) { +bool _handleWebTestEnd2EndMessage(MethodCodec codec, ByteData? data) { final MethodCall decoded = codec.decodeMethodCall(data); double ratio = double.parse(decoded.arguments); switch (decoded.method) { case 'setDevicePixelRatio': window.debugOverrideDevicePixelRatio(ratio); - window.onMetricsChanged(); + window.onMetricsChanged!(); return true; } return false; } /// Invokes [callback] inside the given [zone]. -void _invoke(void callback(), Zone zone) { +void _invoke(void callback()?, Zone? zone) { if (callback == null) { return; } @@ -744,12 +742,12 @@ void _invoke(void callback(), Zone zone) { if (identical(zone, Zone.current)) { callback(); } else { - zone.runGuarded(callback); + zone!.runGuarded(callback); } } /// Invokes [callback] inside the given [zone] passing it [arg]. -void _invoke1(void callback(A a), Zone zone, A arg) { +void _invoke1(void callback(A a)?, Zone? zone, A arg) { if (callback == null) { return; } @@ -759,13 +757,13 @@ void _invoke1(void callback(A a), Zone zone, A arg) { if (identical(zone, Zone.current)) { callback(arg); } else { - zone.runUnaryGuarded(callback, arg); + zone!.runUnaryGuarded(callback, arg); } } /// Invokes [callback] inside the given [zone] passing it [arg1], [arg2], and [arg3]. void _invoke3( - void callback(A1 a1, A2 a2, A3 a3), Zone zone, A1 arg1, A2 arg2, A3 arg3) { + void callback(A1 a1, A2 a2, A3 a3)?, Zone? zone, A1 arg1, A2 arg2, A3 arg3) { if (callback == null) { return; } @@ -775,7 +773,7 @@ void _invoke3( if (identical(zone, Zone.current)) { callback(arg1, arg2, arg3); } else { - zone.runGuarded(() { + zone!.runGuarded(() { callback(arg1, arg2, arg3); }); } @@ -786,15 +784,15 @@ void _invoke3( /// `dart:ui` window delegates to this value. However, this value has a wider /// API surface, providing Web-specific functionality that the standard /// `dart:ui` version does not. -final EngineWindow/*!*/ window = EngineWindow(); +final EngineWindow window = EngineWindow(); /// The Web implementation of [ui.WindowPadding]. class WindowPadding implements ui.WindowPadding { const WindowPadding({ - this.left, - this.top, - this.right, - this.bottom, + required this.left, + required this.top, + required this.right, + required this.bottom, }); final double left; diff --git a/lib/web_ui/lib/ui.dart b/lib/web_ui/lib/ui.dart index bfedc844f9ae4..49217e14a861d 100644 --- a/lib/web_ui/lib/ui.dart +++ b/lib/web_ui/lib/ui.dart @@ -48,7 +48,7 @@ void webOnlyInitializeEngine() { engine.initializeEngine(); } -void webOnlySetPluginHandler(Future Function(String, ByteData, PlatformMessageResponseCallback) handler) { +void webOnlySetPluginHandler(Future Function(String, ByteData?, PlatformMessageResponseCallback?) handler) { engine.pluginMessageCallHandler = handler; } diff --git a/lib/web_ui/test/canvaskit/path_metrics_test.dart b/lib/web_ui/test/canvaskit/path_metrics_test.dart index 9089a6b57af24..b2c3529f8f082 100644 --- a/lib/web_ui/test/canvaskit/path_metrics_test.dart +++ b/lib/web_ui/test/canvaskit/path_metrics_test.dart @@ -62,8 +62,8 @@ void main() { expect(iter2.current, isNotNull); expect(iter1.moveNext(), false); expect(iter2.moveNext(), false); - expect(iter1.current, isNull); - expect(iter2.current, isNull); + expect(() => iter1.current, throwsRangeError); + expect(() => iter2.current, throwsRangeError); }); }, // This test failed on iOS Safari. diff --git a/lib/web_ui/test/dom_renderer_test.dart b/lib/web_ui/test/dom_renderer_test.dart index 1c1d53c5c4a21..ca9d6804a47c8 100644 --- a/lib/web_ui/test/dom_renderer_test.dart +++ b/lib/web_ui/test/dom_renderer_test.dart @@ -76,29 +76,6 @@ void main() { renderer.detachElement(child); expect(element.children, isEmpty); }); - test('can reattach detached elements', () { - final DomRenderer renderer = DomRenderer(); - final html.Element element = renderer.createElement('div'); - final html.Element child = renderer.createElement('div', parent: element); - final html.Element otherChild = - renderer.createElement('foo', parent: element); - renderer.detachElement(child); - expect(element.children, hasLength(1)); - renderer.attachBeforeElement(element, otherChild, child); - expect(element.children, hasLength(2)); - }); - test('insert two elements in the middle of a child list', () { - final DomRenderer renderer = DomRenderer(); - final html.Element parent = renderer.createElement('div'); - renderer.createElement('a', parent: parent); - final html.Element childD = renderer.createElement('d', parent: parent); - expect(parent.innerHtml, ''); - final html.Element childB = renderer.createElement('b', parent: parent); - final html.Element childC = renderer.createElement('c', parent: parent); - renderer.attachBeforeElement(parent, childD, childB); - renderer.attachBeforeElement(parent, childD, childC); - expect(parent.innerHtml, ''); - }); test('innerHeight/innerWidth are equal to visualViewport height and width', () { diff --git a/lib/web_ui/test/paragraph_test.dart b/lib/web_ui/test/paragraph_test.dart index cc3f16663b4d2..0bb402651fae4 100644 --- a/lib/web_ui/test/paragraph_test.dart +++ b/lib/web_ui/test/paragraph_test.dart @@ -406,9 +406,9 @@ void main() async { expect( paragraph.getBoxesForRange(1, 2).single, const TextBox.fromLTRBD( - 10, + 970, 0, - 20, + 980, 10, TextDirection.rtl, ),