blob: 70b69908c26a22384390a67591cf861a2fe920e8 [file] [log] [blame]
// 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.
import 'dart:async';
import 'dart:math' as math;
import 'dart:typed_data';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;
class HtmlRenderer implements Renderer {
static HtmlRenderer get instance => _instance;
static late HtmlRenderer _instance;
@override
String get rendererTag => 'html';
late final HtmlFontCollection _fontCollection = HtmlFontCollection();
late FlutterViewEmbedder _viewEmbedder;
@override
HtmlFontCollection get fontCollection => _fontCollection;
@override
void initialize() {
scheduleMicrotask(() {
// Access [lineLookup] to force the lazy unpacking of line break data
// now. Removing this line won't break anything. It's just an optimization
// to make the unpacking happen while we are waiting for network requests.
lineLookup;
});
_instance = this;
}
@override
void reset(FlutterViewEmbedder embedder) {
_viewEmbedder = embedder;
}
@override
ui.Paint createPaint() => SurfacePaint();
@override
ui.Vertices createVertices(
ui.VertexMode mode,
List<ui.Offset> positions, {
List<ui.Offset>? textureCoordinates,
List<ui.Color>? colors,
List<int>? indices,
}) => SurfaceVertices(
mode,
positions,
colors: colors,
indices: indices);
@override
ui.Vertices createVerticesRaw(
ui.VertexMode mode,
Float32List positions, {
Float32List? textureCoordinates,
Int32List? colors,
Uint16List? indices,
}) => SurfaceVertices.raw(
mode,
positions,
colors: colors,
indices: indices);
@override
ui.Canvas createCanvas(ui.PictureRecorder recorder, [ui.Rect? cullRect]) =>
SurfaceCanvas(recorder as EnginePictureRecorder, cullRect);
@override
ui.Gradient createLinearGradient(
ui.Offset from,
ui.Offset to,
List<ui.Color> colors, [
List<double>? colorStops,
ui.TileMode tileMode = ui.TileMode.clamp,
Float32List? matrix4
]) => GradientLinear(from, to, colors, colorStops, tileMode, matrix4);
@override
ui.Gradient createRadialGradient(
ui.Offset center,
double radius,
List<ui.Color> colors, [
List<double>? colorStops,
ui.TileMode tileMode = ui.TileMode.clamp,
Float32List? matrix4,
ui.Offset? focal,
double focalRadius = 0.0,
]) => GradientRadial(center, radius, colors, colorStops, tileMode, matrix4);
@override
ui.Gradient createConicalGradient(
ui.Offset focal,
double focalRadius,
ui.Offset center,
double radius,
List<ui.Color> colors,
[List<double>? colorStops,
ui.TileMode tileMode = ui.TileMode.clamp,
Float32List? matrix
]) => GradientConical(
focal,
focalRadius,
center,
radius,
colors,
colorStops,
tileMode,
matrix);
@override
ui.Gradient createSweepGradient(
ui.Offset center,
List<ui.Color> colors, [
List<double>? colorStops,
ui.TileMode tileMode = ui.TileMode.clamp,
double startAngle = 0.0,
double endAngle = math.pi * 2,
Float32List? matrix4
]) => GradientSweep(center, colors, colorStops, tileMode, startAngle, endAngle, matrix4);
@override
ui.PictureRecorder createPictureRecorder() => EnginePictureRecorder();
@override
ui.SceneBuilder createSceneBuilder() => SurfaceSceneBuilder();
// TODO(ferhat): implement TileMode.
@override
ui.ImageFilter createBlurImageFilter({
double sigmaX = 0.0,
double sigmaY = 0.0,
ui.TileMode tileMode = ui.TileMode.clamp
}) => EngineImageFilter.blur(sigmaX: sigmaX, sigmaY: sigmaY, tileMode: tileMode);
@override
ui.ImageFilter createDilateImageFilter({double radiusX = 0.0, double radiusY = 0.0}) {
// TODO(fzyzcjy): implement dilate. https://github.com/flutter/flutter/issues/101085
throw UnimplementedError('ImageFilter.dilate not implemented for HTML renderer.');
}
@override
ui.ImageFilter createErodeImageFilter({double radiusX = 0.0, double radiusY = 0.0}) {
// TODO(fzyzcjy): implement erode. https://github.com/flutter/flutter/issues/101085
throw UnimplementedError('ImageFilter.erode not implemented for HTML renderer.');
}
@override
ui.ImageFilter createMatrixImageFilter(
Float64List matrix4, {
ui.FilterQuality filterQuality = ui.FilterQuality.low
}) => EngineImageFilter.matrix(matrix: matrix4, filterQuality: filterQuality);
@override
ui.ImageFilter composeImageFilters({required ui.ImageFilter outer, required ui.ImageFilter inner}) {
// TODO(ferhat): add implementation and remove the "ignore".
// ignore: avoid_unused_constructor_parameters
throw UnimplementedError('ImageFilter.erode not implemented for HTML renderer.');
}
@override
Future<ui.Codec> instantiateImageCodec(
Uint8List list, {
int? targetWidth,
int? targetHeight,
bool allowUpscaling = true}) async {
final DomBlob blob = createDomBlob(<dynamic>[list.buffer]);
return HtmlBlobCodec(blob);
}
@override
Future<ui.Codec> instantiateImageCodecFromUrl(
Uri uri, {
WebOnlyImageCodecChunkCallback? chunkCallback}) {
return futurize<ui.Codec>((Callback<ui.Codec> callback) {
callback(HtmlCodec(uri.toString(), chunkCallback: chunkCallback));
return null;
});
}
@override
void decodeImageFromPixels(
Uint8List pixels,
int width,
int height,
ui.PixelFormat format,
ui.ImageDecoderCallback callback, {
int? rowBytes,
int? targetWidth,
int? targetHeight,
bool allowUpscaling = true
}) {
void executeCallback(ui.Codec codec) {
codec.getNextFrame().then((ui.FrameInfo frameInfo) {
callback(frameInfo.image);
});
}
ui.createBmp(pixels, width, height, rowBytes ?? width, format).then(
executeCallback);
}
@override
ui.ImageShader createImageShader(
ui.Image image,
ui.TileMode tmx,
ui.TileMode tmy,
Float64List matrix4,
ui.FilterQuality? filterQuality
) => EngineImageShader(image, tmx, tmy, matrix4, filterQuality);
@override
ui.Path createPath() => SurfacePath();
@override
ui.Path copyPath(ui.Path src) => SurfacePath.from(src as SurfacePath);
@override
ui.Path combinePaths(ui.PathOperation op, ui.Path path1, ui.Path path2) {
throw UnimplementedError('combinePaths not implemented in HTML renderer.');
}
@override
ui.TextStyle createTextStyle({
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<String>? fontFamilyFallback,
double? fontSize,
double? letterSpacing,
double? wordSpacing,
double? height,
ui.TextLeadingDistribution? leadingDistribution,
ui.Locale? locale,
ui.Paint? background,
ui.Paint? foreground,
List<ui.Shadow>? shadows,
List<ui.FontFeature>? fontFeatures,
List<ui.FontVariation>? fontVariations
}) => EngineTextStyle(
color: color,
decoration: decoration,
decorationColor: decorationColor,
decorationStyle: decorationStyle,
decorationThickness: decorationThickness,
fontWeight: fontWeight,
fontStyle: fontStyle,
textBaseline: textBaseline,
fontFamily: fontFamily,
fontFamilyFallback: fontFamilyFallback,
fontSize: fontSize,
letterSpacing: letterSpacing,
wordSpacing: wordSpacing,
height: height,
locale: locale,
background: background,
foreground: foreground,
shadows: shadows,
fontFeatures: fontFeatures,
fontVariations: fontVariations,
);
@override
ui.ParagraphStyle createParagraphStyle({
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
}) => EngineParagraphStyle(
textAlign: textAlign,
textDirection: textDirection,
maxLines: maxLines,
fontFamily: fontFamily,
fontSize: fontSize,
height: height,
textHeightBehavior: textHeightBehavior,
fontWeight: fontWeight,
fontStyle: fontStyle,
strutStyle: strutStyle,
ellipsis: ellipsis,
locale: locale,
);
@override
ui.StrutStyle createStrutStyle({
String? fontFamily,
List<String>? fontFamilyFallback,
double? fontSize,
double? height,
ui.TextLeadingDistribution? leadingDistribution,
double? leading,
ui.FontWeight? fontWeight,
ui.FontStyle? fontStyle,
bool? forceStrutHeight
}) => EngineStrutStyle(
fontFamily: fontFamily,
fontFamilyFallback: fontFamilyFallback,
fontSize: fontSize,
height: height,
leadingDistribution: leadingDistribution,
leading: leading,
fontWeight: fontWeight,
fontStyle: fontStyle,
forceStrutHeight: forceStrutHeight,
);
@override
ui.ParagraphBuilder createParagraphBuilder(ui.ParagraphStyle style) =>
CanvasParagraphBuilder(style as EngineParagraphStyle);
@override
void renderScene(ui.Scene scene) {
_viewEmbedder.addSceneToSceneHost((scene as SurfaceScene).webOnlyRootElement);
frameTimingsOnRasterFinish();
}
}