[web] Cleanup everything HTML from the framework (#162837)

Things being removed:

- Custom image filter logic in `cupertino/dialog.dart`.
- Network image support for the HTML renderer.
- Shader warm up guard for the HTML renderer.
- Custom caret metrics logic in `text_painter.dart`.
This commit is contained in:
Mouad Debbar 2025-02-13 15:53:36 -05:00 committed by GitHub
parent c2229a884b
commit 4e6e24f729
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 22 additions and 75 deletions

View File

@ -684,7 +684,7 @@ class CupertinoPopupSurface extends StatelessWidget {
isVibrancePainted = debugIsVibrancePainted;
return true;
}());
if ((kIsWeb && !isSkiaWeb) || !isVibrancePainted) {
if (!isVibrancePainted) {
if (blurSigma == 0) {
return null;
}

View File

@ -5,7 +5,6 @@
import 'dart:async';
import 'dart:js_interop';
import 'dart:ui' as ui;
import 'dart:ui_web' as ui_web;
import 'package:flutter/foundation.dart';
@ -134,9 +133,6 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
return collector;
}
// HTML renderer does not support decoding network images to a specified size. The decode parameter
// here is ignored and `ui_web.createImageCodecFromUrl` will be used directly
// in place of the typical `instantiateImageCodec` method.
Future<ImageStreamCompleter> _loadAsync(
NetworkImage key,
_SimpleDecoderCallback decode,
@ -176,9 +172,6 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
final bool containsNetworkImageHeaders = key.headers?.isNotEmpty ?? false;
// When headers are set, the image can only be loaded by decoding.
//
// For the HTML renderer, `ui_web.createImageCodecFromUrl` method is not
// capable of handling headers.
//
// For CanvasKit and Skwasm, it is not possible to load an <img> element and
// pass the headers with the request to fetch the image. Since the user has
// provided headers, this function should assume the headers are required to
@ -188,32 +181,6 @@ class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkIm
return loadViaDecode();
}
if (!isSkiaWeb) {
// This branch is only hit by the HTML renderer, which is deprecated. The
// HTML renderer supports loading images with CORS restrictions, so we
// don't need to catch errors and try loading the image in an <img> tag
// in this case.
// Resolve the Codec before passing it to
// [MultiFrameImageStreamCompleter] so any errors aren't reported
// twice (once from the MultiFrameImageStreamCompleter) and again
// from the wrapping [ForwardingImageStreamCompleter].
final Uri resolved = Uri.base.resolve(key.url);
final ui.Codec codec = await ui_web.createImageCodecFromUrl(
resolved,
chunkCallback: (int bytes, int total) {
chunkEvents.add(ImageChunkEvent(cumulativeBytesLoaded: bytes, expectedTotalBytes: total));
},
);
return MultiFrameImageStreamCompleter(
chunkEvents: chunkEvents.stream,
codec: Future<ui.Codec>.value(codec),
scale: key.scale,
debugLabel: key.url,
informationCollector: _imageStreamInformationCollector(key),
);
}
switch (webHtmlElementStrategy) {
case image_provider.WebHtmlElementStrategy.never:
return loadViaDecode();

View File

@ -90,20 +90,17 @@ abstract class ShaderWarmUp {
await warmUpOnCanvas(canvas);
final ui.Picture picture = recorder.endRecording();
assert(debugCaptureShaderWarmUpPicture(picture));
if (!kIsWeb || isSkiaWeb) {
// Picture.toImage is not implemented on the html renderer.
TimelineTask? debugShaderWarmUpTask;
TimelineTask? debugShaderWarmUpTask;
if (!kReleaseMode) {
debugShaderWarmUpTask = TimelineTask()..start('Warm-up shader');
}
try {
final ui.Image image = await picture.toImage(size.width.ceil(), size.height.ceil());
assert(debugCaptureShaderWarmUpImage(image));
image.dispose();
} finally {
if (!kReleaseMode) {
debugShaderWarmUpTask = TimelineTask()..start('Warm-up shader');
}
try {
final ui.Image image = await picture.toImage(size.width.ceil(), size.height.ceil());
assert(debugCaptureShaderWarmUpImage(image));
image.dispose();
} finally {
if (!kReleaseMode) {
debugShaderWarmUpTask!.finish();
}
debugShaderWarmUpTask!.finish();
}
}
picture.dispose();

View File

@ -1528,9 +1528,7 @@ class TextPainter {
final _TextPainterLayoutCacheWithOffset cachedLayout = _layoutCache!;
// If nothing is laid out, top start is the only reasonable place to place
// the cursor.
// The HTML renderer reports numberOfLines == 1 when the text is empty:
// https://github.com/flutter/flutter/issues/143331
if (cachedLayout.paragraph.numberOfLines < 1 || plainText.isEmpty) {
if (cachedLayout.paragraph.numberOfLines < 1) {
// TODO(LongCatIsLooong): assert when an invalid position is given.
return null;
}
@ -1588,31 +1586,16 @@ class TextPainter {
boxHeightStyle: ui.BoxHeightStyle.strut,
);
if (boxes.isNotEmpty) {
final bool anchorToLeft = switch (glyphInfo.writingDirection) {
TextDirection.ltr => anchorToLeadingEdge,
TextDirection.rtl => !anchorToLeadingEdge,
};
final TextBox box = anchorToLeft ? boxes.first : boxes.last;
metrics = _LineCaretMetrics(
offset: Offset(anchorToLeft ? box.left : box.right, box.top),
writingDirection: box.direction,
height: box.bottom - box.top,
);
} else {
// Fall back to glyphInfo. This should only happen when using the HTML renderer.
assert(kIsWeb && !isSkiaWeb);
final Rect graphemeBounds = glyphInfo.graphemeClusterLayoutBounds;
final double dx = switch (glyphInfo.writingDirection) {
TextDirection.ltr => anchorToLeadingEdge ? graphemeBounds.left : graphemeBounds.right,
TextDirection.rtl => anchorToLeadingEdge ? graphemeBounds.right : graphemeBounds.left,
};
metrics = _LineCaretMetrics(
offset: Offset(dx, graphemeBounds.top),
writingDirection: glyphInfo.writingDirection,
height: graphemeBounds.height,
);
}
final bool anchorToLeft = switch (glyphInfo.writingDirection) {
TextDirection.ltr => anchorToLeadingEdge,
TextDirection.rtl => !anchorToLeadingEdge,
};
final TextBox box = anchorToLeft ? boxes.first : boxes.last;
metrics = _LineCaretMetrics(
offset: Offset(anchorToLeft ? box.left : box.right, box.top),
writingDirection: box.direction,
height: box.bottom - box.top,
);
cachedLayout._previousCaretPositionKey = caretPositionCacheKey;
return _caretMetrics = metrics;