mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Add more TextStyle support to Paragraph in CanvasKit mode (flutter/engine#21629)
* WIP on Paragraph * WIP skparagraph * Add more Paragraph features in CanvasKit mode * Fix addRoundRect test * Respond to review comments * Remove unused (and potentially harmful) getters from Sk classes
This commit is contained in:
parent
986c45ae4a
commit
2407e893a3
@ -176,8 +176,7 @@ class CkCanvas {
|
||||
skCanvas.drawPicture(picture.skiaObject.skiaObject);
|
||||
}
|
||||
|
||||
void drawPoints(CkPaint paint, ui.PointMode pointMode,
|
||||
Float32List points) {
|
||||
void drawPoints(CkPaint paint, ui.PointMode pointMode, Float32List points) {
|
||||
skCanvas.drawPoints(
|
||||
toSkPointMode(pointMode),
|
||||
points,
|
||||
@ -230,24 +229,24 @@ class CkCanvas {
|
||||
|
||||
void saveLayer(ui.Rect bounds, CkPaint paint) {
|
||||
skCanvas.saveLayer(
|
||||
toSkRect(bounds),
|
||||
paint.skiaObject,
|
||||
toSkRect(bounds),
|
||||
null,
|
||||
null,
|
||||
);
|
||||
}
|
||||
|
||||
void saveLayerWithoutBounds(CkPaint paint) {
|
||||
final SkCanvasSaveLayerWithoutBoundsOverload override = skCanvas as SkCanvasSaveLayerWithoutBoundsOverload;
|
||||
override.saveLayer(paint.skiaObject);
|
||||
skCanvas.saveLayer(paint.skiaObject, null, null, null);
|
||||
}
|
||||
|
||||
void saveLayerWithFilter(ui.Rect bounds, ui.ImageFilter filter) {
|
||||
final SkCanvasSaveLayerWithFilterOverload override = skCanvas as SkCanvasSaveLayerWithFilterOverload;
|
||||
final CkImageFilter skImageFilter = filter as CkImageFilter;
|
||||
return override.saveLayer(
|
||||
return skCanvas.saveLayer(
|
||||
null,
|
||||
toSkRect(bounds),
|
||||
skImageFilter.skiaObject,
|
||||
0,
|
||||
toSkRect(bounds),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -79,6 +79,10 @@ class CanvasKit {
|
||||
external int get LineThroughDecoration;
|
||||
// End of text decoration enum.
|
||||
|
||||
external SkTextDecorationStyleEnum get DecorationStyle;
|
||||
external SkTextBaselineEnum get TextBaseline;
|
||||
external SkPlaceholderAlignmentEnum get PlaceholderAlignment;
|
||||
|
||||
external SkFontMgrNamespace get SkFontMgr;
|
||||
external TypefaceFontProviderNamespace get TypefaceFontProvider;
|
||||
external int GetWebGLContext(
|
||||
@ -1015,12 +1019,12 @@ class SkPath {
|
||||
external SkPath([SkPath? other]);
|
||||
external void setFillType(SkFillType fillType);
|
||||
external void addArc(
|
||||
SkRect oval,
|
||||
Float32List oval,
|
||||
double startAngleDegrees,
|
||||
double sweepAngleDegrees,
|
||||
);
|
||||
external void addOval(
|
||||
SkRect oval,
|
||||
Float32List oval,
|
||||
bool counterClockWise,
|
||||
int startIndex,
|
||||
);
|
||||
@ -1041,16 +1045,15 @@ class SkPath {
|
||||
Float32List points,
|
||||
bool close,
|
||||
);
|
||||
external void addRoundRect(
|
||||
SkRect outerRect,
|
||||
Float32List radii,
|
||||
external void addRRect(
|
||||
Float32List rrect,
|
||||
bool counterClockWise,
|
||||
);
|
||||
external void addRect(
|
||||
SkRect rect,
|
||||
Float32List rect,
|
||||
);
|
||||
external void arcToOval(
|
||||
SkRect oval,
|
||||
Float32List oval,
|
||||
double startAngleDegrees,
|
||||
double sweepAngleDegrees,
|
||||
bool forceMoveTo,
|
||||
@ -1084,7 +1087,7 @@ class SkPath {
|
||||
double x3,
|
||||
double y3,
|
||||
);
|
||||
external SkRect getBounds();
|
||||
external Float32List getBounds();
|
||||
external void lineTo(double x, double y);
|
||||
external void moveTo(double x, double y);
|
||||
external void quadTo(
|
||||
@ -1156,88 +1159,46 @@ class SkContourMeasure {
|
||||
external double length();
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class SkRect {
|
||||
external factory SkRect({
|
||||
required double fLeft,
|
||||
required double fTop,
|
||||
required double fRight,
|
||||
required double fBottom,
|
||||
});
|
||||
external double get fLeft;
|
||||
external double get fTop;
|
||||
external double get fRight;
|
||||
external double get fBottom;
|
||||
// TODO(hterkelsen): Use a shared malloc'ed array for performance.
|
||||
Float32List toSkRect(ui.Rect rect) {
|
||||
final Float32List skRect = Float32List(4);
|
||||
skRect[0] = rect.left;
|
||||
skRect[1] = rect.top;
|
||||
skRect[2] = rect.right;
|
||||
skRect[3] = rect.bottom;
|
||||
return skRect;
|
||||
}
|
||||
|
||||
extension SkRectExtensions on SkRect {
|
||||
ui.Rect toRect() {
|
||||
return ui.Rect.fromLTRB(
|
||||
this.fLeft,
|
||||
this.fTop,
|
||||
this.fRight,
|
||||
this.fBottom,
|
||||
);
|
||||
}
|
||||
ui.Rect fromSkRect(Float32List skRect) {
|
||||
return ui.Rect.fromLTRB(skRect[0], skRect[1], skRect[2], skRect[3]);
|
||||
}
|
||||
|
||||
SkRect toSkRect(ui.Rect rect) {
|
||||
return SkRect(
|
||||
fLeft: rect.left,
|
||||
fTop: rect.top,
|
||||
fRight: rect.right,
|
||||
fBottom: rect.bottom,
|
||||
);
|
||||
// TODO(hterkelsen): Use a shared malloc'ed array for performance.
|
||||
Float32List toSkRRect(ui.RRect rrect) {
|
||||
final Float32List skRRect = Float32List(12);
|
||||
skRRect[0] = rrect.left;
|
||||
skRRect[1] = rrect.top;
|
||||
skRRect[2] = rrect.right;
|
||||
skRRect[3] = rrect.bottom;
|
||||
skRRect[4] = rrect.tlRadiusX;
|
||||
skRRect[5] = rrect.tlRadiusY;
|
||||
skRRect[6] = rrect.trRadiusX;
|
||||
skRRect[7] = rrect.trRadiusY;
|
||||
skRRect[8] = rrect.brRadiusX;
|
||||
skRRect[9] = rrect.brRadiusY;
|
||||
skRRect[10] = rrect.blRadiusX;
|
||||
skRRect[11] = rrect.blRadiusY;
|
||||
return skRRect;
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class SkRRect {
|
||||
external factory SkRRect({
|
||||
required SkRect rect,
|
||||
required double rx1,
|
||||
required double ry1,
|
||||
required double rx2,
|
||||
required double ry2,
|
||||
required double rx3,
|
||||
required double ry3,
|
||||
required double rx4,
|
||||
required double ry4,
|
||||
});
|
||||
|
||||
external SkRect get rect;
|
||||
external double get rx1;
|
||||
external double get ry1;
|
||||
external double get rx2;
|
||||
external double get ry2;
|
||||
external double get rx3;
|
||||
external double get ry3;
|
||||
external double get rx4;
|
||||
external double get ry4;
|
||||
}
|
||||
|
||||
SkRRect toSkRRect(ui.RRect rrect) {
|
||||
return SkRRect(
|
||||
rect: toOuterSkRect(rrect),
|
||||
rx1: rrect.tlRadiusX,
|
||||
ry1: rrect.tlRadiusY,
|
||||
rx2: rrect.trRadiusX,
|
||||
ry2: rrect.trRadiusY,
|
||||
rx3: rrect.brRadiusX,
|
||||
ry3: rrect.brRadiusY,
|
||||
rx4: rrect.blRadiusX,
|
||||
ry4: rrect.blRadiusY,
|
||||
);
|
||||
}
|
||||
|
||||
SkRect toOuterSkRect(ui.RRect rrect) {
|
||||
return SkRect(
|
||||
fLeft: rrect.left,
|
||||
fTop: rrect.top,
|
||||
fRight: rrect.right,
|
||||
fBottom: rrect.bottom,
|
||||
);
|
||||
// TODO(hterkelsen): Use a shared malloc'ed array for performance.
|
||||
Float32List toOuterSkRect(ui.RRect rrect) {
|
||||
final Float32List skRect = Float32List(4);
|
||||
skRect[0] = rrect.left;
|
||||
skRect[1] = rrect.top;
|
||||
skRect[2] = rrect.right;
|
||||
skRect[3] = rrect.bottom;
|
||||
return skRect;
|
||||
}
|
||||
|
||||
/// Encodes a list of offsets to CanvasKit-compatible point array.
|
||||
@ -1263,9 +1224,9 @@ List<Float32List> rawPointsToSkPoints2d(Float32List points) {
|
||||
assert(points.length % 2 == 0);
|
||||
final int pointLength = points.length ~/ 2;
|
||||
final List<Float32List> result = <Float32List>[];
|
||||
for (var i = 0; i < pointLength; i++) {
|
||||
var x = i * 2;
|
||||
var y = x + 1;
|
||||
for (int i = 0; i < pointLength; i++) {
|
||||
int x = i * 2;
|
||||
int y = x + 1;
|
||||
final Float32List skPoint = Float32List(2);
|
||||
skPoint[0] = points[x];
|
||||
skPoint[1] = points[y];
|
||||
@ -1277,7 +1238,7 @@ List<Float32List> rawPointsToSkPoints2d(Float32List points) {
|
||||
List<Float32List> toSkPoints2d(List<ui.Offset> offsets) {
|
||||
final int len = offsets.length;
|
||||
final List<Float32List> result = <Float32List>[];
|
||||
for (var i = 0; i < len; i++) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
final ui.Offset offset = offsets[i];
|
||||
final Float32List skPoint = Float32List(2);
|
||||
skPoint[0] = offset.dx;
|
||||
@ -1299,7 +1260,7 @@ Uint16List toUint16List(List<int> ints) {
|
||||
@JS('window.flutterCanvasKit.SkPictureRecorder')
|
||||
class SkPictureRecorder {
|
||||
external SkPictureRecorder();
|
||||
external SkCanvas beginRecording(SkRect bounds);
|
||||
external SkCanvas beginRecording(Float32List bounds);
|
||||
external SkPicture finishRecordingAsPicture();
|
||||
external void delete();
|
||||
}
|
||||
@ -1319,17 +1280,17 @@ class SkCanvas {
|
||||
bool doAntiAlias,
|
||||
);
|
||||
external void clipRRect(
|
||||
SkRRect rrect,
|
||||
Float32List rrect,
|
||||
SkClipOp clipOp,
|
||||
bool doAntiAlias,
|
||||
);
|
||||
external void clipRect(
|
||||
SkRect rrect,
|
||||
Float32List rrect,
|
||||
SkClipOp clipOp,
|
||||
bool doAntiAlias,
|
||||
);
|
||||
external void drawArc(
|
||||
SkRect oval,
|
||||
Float32List oval,
|
||||
double startAngleDegrees,
|
||||
double sweepAngleDegrees,
|
||||
bool useCenter,
|
||||
@ -1354,8 +1315,8 @@ class SkCanvas {
|
||||
SkBlendMode blendMode,
|
||||
);
|
||||
external void drawDRRect(
|
||||
SkRRect outer,
|
||||
SkRRect inner,
|
||||
Float32List outer,
|
||||
Float32List inner,
|
||||
SkPaint paint,
|
||||
);
|
||||
external void drawImage(
|
||||
@ -1366,15 +1327,15 @@ class SkCanvas {
|
||||
);
|
||||
external void drawImageRect(
|
||||
SkImage image,
|
||||
SkRect src,
|
||||
SkRect dst,
|
||||
Float32List src,
|
||||
Float32List dst,
|
||||
SkPaint paint,
|
||||
bool fastSample,
|
||||
);
|
||||
external void drawImageNine(
|
||||
SkImage image,
|
||||
SkRect center,
|
||||
SkRect dst,
|
||||
Float32List center,
|
||||
Float32List dst,
|
||||
SkPaint paint,
|
||||
);
|
||||
external void drawLine(
|
||||
@ -1385,7 +1346,7 @@ class SkCanvas {
|
||||
SkPaint paint,
|
||||
);
|
||||
external void drawOval(
|
||||
SkRect rect,
|
||||
Float32List rect,
|
||||
SkPaint paint,
|
||||
);
|
||||
external void drawPaint(
|
||||
@ -1401,11 +1362,11 @@ class SkCanvas {
|
||||
SkPaint paint,
|
||||
);
|
||||
external void drawRRect(
|
||||
SkRRect rrect,
|
||||
Float32List rrect,
|
||||
SkPaint paint,
|
||||
);
|
||||
external void drawRect(
|
||||
SkRect rrect,
|
||||
Float32List rrect,
|
||||
SkPaint paint,
|
||||
);
|
||||
external void drawShadow(
|
||||
@ -1425,8 +1386,10 @@ class SkCanvas {
|
||||
external int save();
|
||||
external int getSaveCount();
|
||||
external void saveLayer(
|
||||
SkRect bounds,
|
||||
SkPaint paint,
|
||||
SkPaint? paint,
|
||||
Float32List? bounds,
|
||||
SkImageFilter? backdrop,
|
||||
int? flags,
|
||||
);
|
||||
external void restore();
|
||||
external void restoreToCount(int count);
|
||||
@ -1448,23 +1411,6 @@ class SkCanvas {
|
||||
);
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class SkCanvasSaveLayerWithoutBoundsOverload {
|
||||
external void saveLayer(SkPaint paint);
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class SkCanvasSaveLayerWithFilterOverload {
|
||||
external void saveLayer(
|
||||
SkPaint? paint,
|
||||
SkImageFilter? imageFilter,
|
||||
int flags,
|
||||
SkRect rect,
|
||||
);
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class SkPicture {
|
||||
@ -1493,6 +1439,7 @@ class SkParagraphBuilder {
|
||||
external void pushPaintStyle(
|
||||
SkTextStyle textStyle, SkPaint foreground, SkPaint background);
|
||||
external void pop();
|
||||
external void addPlaceholder(SkPlaceholderStyleProperties placeholderStyle);
|
||||
external SkParagraph build();
|
||||
external void delete();
|
||||
}
|
||||
@ -1504,69 +1451,162 @@ class SkParagraphStyle {}
|
||||
@JS()
|
||||
@anonymous
|
||||
class SkParagraphStyleProperties {
|
||||
external SkTextAlign? get textAlign;
|
||||
external set textAlign(SkTextAlign? value);
|
||||
|
||||
external SkTextDirection? get textDirection;
|
||||
external set textDirection(SkTextDirection? value);
|
||||
|
||||
external double? get heightMultiplier;
|
||||
external set heightMultiplier(double? value);
|
||||
|
||||
external int? get textHeightBehavior;
|
||||
external set textHeightBehavior(int? value);
|
||||
|
||||
external int? get maxLines;
|
||||
external set maxLines(int? value);
|
||||
|
||||
external String? get ellipsis;
|
||||
external set ellipsis(String? value);
|
||||
|
||||
external SkTextStyleProperties? get textStyle;
|
||||
external set textStyle(SkTextStyleProperties? value);
|
||||
external set strutStyle(SkStrutStyleProperties? strutStyle);
|
||||
}
|
||||
|
||||
@JS()
|
||||
class SkTextStyle {}
|
||||
|
||||
@JS()
|
||||
class SkTextDecorationStyleEnum {
|
||||
external SkTextDecorationStyle get Solid;
|
||||
external SkTextDecorationStyle get Double;
|
||||
external SkTextDecorationStyle get Dotted;
|
||||
external SkTextDecorationStyle get Dashed;
|
||||
external SkTextDecorationStyle get Wavy;
|
||||
}
|
||||
|
||||
@JS()
|
||||
class SkTextDecorationStyle {
|
||||
external int get value;
|
||||
}
|
||||
|
||||
final List<SkTextDecorationStyle> _skTextDecorationStyles =
|
||||
<SkTextDecorationStyle>[
|
||||
canvasKit.DecorationStyle.Solid,
|
||||
canvasKit.DecorationStyle.Double,
|
||||
canvasKit.DecorationStyle.Dotted,
|
||||
canvasKit.DecorationStyle.Dashed,
|
||||
canvasKit.DecorationStyle.Wavy,
|
||||
];
|
||||
|
||||
SkTextDecorationStyle toSkTextDecorationStyle(ui.TextDecorationStyle style) {
|
||||
return _skTextDecorationStyles[style.index];
|
||||
}
|
||||
|
||||
@JS()
|
||||
class SkTextBaselineEnum {
|
||||
external SkTextBaseline get Alphabetic;
|
||||
external SkTextBaseline get Ideographic;
|
||||
}
|
||||
|
||||
@JS()
|
||||
class SkTextBaseline {
|
||||
external int get value;
|
||||
}
|
||||
|
||||
final List<SkTextBaseline> _skTextBaselines = <SkTextBaseline>[
|
||||
canvasKit.TextBaseline.Alphabetic,
|
||||
canvasKit.TextBaseline.Ideographic,
|
||||
];
|
||||
|
||||
SkTextBaseline toSkTextBaseline(ui.TextBaseline baseline) {
|
||||
return _skTextBaselines[baseline.index];
|
||||
}
|
||||
|
||||
@JS()
|
||||
class SkPlaceholderAlignmentEnum {
|
||||
external SkPlaceholderAlignment get Baseline;
|
||||
external SkPlaceholderAlignment get AboveBaseline;
|
||||
external SkPlaceholderAlignment get BelowBaseline;
|
||||
external SkPlaceholderAlignment get Top;
|
||||
external SkPlaceholderAlignment get Bottom;
|
||||
external SkPlaceholderAlignment get Middle;
|
||||
}
|
||||
|
||||
@JS()
|
||||
class SkPlaceholderAlignment {
|
||||
external int get value;
|
||||
}
|
||||
|
||||
final List<SkPlaceholderAlignment> _skPlaceholderAlignments =
|
||||
<SkPlaceholderAlignment>[
|
||||
canvasKit.PlaceholderAlignment.Baseline,
|
||||
canvasKit.PlaceholderAlignment.AboveBaseline,
|
||||
canvasKit.PlaceholderAlignment.BelowBaseline,
|
||||
canvasKit.PlaceholderAlignment.Top,
|
||||
canvasKit.PlaceholderAlignment.Bottom,
|
||||
canvasKit.PlaceholderAlignment.Middle,
|
||||
];
|
||||
|
||||
SkPlaceholderAlignment toSkPlaceholderAlignment(
|
||||
ui.PlaceholderAlignment alignment) {
|
||||
return _skPlaceholderAlignments[alignment.index];
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class SkTextStyleProperties {
|
||||
external Float32List? get backgroundColor;
|
||||
external set backgroundColor(Float32List? value);
|
||||
|
||||
external Float32List? get color;
|
||||
external set color(Float32List? value);
|
||||
|
||||
external Float32List? get foregroundColor;
|
||||
external set foregroundColor(Float32List? value);
|
||||
|
||||
external int? get decoration;
|
||||
external set decoration(int? value);
|
||||
|
||||
external double? get decorationThickness;
|
||||
external set decorationThickness(double? value);
|
||||
|
||||
external double? get fontSize;
|
||||
external set decorationColor(Float32List? value);
|
||||
external set decorationStyle(SkTextDecorationStyle? value);
|
||||
external set textBaseline(SkTextBaseline? value);
|
||||
external set fontSize(double? value);
|
||||
|
||||
external List<String>? get fontFamilies;
|
||||
external set letterSpacing(double? value);
|
||||
external set wordSpacing(double? value);
|
||||
external set heightMultiplier(double? value);
|
||||
external set locale(String? value);
|
||||
external set fontFamilies(List<String>? value);
|
||||
|
||||
external SkFontStyle? get fontStyle;
|
||||
external set fontStyle(SkFontStyle? value);
|
||||
external set shadows(List<SkTextShadow>? value);
|
||||
external set fontFeatures(List<SkFontFeature>? value);
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class SkStrutStyleProperties {
|
||||
external set fontFamilies(List<String>? value);
|
||||
external set fontStyle(SkFontStyle? value);
|
||||
external set fontSize(double? value);
|
||||
external set heightMultiplier(double? value);
|
||||
external set leading(double? value);
|
||||
external set strutEnabled(bool? value);
|
||||
external set forceStrutHeight(bool? value);
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class SkPlaceholderStyleProperties {
|
||||
external set width(double? value);
|
||||
external set height(double? value);
|
||||
external set alignment(SkPlaceholderAlignment? value);
|
||||
external set offset(double? value);
|
||||
external set baseline(SkTextBaseline? value);
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class SkFontStyle {
|
||||
external SkFontWeight? get weight;
|
||||
external set weight(SkFontWeight? value);
|
||||
|
||||
external SkFontSlant? get slant;
|
||||
external set slant(SkFontSlant? value);
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class SkTextShadow {
|
||||
external set color(Float32List? value);
|
||||
external set offset(Float32List? value);
|
||||
external set blurRadius(double? value);
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class SkFontFeature {
|
||||
external set name(String? value);
|
||||
external set value(int? value);
|
||||
}
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
class SkFontMgr {
|
||||
@ -1591,12 +1631,13 @@ class SkParagraph {
|
||||
external double getMaxIntrinsicWidth();
|
||||
external double getMinIntrinsicWidth();
|
||||
external double getMaxWidth();
|
||||
external List<SkRect> getRectsForRange(
|
||||
external List<Float32List> getRectsForRange(
|
||||
int start,
|
||||
int end,
|
||||
SkRectHeightStyle heightStyle,
|
||||
SkRectWidthStyle widthStyle,
|
||||
);
|
||||
external List<Float32List> getRectsForPlaceholders();
|
||||
external SkTextPosition getGlyphPositionAtCoordinate(
|
||||
double x,
|
||||
double y,
|
||||
@ -1649,7 +1690,8 @@ class TypefaceFontProviderNamespace {
|
||||
Timer? _skObjectCollector;
|
||||
List<SkDeletable> _skObjectDeleteQueue = <SkDeletable>[];
|
||||
|
||||
final SkObjectFinalizationRegistry skObjectFinalizationRegistry = SkObjectFinalizationRegistry(js.allowInterop((SkDeletable deletable) {
|
||||
final SkObjectFinalizationRegistry skObjectFinalizationRegistry =
|
||||
SkObjectFinalizationRegistry(js.allowInterop((SkDeletable deletable) {
|
||||
_skObjectDeleteQueue.add(deletable);
|
||||
_skObjectCollector ??= _scheduleSkObjectCollection();
|
||||
}));
|
||||
@ -1668,19 +1710,20 @@ final SkObjectFinalizationRegistry skObjectFinalizationRegistry = SkObjectFinali
|
||||
/// yielding to the graphics system to render the frame on the screen if there
|
||||
/// is a large number of objects to delete, causing jank.
|
||||
Timer _scheduleSkObjectCollection() => Timer(Duration.zero, () {
|
||||
html.window.performance.mark('SkObject collection-start');
|
||||
final int length = _skObjectDeleteQueue.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
_skObjectDeleteQueue[i].delete();
|
||||
}
|
||||
_skObjectDeleteQueue = <SkDeletable>[];
|
||||
html.window.performance.mark('SkObject collection-start');
|
||||
final int length = _skObjectDeleteQueue.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
_skObjectDeleteQueue[i].delete();
|
||||
}
|
||||
_skObjectDeleteQueue = <SkDeletable>[];
|
||||
|
||||
// Null out the timer so we can schedule a new one next time objects are
|
||||
// scheduled for deletion.
|
||||
_skObjectCollector = null;
|
||||
html.window.performance.mark('SkObject collection-end');
|
||||
html.window.performance.measure('SkObject collection', 'SkObject collection-start', 'SkObject collection-end');
|
||||
});
|
||||
// Null out the timer so we can schedule a new one next time objects are
|
||||
// scheduled for deletion.
|
||||
_skObjectCollector = null;
|
||||
html.window.performance.mark('SkObject collection-end');
|
||||
html.window.performance.measure('SkObject collection',
|
||||
'SkObject collection-start', 'SkObject collection-end');
|
||||
});
|
||||
|
||||
/// Any Skia object that has a `delete` method.
|
||||
@JS()
|
||||
@ -1716,7 +1759,8 @@ class SkObjectFinalizationRegistry {
|
||||
external Object? get _finalizationRegistryConstructor;
|
||||
|
||||
/// Whether the current browser supports `FinalizationRegistry`.
|
||||
bool browserSupportsFinalizationRegistry = _finalizationRegistryConstructor != null;
|
||||
bool browserSupportsFinalizationRegistry =
|
||||
_finalizationRegistryConstructor != null;
|
||||
|
||||
@JS()
|
||||
class SkData {
|
||||
@ -1741,7 +1785,7 @@ class SkImageInfo {
|
||||
external int get height;
|
||||
external bool get isEmpty;
|
||||
external bool get isOpaque;
|
||||
external SkRect get bounds;
|
||||
external Float32List get bounds;
|
||||
external int get width;
|
||||
external SkImageInfo makeAlphaType(SkAlphaType alphaType);
|
||||
external SkImageInfo makeColorSpace(SkColorSpace colorSpace);
|
||||
|
||||
@ -20,7 +20,7 @@ const bool canvasKitForceCpuOnly =
|
||||
/// NPM, update this URL to `https://unpkg.com/canvaskit-wasm@0.34.0/bin/`.
|
||||
const String canvasKitBaseUrl = String.fromEnvironment(
|
||||
'FLUTTER_WEB_CANVASKIT_URL',
|
||||
defaultValue: 'https://unpkg.com/canvaskit-wasm@0.17.3/bin/',
|
||||
defaultValue: 'https://unpkg.com/canvaskit-wasm@0.18.1/bin/',
|
||||
);
|
||||
|
||||
/// Initialize CanvasKit.
|
||||
|
||||
@ -11,11 +11,15 @@ part of engine;
|
||||
class CkPath implements ui.Path {
|
||||
final SkPath _skPath;
|
||||
|
||||
CkPath() : _skPath = SkPath(), _fillType = ui.PathFillType.nonZero {
|
||||
CkPath()
|
||||
: _skPath = SkPath(),
|
||||
_fillType = ui.PathFillType.nonZero {
|
||||
_skPath.setFillType(toSkFillType(_fillType));
|
||||
}
|
||||
|
||||
CkPath.from(CkPath other) : _skPath = SkPath(other._skPath), _fillType = other.fillType {
|
||||
CkPath.from(CkPath other)
|
||||
: _skPath = SkPath(other._skPath),
|
||||
_fillType = other.fillType {
|
||||
_skPath.setFillType(toSkFillType(_fillType));
|
||||
}
|
||||
|
||||
@ -89,22 +93,10 @@ class CkPath implements ui.Path {
|
||||
|
||||
@override
|
||||
void addRRect(ui.RRect rrect) {
|
||||
final SkFloat32List skRadii = mallocFloat32List(8);
|
||||
final Float32List radii = skRadii.toTypedArray();
|
||||
radii[0] = rrect.tlRadiusX;
|
||||
radii[1] = rrect.tlRadiusY;
|
||||
radii[2] = rrect.trRadiusX;
|
||||
radii[3] = rrect.trRadiusY;
|
||||
radii[4] = rrect.brRadiusX;
|
||||
radii[5] = rrect.brRadiusY;
|
||||
radii[6] = rrect.blRadiusX;
|
||||
radii[7] = rrect.blRadiusY;
|
||||
_skPath.addRoundRect(
|
||||
toOuterSkRect(rrect),
|
||||
radii,
|
||||
_skPath.addRRect(
|
||||
toSkRRect(rrect),
|
||||
false,
|
||||
);
|
||||
freeFloat32List(skRadii);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -195,7 +187,7 @@ class CkPath implements ui.Path {
|
||||
}
|
||||
|
||||
@override
|
||||
ui.Rect getBounds() => _skPath.getBounds().toRect();
|
||||
ui.Rect getBounds() => fromSkRect(_skPath.getBounds());
|
||||
|
||||
@override
|
||||
void lineTo(double x, double y) {
|
||||
|
||||
@ -13,7 +13,7 @@ class CkPictureRecorder implements ui.PictureRecorder {
|
||||
CkCanvas beginRecording(ui.Rect bounds) {
|
||||
_cullRect = bounds;
|
||||
final SkPictureRecorder recorder = _skRecorder = SkPictureRecorder();
|
||||
final SkRect skRect = toSkRect(bounds);
|
||||
final Float32List skRect = toSkRect(bounds);
|
||||
final SkCanvas skCanvas = recorder.beginRecording(skRect);
|
||||
return _recordingCanvas = CkCanvas(skCanvas);
|
||||
}
|
||||
|
||||
@ -29,15 +29,23 @@ class CkParagraphStyle implements ui.ParagraphStyle {
|
||||
textHeightBehavior,
|
||||
fontWeight,
|
||||
fontStyle,
|
||||
strutStyle,
|
||||
ellipsis,
|
||||
locale,
|
||||
) {
|
||||
_textDirection = textDirection ?? ui.TextDirection.ltr;
|
||||
_fontFamily = fontFamily;
|
||||
_fontSize = fontSize;
|
||||
_fontWeight = fontWeight;
|
||||
_fontStyle = fontStyle;
|
||||
}
|
||||
|
||||
SkParagraphStyle skParagraphStyle;
|
||||
ui.TextDirection? _textDirection;
|
||||
String? _fontFamily;
|
||||
double? _fontSize;
|
||||
ui.FontWeight? _fontWeight;
|
||||
ui.FontStyle? _fontStyle;
|
||||
|
||||
static SkTextStyleProperties toSkTextStyleProperties(
|
||||
String? fontFamily,
|
||||
@ -63,6 +71,46 @@ class CkParagraphStyle implements ui.ParagraphStyle {
|
||||
return skTextStyle;
|
||||
}
|
||||
|
||||
static SkStrutStyleProperties toSkStrutStyleProperties(ui.StrutStyle value) {
|
||||
EngineStrutStyle style = value as EngineStrutStyle;
|
||||
final SkStrutStyleProperties skStrutStyle = SkStrutStyleProperties();
|
||||
if (style._fontFamily != null) {
|
||||
final List<String> fontFamilies = <String>[style._fontFamily!];
|
||||
if (style._fontFamilyFallback != null) {
|
||||
fontFamilies.addAll(style._fontFamilyFallback!);
|
||||
}
|
||||
skStrutStyle.fontFamilies = fontFamilies;
|
||||
} else {
|
||||
// If no strut font family is given, default to Roboto.
|
||||
skStrutStyle.fontFamilies = ['Roboto'];
|
||||
}
|
||||
|
||||
if (style._fontSize != null) {
|
||||
skStrutStyle.fontSize = style._fontSize;
|
||||
}
|
||||
|
||||
if (style._height != null) {
|
||||
skStrutStyle.heightMultiplier = style._height;
|
||||
}
|
||||
|
||||
if (style._leading != null) {
|
||||
skStrutStyle.leading = style._leading;
|
||||
}
|
||||
|
||||
if (style._fontWeight != null || style._fontStyle != null) {
|
||||
skStrutStyle.fontStyle =
|
||||
toSkFontStyle(style._fontWeight, style._fontStyle);
|
||||
}
|
||||
|
||||
if (style._forceStrutHeight != null) {
|
||||
skStrutStyle.forceStrutHeight = style._forceStrutHeight;
|
||||
}
|
||||
|
||||
skStrutStyle.strutEnabled = true;
|
||||
|
||||
return skStrutStyle;
|
||||
}
|
||||
|
||||
static SkParagraphStyle toSkParagraphStyle(
|
||||
ui.TextAlign? textAlign,
|
||||
ui.TextDirection? textDirection,
|
||||
@ -73,7 +121,9 @@ class CkParagraphStyle implements ui.ParagraphStyle {
|
||||
ui.TextHeightBehavior? textHeightBehavior,
|
||||
ui.FontWeight? fontWeight,
|
||||
ui.FontStyle? fontStyle,
|
||||
ui.StrutStyle? strutStyle,
|
||||
String? ellipsis,
|
||||
ui.Locale? locale,
|
||||
) {
|
||||
final SkParagraphStyleProperties properties = SkParagraphStyleProperties();
|
||||
|
||||
@ -85,6 +135,10 @@ class CkParagraphStyle implements ui.ParagraphStyle {
|
||||
properties.textDirection = toSkTextDirection(textDirection);
|
||||
}
|
||||
|
||||
if (maxLines != null) {
|
||||
properties.maxLines = maxLines;
|
||||
}
|
||||
|
||||
if (height != null) {
|
||||
properties.heightMultiplier = height;
|
||||
}
|
||||
@ -93,25 +147,52 @@ class CkParagraphStyle implements ui.ParagraphStyle {
|
||||
properties.textHeightBehavior = textHeightBehavior.encode();
|
||||
}
|
||||
|
||||
if (maxLines != null) {
|
||||
properties.maxLines = maxLines;
|
||||
}
|
||||
|
||||
if (ellipsis != null) {
|
||||
properties.ellipsis = ellipsis;
|
||||
}
|
||||
|
||||
if (strutStyle != null) {
|
||||
properties.strutStyle = toSkStrutStyleProperties(strutStyle);
|
||||
}
|
||||
|
||||
properties.textStyle =
|
||||
toSkTextStyleProperties(fontFamily, fontSize, fontWeight, fontStyle);
|
||||
|
||||
return canvasKit.ParagraphStyle(properties);
|
||||
}
|
||||
|
||||
CkTextStyle getTextStyle() {
|
||||
return CkTextStyle(
|
||||
fontFamily: _fontFamily,
|
||||
fontSize: _fontSize,
|
||||
fontWeight: _fontWeight,
|
||||
fontStyle: _fontStyle,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CkTextStyle implements ui.TextStyle {
|
||||
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<String>? fontFamilyFallback;
|
||||
double? fontSize;
|
||||
double? letterSpacing;
|
||||
double? wordSpacing;
|
||||
double? height;
|
||||
ui.Locale? locale;
|
||||
CkPaint? background;
|
||||
CkPaint? foreground;
|
||||
List<ui.Shadow>? shadows;
|
||||
List<ui.FontFeature>? fontFeatures;
|
||||
|
||||
factory CkTextStyle({
|
||||
ui.Color? color,
|
||||
@ -162,10 +243,38 @@ class CkTextStyle implements ui.TextStyle {
|
||||
properties.decorationThickness = decorationThickness;
|
||||
}
|
||||
|
||||
if (decorationColor != null) {
|
||||
properties.decorationColor = makeFreshSkColor(decorationColor);
|
||||
}
|
||||
|
||||
if (decorationStyle != null) {
|
||||
properties.decorationStyle = toSkTextDecorationStyle(decorationStyle);
|
||||
}
|
||||
|
||||
if (textBaseline != null) {
|
||||
properties.textBaseline = toSkTextBaseline(textBaseline);
|
||||
}
|
||||
|
||||
if (fontSize != null) {
|
||||
properties.fontSize = fontSize;
|
||||
}
|
||||
|
||||
if (letterSpacing != null) {
|
||||
properties.letterSpacing = letterSpacing;
|
||||
}
|
||||
|
||||
if (wordSpacing != null) {
|
||||
properties.wordSpacing = wordSpacing;
|
||||
}
|
||||
|
||||
if (height != null) {
|
||||
properties.heightMultiplier = height;
|
||||
}
|
||||
|
||||
if (locale != null) {
|
||||
properties.locale = locale.toLanguageTag();
|
||||
}
|
||||
|
||||
if (fontFamily == null ||
|
||||
!skiaFontCollection.registeredFamilies.contains(fontFamily)) {
|
||||
fontFamily = 'Roboto';
|
||||
@ -187,21 +296,103 @@ class CkTextStyle implements ui.TextStyle {
|
||||
properties.foregroundColor = makeFreshSkColor(foreground.color);
|
||||
}
|
||||
|
||||
// TODO(hterkelsen): Add support for
|
||||
// - decorationColor
|
||||
// - decorationStyle
|
||||
// - textBaseline
|
||||
// - letterSpacing
|
||||
// - wordSpacing
|
||||
// - height
|
||||
// - locale
|
||||
// - shadows
|
||||
// - fontFeatures
|
||||
if (shadows != null) {
|
||||
List<SkTextShadow> ckShadows = <SkTextShadow>[];
|
||||
for (ui.Shadow shadow in shadows) {
|
||||
final ckShadow = SkTextShadow();
|
||||
ckShadow.color = makeFreshSkColor(shadow.color);
|
||||
ckShadow.offset = toSkPoint(shadow.offset);
|
||||
ckShadow.blurRadius = shadow.blurRadius;
|
||||
ckShadows.add(ckShadow);
|
||||
}
|
||||
properties.shadows = ckShadows;
|
||||
}
|
||||
|
||||
if (fontFeatures != null) {
|
||||
List<SkFontFeature> ckFontFeatures = <SkFontFeature>[];
|
||||
for (ui.FontFeature fontFeature in fontFeatures) {
|
||||
SkFontFeature ckFontFeature = SkFontFeature();
|
||||
ckFontFeature.name = fontFeature.feature;
|
||||
ckFontFeature.value = fontFeature.value;
|
||||
ckFontFeatures.add(ckFontFeature);
|
||||
}
|
||||
properties.fontFeatures = ckFontFeatures;
|
||||
}
|
||||
|
||||
return CkTextStyle._(
|
||||
canvasKit.TextStyle(properties), foreground, background);
|
||||
canvasKit.TextStyle(properties),
|
||||
color,
|
||||
decoration,
|
||||
decorationColor,
|
||||
decorationStyle,
|
||||
decorationThickness,
|
||||
fontWeight,
|
||||
fontStyle,
|
||||
textBaseline,
|
||||
fontFamily,
|
||||
fontFamilyFallback,
|
||||
fontSize,
|
||||
letterSpacing,
|
||||
wordSpacing,
|
||||
height,
|
||||
locale,
|
||||
background,
|
||||
foreground,
|
||||
shadows,
|
||||
fontFeatures,
|
||||
);
|
||||
}
|
||||
|
||||
CkTextStyle._(this.skTextStyle, this.foreground, this.background);
|
||||
/// Merges this text style with [other] and returns the new text style.
|
||||
///
|
||||
/// The values in this text style are used unless [other] specifically
|
||||
/// overrides it.
|
||||
CkTextStyle mergeWith(CkTextStyle other) {
|
||||
return CkTextStyle(
|
||||
color: other.color ?? color,
|
||||
decoration: other.decoration ?? decoration,
|
||||
decorationColor: other.decorationColor ?? decorationColor,
|
||||
decorationStyle: other.decorationStyle ?? decorationStyle,
|
||||
decorationThickness: other.decorationThickness ?? decorationThickness,
|
||||
fontWeight: other.fontWeight ?? fontWeight,
|
||||
fontStyle: other.fontStyle ?? fontStyle,
|
||||
textBaseline: other.textBaseline ?? textBaseline,
|
||||
fontFamily: other.fontFamily ?? fontFamily,
|
||||
fontFamilyFallback: other.fontFamilyFallback ?? fontFamilyFallback,
|
||||
fontSize: other.fontSize ?? fontSize,
|
||||
letterSpacing: other.letterSpacing ?? letterSpacing,
|
||||
wordSpacing: other.wordSpacing ?? wordSpacing,
|
||||
height: other.height ?? height,
|
||||
locale: other.locale ?? locale,
|
||||
background: other.background ?? background,
|
||||
foreground: other.foreground ?? foreground,
|
||||
shadows: other.shadows ?? shadows,
|
||||
fontFeatures: other.fontFeatures ?? fontFeatures,
|
||||
);
|
||||
}
|
||||
|
||||
CkTextStyle._(
|
||||
this.skTextStyle,
|
||||
this.color,
|
||||
this.decoration,
|
||||
this.decorationColor,
|
||||
this.decorationStyle,
|
||||
this.decorationThickness,
|
||||
this.fontWeight,
|
||||
this.fontStyle,
|
||||
this.textBaseline,
|
||||
this.fontFamily,
|
||||
this.fontFamilyFallback,
|
||||
this.fontSize,
|
||||
this.letterSpacing,
|
||||
this.wordSpacing,
|
||||
this.height,
|
||||
this.locale,
|
||||
this.background,
|
||||
this.foreground,
|
||||
this.shadows,
|
||||
this.fontFeatures,
|
||||
);
|
||||
}
|
||||
|
||||
SkFontStyle toSkFontStyle(ui.FontWeight? fontWeight, ui.FontStyle? fontStyle) {
|
||||
@ -260,6 +451,9 @@ class CkParagraph extends ManagedSkiaObject<SkParagraph>
|
||||
case _ParagraphCommandType.pushStyle:
|
||||
builder.pushStyle(command.style!);
|
||||
break;
|
||||
case _ParagraphCommandType.addPlaceholder:
|
||||
builder._addPlaceholder(command.placeholderStyle!);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,10 +498,10 @@ class CkParagraph extends ManagedSkiaObject<SkParagraph>
|
||||
@override
|
||||
double get width => skiaObject.getMaxWidth();
|
||||
|
||||
// TODO(hterkelsen): Implement placeholders once it's in CanvasKit
|
||||
@override
|
||||
List<ui.TextBox> getBoxesForPlaceholders() {
|
||||
return const <ui.TextBox>[];
|
||||
List<List<double>> skRects = skiaObject.getRectsForPlaceholders();
|
||||
return skRectsToTextBoxes(skRects);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -321,22 +515,26 @@ class CkParagraph extends ManagedSkiaObject<SkParagraph>
|
||||
return const <ui.TextBox>[];
|
||||
}
|
||||
|
||||
List<SkRect> skRects = skiaObject.getRectsForRange(
|
||||
List<List<double>> skRects = skiaObject.getRectsForRange(
|
||||
start,
|
||||
end,
|
||||
toSkRectHeightStyle(boxHeightStyle),
|
||||
toSkRectWidthStyle(boxWidthStyle),
|
||||
);
|
||||
|
||||
return skRectsToTextBoxes(skRects);
|
||||
}
|
||||
|
||||
List<ui.TextBox> skRectsToTextBoxes(List<List<double>> skRects) {
|
||||
List<ui.TextBox> result = <ui.TextBox>[];
|
||||
|
||||
for (int i = 0; i < skRects.length; i++) {
|
||||
final SkRect rect = skRects[i];
|
||||
final List<double> rect = skRects[i];
|
||||
result.add(ui.TextBox.fromLTRBD(
|
||||
rect.fLeft,
|
||||
rect.fTop,
|
||||
rect.fRight,
|
||||
rect.fBottom,
|
||||
rect[0],
|
||||
rect[1],
|
||||
rect[2],
|
||||
rect[3],
|
||||
_paragraphStyle._textDirection!,
|
||||
));
|
||||
}
|
||||
@ -404,16 +602,21 @@ class CkParagraphBuilder implements ui.ParagraphBuilder {
|
||||
final SkParagraphBuilder _paragraphBuilder;
|
||||
final CkParagraphStyle _style;
|
||||
final List<_ParagraphCommand> _commands;
|
||||
int _placeholderCount;
|
||||
final List<double> _placeholderScales;
|
||||
final List<CkTextStyle> _styleStack;
|
||||
|
||||
CkParagraphBuilder(ui.ParagraphStyle style)
|
||||
: _commands = <_ParagraphCommand>[],
|
||||
_style = style as CkParagraphStyle,
|
||||
_placeholderCount = 0,
|
||||
_placeholderScales = <double>[],
|
||||
_styleStack = <CkTextStyle>[],
|
||||
_paragraphBuilder = canvasKit.ParagraphBuilder.MakeFromFontProvider(
|
||||
style.skParagraphStyle,
|
||||
skiaFontCollection.fontProvider,
|
||||
);
|
||||
|
||||
// TODO(hterkelsen): Implement placeholders.
|
||||
@override
|
||||
void addPlaceholder(
|
||||
double width,
|
||||
@ -423,7 +626,44 @@ class CkParagraphBuilder implements ui.ParagraphBuilder {
|
||||
double? baselineOffset,
|
||||
ui.TextBaseline? baseline,
|
||||
}) {
|
||||
throw UnimplementedError('addPlaceholder');
|
||||
// Require a baseline to be specified if using a baseline-based alignment.
|
||||
assert((alignment == ui.PlaceholderAlignment.aboveBaseline ||
|
||||
alignment == ui.PlaceholderAlignment.belowBaseline ||
|
||||
alignment == ui.PlaceholderAlignment.baseline)
|
||||
? baseline != null
|
||||
: true);
|
||||
|
||||
_placeholderCount++;
|
||||
_placeholderScales.add(scale);
|
||||
SkPlaceholderStyleProperties placeholderStyle = toSkPlaceholderStyle(
|
||||
width * scale,
|
||||
height * scale,
|
||||
alignment,
|
||||
(baselineOffset ?? height) * scale,
|
||||
baseline ?? ui.TextBaseline.alphabetic,
|
||||
);
|
||||
_addPlaceholder(placeholderStyle);
|
||||
}
|
||||
|
||||
void _addPlaceholder(SkPlaceholderStyleProperties placeholderStyle) {
|
||||
_commands.add(_ParagraphCommand.addPlaceholder(placeholderStyle));
|
||||
_paragraphBuilder.addPlaceholder(placeholderStyle);
|
||||
}
|
||||
|
||||
static SkPlaceholderStyleProperties toSkPlaceholderStyle(
|
||||
double width,
|
||||
double height,
|
||||
ui.PlaceholderAlignment alignment,
|
||||
double baselineOffset,
|
||||
ui.TextBaseline baseline,
|
||||
) {
|
||||
final properties = SkPlaceholderStyleProperties();
|
||||
properties.width = width;
|
||||
properties.height = height;
|
||||
properties.alignment = toSkPlaceholderAlignment(alignment);
|
||||
properties.offset = baselineOffset;
|
||||
properties.baseline = toSkTextBaseline(baseline);
|
||||
return properties;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -446,22 +686,28 @@ class CkParagraphBuilder implements ui.ParagraphBuilder {
|
||||
}
|
||||
|
||||
@override
|
||||
int get placeholderCount => throw UnimplementedError('placeholderCount');
|
||||
int get placeholderCount => _placeholderCount;
|
||||
|
||||
// TODO(hterkelsen): Implement this once CanvasKit exposes placeholders.
|
||||
@override
|
||||
List<double> get placeholderScales => const <double>[];
|
||||
List<double> get placeholderScales => _placeholderScales;
|
||||
|
||||
@override
|
||||
void pop() {
|
||||
_commands.add(const _ParagraphCommand.pop());
|
||||
_styleStack.removeLast();
|
||||
_paragraphBuilder.pop();
|
||||
}
|
||||
|
||||
CkTextStyle _peekStyle() =>
|
||||
_styleStack.isEmpty ? _style.getTextStyle() : _styleStack.last;
|
||||
|
||||
@override
|
||||
void pushStyle(ui.TextStyle style) {
|
||||
final CkTextStyle skStyle = style as CkTextStyle;
|
||||
_commands.add(_ParagraphCommand.pushStyle(skStyle));
|
||||
final CkTextStyle baseStyle = _peekStyle();
|
||||
final CkTextStyle ckStyle = style as CkTextStyle;
|
||||
final CkTextStyle skStyle = baseStyle.mergeWith(ckStyle);
|
||||
_styleStack.add(skStyle);
|
||||
_commands.add(_ParagraphCommand.pushStyle(ckStyle));
|
||||
if (skStyle.foreground != null || skStyle.background != null) {
|
||||
final SkPaint foreground = skStyle.foreground?.skiaObject ?? SkPaint();
|
||||
final SkPaint background = skStyle.background?.skiaObject ?? SkPaint();
|
||||
@ -477,20 +723,33 @@ class _ParagraphCommand {
|
||||
final _ParagraphCommandType type;
|
||||
final String? text;
|
||||
final CkTextStyle? style;
|
||||
final SkPlaceholderStyleProperties? placeholderStyle;
|
||||
|
||||
const _ParagraphCommand._(this.type, this.text, this.style);
|
||||
const _ParagraphCommand._(
|
||||
this.type,
|
||||
this.text,
|
||||
this.style,
|
||||
this.placeholderStyle,
|
||||
);
|
||||
|
||||
const _ParagraphCommand.addText(String text)
|
||||
: this._(_ParagraphCommandType.addText, text, null);
|
||||
: this._(_ParagraphCommandType.addText, text, null, null);
|
||||
|
||||
const _ParagraphCommand.pop() : this._(_ParagraphCommandType.pop, null, null);
|
||||
const _ParagraphCommand.pop()
|
||||
: this._(_ParagraphCommandType.pop, null, null, null);
|
||||
|
||||
const _ParagraphCommand.pushStyle(CkTextStyle style)
|
||||
: this._(_ParagraphCommandType.pushStyle, null, style);
|
||||
: this._(_ParagraphCommandType.pushStyle, null, style, null);
|
||||
|
||||
const _ParagraphCommand.addPlaceholder(
|
||||
SkPlaceholderStyleProperties placeholderStyle)
|
||||
: this._(
|
||||
_ParagraphCommandType.addPlaceholder, null, null, placeholderStyle);
|
||||
}
|
||||
|
||||
enum _ParagraphCommandType {
|
||||
addText,
|
||||
pop,
|
||||
pushStyle,
|
||||
addPlaceholder,
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ void testMain() {
|
||||
_toSkPointTests();
|
||||
_toSkColorStopsTests();
|
||||
_toSkMatrixFromFloat32Tests();
|
||||
_skSkRectTests();
|
||||
_toSkRectTests();
|
||||
_skVerticesTests();
|
||||
group('SkPath', () {
|
||||
_pathTests();
|
||||
@ -59,7 +59,10 @@ void testMain() {
|
||||
group('SkCanvas', () {
|
||||
_canvasTests();
|
||||
});
|
||||
// TODO: https://github.com/flutter/flutter/issues/60040
|
||||
group('SkParagraph', () {
|
||||
_textStyleTests();
|
||||
});
|
||||
// TODO: https://github.com/flutter/flutter/issues/60040
|
||||
}, skip: isIosSafari);
|
||||
}
|
||||
|
||||
@ -203,11 +206,13 @@ void _fillTypeTests() {
|
||||
|
||||
void _pathOpTests() {
|
||||
test('path op mapping is correct', () {
|
||||
expect(canvasKit.PathOp.Difference.value, ui.PathOperation.difference.index);
|
||||
expect(
|
||||
canvasKit.PathOp.Difference.value, ui.PathOperation.difference.index);
|
||||
expect(canvasKit.PathOp.Intersect.value, ui.PathOperation.intersect.index);
|
||||
expect(canvasKit.PathOp.Union.value, ui.PathOperation.union.index);
|
||||
expect(canvasKit.PathOp.XOR.value, ui.PathOperation.xor.index);
|
||||
expect(canvasKit.PathOp.ReverseDifference.value, ui.PathOperation.reverseDifference.index);
|
||||
expect(canvasKit.PathOp.ReverseDifference.value,
|
||||
ui.PathOperation.reverseDifference.index);
|
||||
});
|
||||
|
||||
test('ui.PathOperation converts to SkPathOp', () {
|
||||
@ -269,8 +274,10 @@ void _pointModeTests() {
|
||||
void _vertexModeTests() {
|
||||
test('vertex mode mapping is correct', () {
|
||||
expect(canvasKit.VertexMode.Triangles.value, ui.VertexMode.triangles.index);
|
||||
expect(canvasKit.VertexMode.TrianglesStrip.value, ui.VertexMode.triangleStrip.index);
|
||||
expect(canvasKit.VertexMode.TriangleFan.value, ui.VertexMode.triangleFan.index);
|
||||
expect(canvasKit.VertexMode.TrianglesStrip.value,
|
||||
ui.VertexMode.triangleStrip.index);
|
||||
expect(canvasKit.VertexMode.TriangleFan.value,
|
||||
ui.VertexMode.triangleFan.index);
|
||||
});
|
||||
|
||||
test('ui.VertexMode converts to SkVertexMode', () {
|
||||
@ -282,7 +289,8 @@ void _vertexModeTests() {
|
||||
|
||||
void _imageTests() {
|
||||
test('MakeAnimatedImageFromEncoded makes a non-animated image', () {
|
||||
final SkAnimatedImage nonAnimated = canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
|
||||
final SkAnimatedImage nonAnimated =
|
||||
canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
|
||||
expect(nonAnimated.getFrameCount(), 1);
|
||||
expect(nonAnimated.getRepetitionCount(), 0);
|
||||
expect(nonAnimated.width(), 1);
|
||||
@ -304,9 +312,10 @@ void _imageTests() {
|
||||
});
|
||||
|
||||
test('MakeAnimatedImageFromEncoded makes an animated image', () {
|
||||
final SkAnimatedImage animated = canvasKit.MakeAnimatedImageFromEncoded(kAnimatedGif);
|
||||
final SkAnimatedImage animated =
|
||||
canvasKit.MakeAnimatedImageFromEncoded(kAnimatedGif);
|
||||
expect(animated.getFrameCount(), 3);
|
||||
expect(animated.getRepetitionCount(), -1); // animates forever
|
||||
expect(animated.getRepetitionCount(), -1); // animates forever
|
||||
expect(animated.width(), 1);
|
||||
expect(animated.height(), 1);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
@ -324,35 +333,39 @@ void _shaderTests() {
|
||||
});
|
||||
|
||||
test('MakeRadialGradient', () {
|
||||
expect(canvasKit.SkShader.MakeRadialGradient(
|
||||
Float32List.fromList([1, 1]),
|
||||
10.0,
|
||||
<Float32List>[
|
||||
Float32List.fromList([0, 0, 0, 1]),
|
||||
Float32List.fromList([1, 1, 1, 1]),
|
||||
],
|
||||
Float32List.fromList([0, 1]),
|
||||
canvasKit.TileMode.Repeat,
|
||||
toSkMatrixFromFloat32(Matrix4.identity().storage),
|
||||
0,
|
||||
), isNotNull);
|
||||
expect(
|
||||
canvasKit.SkShader.MakeRadialGradient(
|
||||
Float32List.fromList([1, 1]),
|
||||
10.0,
|
||||
<Float32List>[
|
||||
Float32List.fromList([0, 0, 0, 1]),
|
||||
Float32List.fromList([1, 1, 1, 1]),
|
||||
],
|
||||
Float32List.fromList([0, 1]),
|
||||
canvasKit.TileMode.Repeat,
|
||||
toSkMatrixFromFloat32(Matrix4.identity().storage),
|
||||
0,
|
||||
),
|
||||
isNotNull);
|
||||
});
|
||||
|
||||
test('MakeTwoPointConicalGradient', () {
|
||||
expect(canvasKit.SkShader.MakeTwoPointConicalGradient(
|
||||
Float32List.fromList([1, 1]),
|
||||
10.0,
|
||||
Float32List.fromList([1, 1]),
|
||||
10.0,
|
||||
<Float32List>[
|
||||
Float32List.fromList([0, 0, 0, 1]),
|
||||
Float32List.fromList([1, 1, 1, 1]),
|
||||
],
|
||||
Float32List.fromList([0, 1]),
|
||||
canvasKit.TileMode.Repeat,
|
||||
toSkMatrixFromFloat32(Matrix4.identity().storage),
|
||||
0,
|
||||
), isNotNull);
|
||||
expect(
|
||||
canvasKit.SkShader.MakeTwoPointConicalGradient(
|
||||
Float32List.fromList([1, 1]),
|
||||
10.0,
|
||||
Float32List.fromList([1, 1]),
|
||||
10.0,
|
||||
<Float32List>[
|
||||
Float32List.fromList([0, 0, 0, 1]),
|
||||
Float32List.fromList([1, 1, 1, 1]),
|
||||
],
|
||||
Float32List.fromList([0, 1]),
|
||||
canvasKit.TileMode.Repeat,
|
||||
toSkMatrixFromFloat32(Matrix4.identity().storage),
|
||||
0,
|
||||
),
|
||||
isNotNull);
|
||||
});
|
||||
}
|
||||
|
||||
@ -398,11 +411,13 @@ void _paintTests() {
|
||||
|
||||
void _maskFilterTests() {
|
||||
test('MakeBlurMaskFilter', () {
|
||||
expect(canvasKit.MakeBlurMaskFilter(
|
||||
canvasKit.BlurStyle.Outer,
|
||||
5.0,
|
||||
false,
|
||||
), isNotNull);
|
||||
expect(
|
||||
canvasKit.MakeBlurMaskFilter(
|
||||
canvasKit.BlurStyle.Outer,
|
||||
5.0,
|
||||
false,
|
||||
),
|
||||
isNotNull);
|
||||
});
|
||||
}
|
||||
|
||||
@ -543,18 +558,44 @@ void _toSkMatrixFromFloat32Tests() {
|
||||
..translate(1, 2, 3)
|
||||
..rotateZ(4);
|
||||
expect(
|
||||
toSkMatrixFromFloat32(matrix.storage),
|
||||
Float32List.fromList(<double>[
|
||||
-0.6536436080932617,
|
||||
0.756802499294281,
|
||||
toSkMatrixFromFloat32(matrix.storage),
|
||||
Float32List.fromList(<double>[
|
||||
-0.6536436080932617,
|
||||
0.756802499294281,
|
||||
1,
|
||||
-0.756802499294281,
|
||||
-0.6536436080932617,
|
||||
2,
|
||||
-0.0,
|
||||
0,
|
||||
1,
|
||||
]));
|
||||
});
|
||||
}
|
||||
|
||||
void _toSkRectTests() {
|
||||
test('toSkRect', () {
|
||||
expect(toSkRect(ui.Rect.fromLTRB(1, 2, 3, 4)), [1, 2, 3, 4]);
|
||||
});
|
||||
|
||||
test('fromSkRect', () {
|
||||
expect(fromSkRect(Float32List.fromList([1, 2, 3, 4])),
|
||||
ui.Rect.fromLTRB(1, 2, 3, 4));
|
||||
});
|
||||
|
||||
test('toSkRRect', () {
|
||||
expect(
|
||||
toSkRRect(ui.RRect.fromLTRBAndCorners(
|
||||
1,
|
||||
-0.756802499294281,
|
||||
-0.6536436080932617,
|
||||
2,
|
||||
-0.0,
|
||||
0,
|
||||
1,
|
||||
])
|
||||
3,
|
||||
4,
|
||||
topLeft: ui.Radius.elliptical(5, 6),
|
||||
topRight: ui.Radius.elliptical(7, 8),
|
||||
bottomRight: ui.Radius.elliptical(9, 10),
|
||||
bottomLeft: ui.Radius.elliptical(11, 12),
|
||||
)),
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
|
||||
);
|
||||
});
|
||||
}
|
||||
@ -581,7 +622,7 @@ void _pathTests() {
|
||||
|
||||
test('addArc', () {
|
||||
path.addArc(
|
||||
SkRect(fLeft: 10, fTop: 20, fRight: 30, fBottom: 40),
|
||||
toSkRect(ui.Rect.fromLTRB(10, 20, 30, 40)),
|
||||
1,
|
||||
5,
|
||||
);
|
||||
@ -589,7 +630,7 @@ void _pathTests() {
|
||||
|
||||
test('addOval', () {
|
||||
path.addOval(
|
||||
SkRect(fLeft: 10, fTop: 20, fRight: 30, fBottom: 40),
|
||||
toSkRect(ui.Rect.fromLTRB(10, 20, 30, 40)),
|
||||
false,
|
||||
1,
|
||||
);
|
||||
@ -608,36 +649,24 @@ void _pathTests() {
|
||||
freeFloat32List(encodedPoints);
|
||||
});
|
||||
|
||||
test('addRoundRect', () {
|
||||
test('addRRect', () {
|
||||
final ui.RRect rrect = ui.RRect.fromRectAndRadius(
|
||||
ui.Rect.fromLTRB(10, 10, 20, 20),
|
||||
ui.Radius.circular(3),
|
||||
);
|
||||
final SkFloat32List skRadii = mallocFloat32List(8);
|
||||
final Float32List radii = skRadii.toTypedArray();
|
||||
radii[0] = rrect.tlRadiusX;
|
||||
radii[1] = rrect.tlRadiusY;
|
||||
radii[2] = rrect.trRadiusX;
|
||||
radii[3] = rrect.trRadiusY;
|
||||
radii[4] = rrect.brRadiusX;
|
||||
radii[5] = rrect.brRadiusY;
|
||||
radii[6] = rrect.blRadiusX;
|
||||
radii[7] = rrect.blRadiusY;
|
||||
path.addRoundRect(
|
||||
toOuterSkRect(rrect),
|
||||
radii,
|
||||
path.addRRect(
|
||||
toSkRRect(rrect),
|
||||
false,
|
||||
);
|
||||
freeFloat32List(skRadii);
|
||||
});
|
||||
|
||||
test('addRect', () {
|
||||
path.addRect(SkRect(fLeft: 1, fTop: 2, fRight: 3, fBottom: 4));
|
||||
path.addRect(toSkRect(ui.Rect.fromLTRB(1, 2, 3, 4)));
|
||||
});
|
||||
|
||||
test('arcTo', () {
|
||||
path.arcToOval(
|
||||
SkRect(fLeft: 1, fTop: 2, fRight: 3, fBottom: 4),
|
||||
toSkRect(ui.Rect.fromLTRB(1, 2, 3, 4)),
|
||||
5,
|
||||
40,
|
||||
false,
|
||||
@ -676,7 +705,7 @@ void _pathTests() {
|
||||
|
||||
test('getBounds', () {
|
||||
final SkPath testPath = _testClosedSkPath();
|
||||
final ui.Rect bounds = testPath.getBounds().toRect();
|
||||
final ui.Rect bounds = fromSkRect(testPath.getBounds());
|
||||
expect(bounds, const ui.Rect.fromLTRB(10, 10, 20, 20));
|
||||
});
|
||||
|
||||
@ -726,13 +755,15 @@ void _pathTests() {
|
||||
|
||||
test('reset', () {
|
||||
final SkPath testPath = _testClosedSkPath();
|
||||
expect(testPath.getBounds().toRect(), const ui.Rect.fromLTRB(10, 10, 20, 20));
|
||||
expect(fromSkRect(testPath.getBounds()),
|
||||
const ui.Rect.fromLTRB(10, 10, 20, 20));
|
||||
testPath.reset();
|
||||
expect(testPath.getBounds().toRect(), ui.Rect.zero);
|
||||
expect(fromSkRect(testPath.getBounds()), ui.Rect.zero);
|
||||
});
|
||||
|
||||
test('toSVGString', () {
|
||||
expect(_testClosedSkPath().toSVGString(), 'M10 10L20 10L20 20L10 20L10 10Z');
|
||||
expect(
|
||||
_testClosedSkPath().toSVGString(), 'M10 10L20 10L20 20L10 20L10 10Z');
|
||||
});
|
||||
|
||||
test('isEmpty', () {
|
||||
@ -743,22 +774,24 @@ void _pathTests() {
|
||||
test('copy', () {
|
||||
final SkPath original = _testClosedSkPath();
|
||||
final SkPath copy = original.copy();
|
||||
expect(original.getBounds().toRect(), copy.getBounds().toRect());
|
||||
expect(fromSkRect(original.getBounds()), fromSkRect(copy.getBounds()));
|
||||
});
|
||||
|
||||
test('transform', () {
|
||||
path = _testClosedSkPath();
|
||||
path.transform(2, 0, 10, 0, 2, 10, 0, 0, 0);
|
||||
final ui.Rect transformedBounds = path.getBounds().toRect();
|
||||
final ui.Rect transformedBounds = fromSkRect(path.getBounds());
|
||||
expect(transformedBounds, ui.Rect.fromLTRB(30, 30, 50, 50));
|
||||
});
|
||||
|
||||
test('SkContourMeasureIter/SkContourMeasure', () {
|
||||
final SkContourMeasureIter iter = SkContourMeasureIter(_testClosedSkPath(), false, 0);
|
||||
final SkContourMeasureIter iter =
|
||||
SkContourMeasureIter(_testClosedSkPath(), false, 0);
|
||||
final SkContourMeasure measure1 = iter.next();
|
||||
expect(measure1.length(), 40);
|
||||
expect(measure1.getPosTan(5), Float32List.fromList(<double>[15, 10, 1, 0]));
|
||||
expect(measure1.getPosTan(15), Float32List.fromList(<double>[20, 15, 0, 1]));
|
||||
expect(
|
||||
measure1.getPosTan(15), Float32List.fromList(<double>[20, 15, 0, 1]));
|
||||
expect(measure1.isClosed(), true);
|
||||
|
||||
// Starting with a box path:
|
||||
@ -783,29 +816,13 @@ void _pathTests() {
|
||||
// | |
|
||||
// 20 +-----------+
|
||||
final SkPath segment = measure1.getSegment(5, 15, true);
|
||||
expect(segment.getBounds().toRect(), ui.Rect.fromLTRB(15, 10, 20, 15));
|
||||
expect(fromSkRect(segment.getBounds()), ui.Rect.fromLTRB(15, 10, 20, 15));
|
||||
|
||||
final SkContourMeasure measure2 = iter.next();
|
||||
expect(measure2, isNull);
|
||||
});
|
||||
}
|
||||
|
||||
void _skSkRectTests() {
|
||||
test('SkRect', () {
|
||||
final SkRect rect = SkRect(fLeft: 1, fTop: 2, fRight: 3, fBottom: 4);
|
||||
expect(rect.fLeft, 1);
|
||||
expect(rect.fTop, 2);
|
||||
expect(rect.fRight, 3);
|
||||
expect(rect.fBottom, 4);
|
||||
|
||||
final ui.Rect uiRect = rect.toRect();
|
||||
expect(uiRect.left, 1);
|
||||
expect(uiRect.top, 2);
|
||||
expect(uiRect.right, 3);
|
||||
expect(uiRect.bottom, 4);
|
||||
});
|
||||
}
|
||||
|
||||
SkVertices _testVertices() {
|
||||
return canvasKit.MakeSkVertices(
|
||||
canvasKit.VertexMode.Triangles,
|
||||
@ -840,12 +857,8 @@ void _canvasTests() {
|
||||
|
||||
setUp(() {
|
||||
recorder = SkPictureRecorder();
|
||||
canvas = recorder.beginRecording(SkRect(
|
||||
fLeft: 0,
|
||||
fTop: 0,
|
||||
fRight: 100,
|
||||
fBottom: 100,
|
||||
));
|
||||
canvas =
|
||||
recorder.beginRecording(toSkRect(ui.Rect.fromLTRB(0, 0, 100, 100)));
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
@ -866,33 +879,23 @@ void _canvasTests() {
|
||||
|
||||
test('saveLayer', () {
|
||||
canvas.saveLayer(
|
||||
SkRect(
|
||||
fLeft: 0,
|
||||
fTop: 0,
|
||||
fRight: 100,
|
||||
fBottom: 100,
|
||||
),
|
||||
SkPaint(),
|
||||
toSkRect(ui.Rect.fromLTRB(0, 0, 100, 100)),
|
||||
null,
|
||||
null,
|
||||
);
|
||||
});
|
||||
|
||||
test('SkCanvasSaveLayerWithoutBoundsOverload.saveLayer', () {
|
||||
final SkCanvasSaveLayerWithoutBoundsOverload override = canvas as SkCanvasSaveLayerWithoutBoundsOverload;
|
||||
override.saveLayer(SkPaint());
|
||||
test('saveLayer without bounds', () {
|
||||
canvas.saveLayer(SkPaint(), null, null, null);
|
||||
});
|
||||
|
||||
test('SkCanvasSaveLayerWithFilterOverload.saveLayer', () {
|
||||
final SkCanvasSaveLayerWithFilterOverload override = canvas as SkCanvasSaveLayerWithFilterOverload;
|
||||
override.saveLayer(
|
||||
test('saveLayer with filter', () {
|
||||
canvas.saveLayer(
|
||||
SkPaint(),
|
||||
toSkRect(ui.Rect.fromLTRB(0, 0, 100, 100)),
|
||||
canvasKit.SkImageFilter.MakeBlur(1, 2, canvasKit.TileMode.Repeat, null),
|
||||
0,
|
||||
SkRect(
|
||||
fLeft: 0,
|
||||
fTop: 0,
|
||||
fRight: 100,
|
||||
fBottom: 100,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
@ -910,22 +913,7 @@ void _canvasTests() {
|
||||
|
||||
test('clipRRect', () {
|
||||
canvas.clipRRect(
|
||||
SkRRect(
|
||||
rect: SkRect(
|
||||
fLeft: 0,
|
||||
fTop: 0,
|
||||
fRight: 100,
|
||||
fBottom: 100,
|
||||
),
|
||||
rx1: 1,
|
||||
ry1: 2,
|
||||
rx2: 3,
|
||||
ry2: 4,
|
||||
rx3: 5,
|
||||
ry3: 6,
|
||||
rx4: 7,
|
||||
ry4: 8,
|
||||
),
|
||||
Float32List.fromList([0, 0, 100, 100, 1, 2, 3, 4, 5, 6, 7, 8]),
|
||||
canvasKit.ClipOp.Intersect,
|
||||
true,
|
||||
);
|
||||
@ -933,12 +921,7 @@ void _canvasTests() {
|
||||
|
||||
test('clipRect', () {
|
||||
canvas.clipRect(
|
||||
SkRect(
|
||||
fLeft: 0,
|
||||
fTop: 0,
|
||||
fRight: 100,
|
||||
fBottom: 100,
|
||||
),
|
||||
Float32List.fromList([0, 0, 100, 100]),
|
||||
canvasKit.ClipOp.Intersect,
|
||||
true,
|
||||
);
|
||||
@ -946,12 +929,7 @@ void _canvasTests() {
|
||||
|
||||
test('drawArc', () {
|
||||
canvas.drawArc(
|
||||
SkRect(
|
||||
fLeft: 0,
|
||||
fTop: 0,
|
||||
fRight: 100,
|
||||
fBottom: 50,
|
||||
),
|
||||
Float32List.fromList([0, 0, 100, 50]),
|
||||
0,
|
||||
100,
|
||||
true,
|
||||
@ -960,7 +938,8 @@ void _canvasTests() {
|
||||
});
|
||||
|
||||
test('drawAtlas', () {
|
||||
final SkAnimatedImage image = canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
|
||||
final SkAnimatedImage image =
|
||||
canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
|
||||
canvas.drawAtlas(
|
||||
image.getCurrentFrame(),
|
||||
Float32List.fromList([0, 0, 1, 1]),
|
||||
@ -984,44 +963,15 @@ void _canvasTests() {
|
||||
|
||||
test('drawDRRect', () {
|
||||
canvas.drawDRRect(
|
||||
SkRRect(
|
||||
rect: SkRect(
|
||||
fLeft: 0,
|
||||
fTop: 0,
|
||||
fRight: 100,
|
||||
fBottom: 100,
|
||||
),
|
||||
rx1: 1,
|
||||
ry1: 2,
|
||||
rx2: 3,
|
||||
ry2: 4,
|
||||
rx3: 5,
|
||||
ry3: 6,
|
||||
rx4: 7,
|
||||
ry4: 8,
|
||||
),
|
||||
SkRRect(
|
||||
rect: SkRect(
|
||||
fLeft: 20,
|
||||
fTop: 20,
|
||||
fRight: 80,
|
||||
fBottom: 80,
|
||||
),
|
||||
rx1: 1,
|
||||
ry1: 2,
|
||||
rx2: 3,
|
||||
ry2: 4,
|
||||
rx3: 5,
|
||||
ry3: 6,
|
||||
rx4: 7,
|
||||
ry4: 8,
|
||||
),
|
||||
Float32List.fromList([0, 0, 100, 100, 1, 2, 3, 4, 5, 6, 7, 8]),
|
||||
Float32List.fromList([20, 20, 80, 80, 1, 2, 3, 4, 5, 6, 7, 8]),
|
||||
SkPaint(),
|
||||
);
|
||||
});
|
||||
|
||||
test('drawImage', () {
|
||||
final SkAnimatedImage image = canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
|
||||
final SkAnimatedImage image =
|
||||
canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
|
||||
canvas.drawImage(
|
||||
image.getCurrentFrame(),
|
||||
10,
|
||||
@ -1031,22 +981,24 @@ void _canvasTests() {
|
||||
});
|
||||
|
||||
test('drawImageRect', () {
|
||||
final SkAnimatedImage image = canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
|
||||
final SkAnimatedImage image =
|
||||
canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
|
||||
canvas.drawImageRect(
|
||||
image.getCurrentFrame(),
|
||||
SkRect(fLeft: 0, fTop: 0, fRight: 1, fBottom: 1),
|
||||
SkRect(fLeft: 0, fTop: 0, fRight: 1, fBottom: 1),
|
||||
Float32List.fromList([0, 0, 1, 1]),
|
||||
Float32List.fromList([0, 0, 1, 1]),
|
||||
SkPaint(),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test('drawImageNine', () {
|
||||
final SkAnimatedImage image = canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
|
||||
final SkAnimatedImage image =
|
||||
canvasKit.MakeAnimatedImageFromEncoded(kTransparentImage);
|
||||
canvas.drawImageNine(
|
||||
image.getCurrentFrame(),
|
||||
SkRect(fLeft: 0, fTop: 0, fRight: 1, fBottom: 1),
|
||||
SkRect(fLeft: 0, fTop: 0, fRight: 1, fBottom: 1),
|
||||
Float32List.fromList([0, 0, 1, 1]),
|
||||
Float32List.fromList([0, 0, 1, 1]),
|
||||
SkPaint(),
|
||||
);
|
||||
});
|
||||
@ -1056,7 +1008,7 @@ void _canvasTests() {
|
||||
});
|
||||
|
||||
test('drawOval', () {
|
||||
canvas.drawOval(SkRect(fLeft: 0, fTop: 0, fRight: 1, fBottom: 1), SkPaint());
|
||||
canvas.drawOval(Float32List.fromList([0, 0, 1, 1]), SkPaint());
|
||||
});
|
||||
|
||||
test('drawPaint', () {
|
||||
@ -1080,34 +1032,14 @@ void _canvasTests() {
|
||||
|
||||
test('drawRRect', () {
|
||||
canvas.drawRRect(
|
||||
SkRRect(
|
||||
rect: SkRect(
|
||||
fLeft: 0,
|
||||
fTop: 0,
|
||||
fRight: 100,
|
||||
fBottom: 100,
|
||||
),
|
||||
rx1: 1,
|
||||
ry1: 2,
|
||||
rx2: 3,
|
||||
ry2: 4,
|
||||
rx3: 5,
|
||||
ry3: 6,
|
||||
rx4: 7,
|
||||
ry4: 8,
|
||||
),
|
||||
Float32List.fromList([0, 0, 100, 100, 1, 2, 3, 4, 5, 6, 7, 8]),
|
||||
SkPaint(),
|
||||
);
|
||||
});
|
||||
|
||||
test('drawRect', () {
|
||||
canvas.drawRect(
|
||||
SkRect(
|
||||
fLeft: 0,
|
||||
fTop: 0,
|
||||
fRight: 100,
|
||||
fBottom: 100,
|
||||
),
|
||||
Float32List.fromList([0, 0, 100, 100]),
|
||||
SkPaint(),
|
||||
);
|
||||
});
|
||||
@ -1120,12 +1052,13 @@ void _canvasTests() {
|
||||
const double spotAlpha = 0.25;
|
||||
|
||||
final SkPath path = _testClosedSkPath();
|
||||
final ui.Rect bounds = path.getBounds().toRect();
|
||||
final ui.Rect bounds = fromSkRect(path.getBounds());
|
||||
final double shadowX = (bounds.left + bounds.right) / 2.0;
|
||||
final double shadowY = bounds.top - 600.0;
|
||||
|
||||
const ui.Color color = ui.Color(0xAABBCCDD);
|
||||
ui.Color inAmbient = color.withAlpha((color.alpha * ambientAlpha).round());
|
||||
ui.Color inAmbient =
|
||||
color.withAlpha((color.alpha * ambientAlpha).round());
|
||||
ui.Color inSpot = color.withAlpha((color.alpha * spotAlpha).round());
|
||||
|
||||
final SkTonalColors inTonalColors = SkTonalColors(
|
||||
@ -1138,8 +1071,7 @@ void _canvasTests() {
|
||||
|
||||
canvas.drawShadow(
|
||||
path,
|
||||
Float32List(3)
|
||||
..[2] = devicePixelRatio * elevation,
|
||||
Float32List(3)..[2] = devicePixelRatio * elevation,
|
||||
Float32List(3)
|
||||
..[0] = shadowX
|
||||
..[1] = shadowY
|
||||
@ -1186,12 +1118,8 @@ void _canvasTests() {
|
||||
|
||||
test('drawPicture', () {
|
||||
final SkPictureRecorder otherRecorder = SkPictureRecorder();
|
||||
final SkCanvas otherCanvas = otherRecorder.beginRecording(SkRect(
|
||||
fLeft: 0,
|
||||
fTop: 0,
|
||||
fRight: 100,
|
||||
fBottom: 100,
|
||||
));
|
||||
final SkCanvas otherCanvas =
|
||||
otherRecorder.beginRecording(Float32List.fromList([0, 0, 100, 100]));
|
||||
otherCanvas.drawLine(0, 0, 10, 10, SkPaint());
|
||||
canvas.drawPicture(otherRecorder.finishRecordingAsPicture());
|
||||
});
|
||||
@ -1212,26 +1140,79 @@ void _canvasTests() {
|
||||
|
||||
test('toImage.toByteData', () async {
|
||||
final SkPictureRecorder otherRecorder = SkPictureRecorder();
|
||||
final SkCanvas otherCanvas = otherRecorder.beginRecording(SkRect(
|
||||
fLeft: 0,
|
||||
fTop: 0,
|
||||
fRight: 1,
|
||||
fBottom: 1,
|
||||
));
|
||||
final SkCanvas otherCanvas =
|
||||
otherRecorder.beginRecording(Float32List.fromList([0, 0, 1, 1]));
|
||||
otherCanvas.drawRect(
|
||||
SkRect(
|
||||
fLeft: 0,
|
||||
fTop: 0,
|
||||
fRight: 1,
|
||||
fBottom: 1,
|
||||
),
|
||||
Float32List.fromList([0, 0, 1, 1]),
|
||||
SkPaint(),
|
||||
);
|
||||
final CkPicture picture = CkPicture(otherRecorder.finishRecordingAsPicture(), null);
|
||||
final CkPicture picture =
|
||||
CkPicture(otherRecorder.finishRecordingAsPicture(), null);
|
||||
final CkImage image = await picture.toImage(1, 1);
|
||||
final ByteData rawData = await image.toByteData(format: ui.ImageByteFormat.rawRgba);
|
||||
final ByteData rawData =
|
||||
await image.toByteData(format: ui.ImageByteFormat.rawRgba);
|
||||
expect(rawData, isNotNull);
|
||||
final ByteData pngData = await image.toByteData(format: ui.ImageByteFormat.png);
|
||||
final ByteData pngData =
|
||||
await image.toByteData(format: ui.ImageByteFormat.png);
|
||||
expect(pngData, isNotNull);
|
||||
});
|
||||
}
|
||||
|
||||
void _textStyleTests() {
|
||||
test('SkTextDecorationStyle mapping is correct', () {
|
||||
expect(canvasKit.DecorationStyle.Solid.value,
|
||||
ui.TextDecorationStyle.solid.index);
|
||||
expect(canvasKit.DecorationStyle.Double.value,
|
||||
ui.TextDecorationStyle.double.index);
|
||||
expect(canvasKit.DecorationStyle.Dotted.value,
|
||||
ui.TextDecorationStyle.dotted.index);
|
||||
expect(canvasKit.DecorationStyle.Dashed.value,
|
||||
ui.TextDecorationStyle.dashed.index);
|
||||
expect(canvasKit.DecorationStyle.Wavy.value,
|
||||
ui.TextDecorationStyle.wavy.index);
|
||||
});
|
||||
|
||||
test('ui.TextDecorationStyle converts to SkTextDecorationStyle', () {
|
||||
for (ui.TextDecorationStyle decorationStyle
|
||||
in ui.TextDecorationStyle.values) {
|
||||
expect(toSkTextDecorationStyle(decorationStyle).value,
|
||||
decorationStyle.index);
|
||||
}
|
||||
});
|
||||
|
||||
test('SkTextBaseline mapping is correct', () {
|
||||
expect(canvasKit.TextBaseline.Alphabetic.value,
|
||||
ui.TextBaseline.alphabetic.index);
|
||||
expect(canvasKit.TextBaseline.Ideographic.value,
|
||||
ui.TextBaseline.ideographic.index);
|
||||
});
|
||||
|
||||
test('ui.TextBaseline converts to SkTextBaseline', () {
|
||||
for (ui.TextBaseline textBaseline in ui.TextBaseline.values) {
|
||||
expect(toSkTextBaseline(textBaseline).value, textBaseline.index);
|
||||
}
|
||||
});
|
||||
|
||||
test('SkPlaceholderAlignment mapping is correct', () {
|
||||
expect(canvasKit.PlaceholderAlignment.Baseline.value,
|
||||
ui.PlaceholderAlignment.baseline.index);
|
||||
expect(canvasKit.PlaceholderAlignment.AboveBaseline.value,
|
||||
ui.PlaceholderAlignment.aboveBaseline.index);
|
||||
expect(canvasKit.PlaceholderAlignment.BelowBaseline.value,
|
||||
ui.PlaceholderAlignment.belowBaseline.index);
|
||||
expect(canvasKit.PlaceholderAlignment.Top.value,
|
||||
ui.PlaceholderAlignment.top.index);
|
||||
expect(canvasKit.PlaceholderAlignment.Bottom.value,
|
||||
ui.PlaceholderAlignment.bottom.index);
|
||||
expect(canvasKit.PlaceholderAlignment.Middle.value,
|
||||
ui.PlaceholderAlignment.middle.index);
|
||||
});
|
||||
|
||||
test('ui.PlaceholderAlignment converts to SkPlaceholderAlignment', () {
|
||||
for (ui.PlaceholderAlignment placeholderAlignment
|
||||
in ui.PlaceholderAlignment.values) {
|
||||
expect(toSkPlaceholderAlignment(placeholderAlignment).value,
|
||||
placeholderAlignment.index);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user