blob: 53b9638069689a02c0fd47972c944d0c273ecd39 [file] [log] [blame] [edit]
// 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:typed_data';
import 'package:meta/meta.dart';
import 'package:test/test.dart';
import 'package:vector_graphics_codec/vector_graphics_codec.dart';
const VectorGraphicsCodec codec = VectorGraphicsCodec();
final Float64List mat4 = Float64List.fromList(
<double>[2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
void bufferContains(VectorGraphicsBuffer buffer, List<int> expectedBytes) {
final Uint8List data = buffer.done().buffer.asUint8List();
expect(data, equals(expectedBytes));
}
void main() {
test('Messages begin with a magic number and version', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
bufferContains(buffer, <int>[98, 45, 136, 0, 1]);
});
test('Messages without any contents cannot be decoded', () {
expect(
() => codec.decode(Uint8List(0).buffer.asByteData(), null),
throwsA(isA<StateError>().having(
(StateError se) => se.message,
'message',
contains(
'The provided data was not a vector_graphics binary asset.'))));
});
test('Messages without a magic number cannot be decoded', () {
expect(
() => codec.decode(Uint8List(6).buffer.asByteData(), null),
throwsA(isA<StateError>().having(
(StateError se) => se.message,
'message',
contains(
'The provided data was not a vector_graphics binary asset.'))));
});
test('Messages without an incompatible version cannot be decoded', () {
final Uint8List bytes = Uint8List(6);
bytes[0] = 98;
bytes[1] = 45;
bytes[2] = 136;
bytes[3] = 0;
bytes[4] = 6; // version 6.
expect(
() => codec.decode(bytes.buffer.asByteData(), null),
throwsA(isA<StateError>().having(
(StateError se) => se.message,
'message',
contains(
'he provided data does not match the currently supported version.'))));
});
test('Basic message encode and decode with filled path', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
final int paintId = codec.writeFill(buffer, 23, 0);
final int pathId = codec.writePath(
buffer,
Uint8List.fromList(<int>[
ControlPointTypes.moveTo,
ControlPointTypes.lineTo,
ControlPointTypes.close
]),
Float32List.fromList(<double>[1, 2, 2, 3]),
0,
);
codec.writeDrawPath(buffer, pathId, paintId, null);
codec.decode(buffer.done(), listener);
expect(listener.commands, <Object>[
OnPaintObject(
color: 23,
strokeCap: null,
strokeJoin: null,
blendMode: 0,
strokeMiterLimit: null,
strokeWidth: null,
paintStyle: 0,
id: paintId,
shaderId: null,
),
OnPathStart(pathId, 0),
const OnPathMoveTo(1, 2),
const OnPathLineTo(2, 3),
const OnPathClose(),
const OnPathFinished(),
OnDrawPath(pathId, paintId, null),
]);
});
test('Basic message encode and decode with shaded path', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
final int shaderId = codec.writeLinearGradient(
buffer,
fromX: 0,
fromY: 0,
toX: 1,
toY: 1,
colors: Int32List.fromList(<int>[0, 1]),
offsets: Float32List.fromList(<double>[0, 1]),
tileMode: 1,
);
final int fillId = codec.writeFill(buffer, 23, 0, shaderId);
final int strokeId =
codec.writeStroke(buffer, 44, 1, 2, 3, 4.0, 6.0, shaderId);
final int pathId = codec.writePath(
buffer,
Uint8List.fromList(<int>[
ControlPointTypes.moveTo,
ControlPointTypes.lineTo,
ControlPointTypes.close
]),
Float32List.fromList(<double>[1, 2, 2, 3]),
0,
);
codec.writeDrawPath(buffer, pathId, fillId, null);
codec.writeDrawPath(buffer, pathId, strokeId, null);
codec.decode(buffer.done(), listener);
expect(listener.commands, <Object>[
OnLinearGradient(
fromX: 0,
fromY: 0,
toX: 1,
toY: 1,
colors: Int32List.fromList(<int>[0, 1]),
offsets: Float32List.fromList(<double>[0, 1]),
tileMode: 1,
id: shaderId,
),
OnPaintObject(
color: 23,
strokeCap: null,
strokeJoin: null,
blendMode: 0,
strokeMiterLimit: null,
strokeWidth: null,
paintStyle: 0,
id: fillId,
shaderId: shaderId,
),
OnPaintObject(
color: 44,
strokeCap: 1,
strokeJoin: 2,
blendMode: 3,
strokeMiterLimit: 4.0,
strokeWidth: 6.0,
paintStyle: 1,
id: strokeId,
shaderId: shaderId,
),
OnPathStart(pathId, 0),
const OnPathMoveTo(1, 2),
const OnPathLineTo(2, 3),
const OnPathClose(),
const OnPathFinished(),
OnDrawPath(pathId, fillId, null),
OnDrawPath(pathId, strokeId, null),
]);
});
test('Basic message encode and decode with stroked vertex', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
final int paintId = codec.writeStroke(buffer, 44, 1, 2, 3, 4.0, 6.0);
codec.writeDrawVertices(
buffer,
Float32List.fromList(<double>[
0.0,
2.0,
3.0,
4.0,
2.0,
4.0,
]),
null,
paintId);
codec.decode(buffer.done(), listener);
expect(listener.commands, <Object>[
OnPaintObject(
color: 44,
strokeCap: 1,
strokeJoin: 2,
blendMode: 3,
strokeMiterLimit: 4.0,
strokeWidth: 6.0,
paintStyle: 1,
id: paintId,
shaderId: null,
),
OnDrawVertices(const <double>[
0.0,
2.0,
3.0,
4.0,
2.0,
4.0,
], null, paintId),
]);
});
test('Basic message encode and decode with stroked vertex and indexes', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
final int paintId = codec.writeStroke(buffer, 44, 1, 2, 3, 4.0, 6.0);
codec.writeDrawVertices(
buffer,
Float32List.fromList(<double>[
0.0,
2.0,
3.0,
4.0,
2.0,
4.0,
]),
Uint16List.fromList(<int>[
0,
1,
2,
3,
4,
5,
]),
paintId,
);
codec.decode(buffer.done(), listener);
expect(listener.commands, <Object>[
OnPaintObject(
color: 44,
strokeCap: 1,
strokeJoin: 2,
blendMode: 3,
strokeMiterLimit: 4.0,
strokeWidth: 6.0,
paintStyle: 1,
id: paintId,
shaderId: null,
),
OnDrawVertices(const <double>[
0.0,
2.0,
3.0,
4.0,
2.0,
4.0,
], const <int>[
0,
1,
2,
3,
4,
5,
], paintId),
]);
});
test('Can encode opacity/save/restore layers', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
final int paintId = codec.writeFill(buffer, 0xAA000000, 0);
codec.writeSaveLayer(buffer, paintId);
codec.writeRestoreLayer(buffer);
codec.decode(buffer.done(), listener);
expect(listener.commands, <Object>[
OnPaintObject(
color: 0xAA000000,
strokeCap: null,
strokeJoin: null,
blendMode: 0,
strokeMiterLimit: null,
strokeWidth: null,
paintStyle: 0,
id: paintId,
shaderId: null,
),
OnSaveLayer(paintId),
const OnRestoreLayer(),
]);
});
test('Can encode a radial gradient', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
final int shaderId = codec.writeRadialGradient(
buffer,
centerX: 2.0,
centerY: 3.0,
radius: 5.0,
focalX: 1.0,
focalY: 1.0,
colors: Int32List.fromList(<int>[0xFFAABBAA]),
offsets: Float32List.fromList(<double>[2.2, 1.2]),
tileMode: 0,
transform: mat4,
);
codec.decode(buffer.done(), listener);
expect(listener.commands, <OnRadialGradient>[
OnRadialGradient(
centerX: 2.0,
centerY: 3.0,
radius: 5.0,
focalX: 1.0,
focalY: 1.0,
colors: Int32List.fromList(<int>[0xFFAABBAA]),
offsets: Float32List.fromList(<double>[2.2, 1.2]),
transform: mat4,
tileMode: 0,
id: shaderId,
),
]);
});
test('Can encode a radial gradient (no matrix)', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
final int shaderId = codec.writeRadialGradient(
buffer,
centerX: 2.0,
centerY: 3.0,
radius: 5.0,
focalX: 1.0,
focalY: 1.0,
colors: Int32List.fromList(<int>[0xFFAABBAA]),
offsets: Float32List.fromList(<double>[2.2, 1.2]),
tileMode: 0,
transform: null,
);
codec.decode(buffer.done(), listener);
expect(listener.commands, <OnRadialGradient>[
OnRadialGradient(
centerX: 2.0,
centerY: 3.0,
radius: 5.0,
focalX: 1.0,
focalY: 1.0,
colors: Int32List.fromList(<int>[0xFFAABBAA]),
offsets: Float32List.fromList(<double>[2.2, 1.2]),
transform: null,
tileMode: 0,
id: shaderId,
),
]);
});
test('Can encode a linear gradient', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
final int shaderId = codec.writeLinearGradient(
buffer,
fromX: 2.0,
fromY: 3.0,
toX: 1.0,
toY: 1.0,
colors: Int32List.fromList(<int>[0xFFAABBAA]),
offsets: Float32List.fromList(<double>[2.2, 1.2]),
tileMode: 0,
);
codec.decode(buffer.done(), listener);
expect(listener.commands, <OnLinearGradient>[
OnLinearGradient(
fromX: 2.0,
fromY: 3.0,
toX: 1.0,
toY: 1.0,
colors: Int32List.fromList(<int>[0xFFAABBAA]),
offsets: Float32List.fromList(<double>[2.2, 1.2]),
tileMode: 0,
id: shaderId,
),
]);
});
test('Can encode clips', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
final int pathId = codec.writePath(
buffer,
Uint8List.fromList(<int>[
ControlPointTypes.lineTo,
ControlPointTypes.lineTo,
ControlPointTypes.lineTo,
ControlPointTypes.close,
]),
Float32List.fromList(<double>[0, 10, 20, 10, 20, 0]),
0,
);
codec.writeClipPath(buffer, pathId);
codec.writeRestoreLayer(buffer);
codec.decode(buffer.done(), listener);
expect(listener.commands, <Object>[
OnPathStart(pathId, 0),
const OnPathLineTo(0, 10),
const OnPathLineTo(20, 10),
const OnPathLineTo(20, 0),
const OnPathClose(),
const OnPathFinished(),
OnClipPath(pathId),
const OnRestoreLayer(),
]);
});
test('Can encode masks', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
codec.writeMask(buffer);
codec.decode(buffer.done(), listener);
expect(listener.commands, <OnMask>[const OnMask()]);
});
test('Encodes a size', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
codec.writeSize(buffer, 20, 30);
codec.decode(buffer.done(), listener);
expect(listener.commands, <OnSize>[const OnSize(20, 30)]);
});
test('Only supports a single size', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
codec.writeSize(buffer, 20, 30);
expect(() => codec.writeSize(buffer, 1, 1), throwsStateError);
});
test('Encodes text', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
final int paintId = codec.writeFill(buffer, 0xFFAABBAA, 0);
final int textId = codec.writeTextConfig(
buffer: buffer,
text: 'Hello',
fontFamily: 'Roboto',
xAnchorMultiplier: 0,
fontWeight: 0,
fontSize: 16,
decoration: 0,
decorationStyle: 0,
decorationColor: 0,
);
codec.writeDrawText(buffer, textId, paintId, null, null);
codec.decode(buffer.done(), listener);
expect(listener.commands, <Object>[
OnPaintObject(
color: 0xFFAABBAA,
strokeCap: null,
strokeJoin: null,
blendMode: 0,
strokeMiterLimit: null,
strokeWidth: null,
paintStyle: 0,
id: paintId,
shaderId: null,
),
OnTextConfig('Hello', 0, 16, 'Roboto', 0, 0, 0, 0, textId),
OnDrawText(textId, paintId, null, null),
]);
});
test('Encodes text with null font family', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
final int paintId = codec.writeFill(buffer, 0xFFAABBAA, 0);
final int textId = codec.writeTextConfig(
buffer: buffer,
text: 'Hello',
fontFamily: null,
xAnchorMultiplier: 0,
fontWeight: 0,
fontSize: 16,
decoration: 0,
decorationStyle: 0,
decorationColor: 0,
);
codec.writeDrawText(buffer, textId, paintId, null, null);
codec.decode(buffer.done(), listener);
expect(listener.commands, <Object>[
OnPaintObject(
color: 0xFFAABBAA,
strokeCap: null,
strokeJoin: null,
blendMode: 0,
strokeMiterLimit: null,
strokeWidth: null,
paintStyle: 0,
id: paintId,
shaderId: null,
),
OnTextConfig('Hello', 0, 16, null, 0, 0, 0, 0, textId),
OnDrawText(textId, paintId, null, null),
]);
});
test('Encodes empty text', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
final int paintId = codec.writeFill(buffer, 0xFFAABBAA, 0);
final int textId = codec.writeTextConfig(
buffer: buffer,
text: '',
fontFamily: null,
xAnchorMultiplier: 0,
fontWeight: 0,
fontSize: 16,
decoration: 0,
decorationStyle: 0,
decorationColor: 0,
);
codec.writeDrawText(buffer, textId, paintId, null, null);
codec.decode(buffer.done(), listener);
expect(listener.commands, <Object>[
OnPaintObject(
color: 0xFFAABBAA,
strokeCap: null,
strokeJoin: null,
blendMode: 0,
strokeMiterLimit: null,
strokeWidth: null,
paintStyle: 0,
id: paintId,
shaderId: null,
),
OnTextConfig('', 0, 16, null, 0, 0, 0, 0, textId),
OnDrawText(textId, paintId, null, null),
]);
});
test('Encodes text position', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
codec.writeTextPosition(buffer, 1, 2, 3, 4, true, mat4);
codec.decode(buffer.done(), listener);
expect(listener.commands, <Object>[
OnTextPosition(
id: 0,
x: 1,
y: 2,
dx: 3,
dy: 4,
reset: true,
transform: mat4,
),
]);
});
test('Encodes image data without transform', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
final int id =
codec.writeImage(buffer, 0, Uint8List.fromList(<int>[0, 1, 3, 4, 5]));
codec.writeDrawImage(buffer, id, 1, 2, 100, 100, null);
final ByteData data = buffer.done();
final DecodeResponse response = codec.decode(data, listener);
expect(response.complete, false);
expect(listener.commands, <OnImage>[
OnImage(id, 0, const <int>[0, 1, 3, 4, 5]),
]);
final DecodeResponse nextResponse =
codec.decode(data, listener, response: response);
expect(nextResponse.complete, true);
expect(listener.commands, <Object>[
OnImage(id, 0, const <int>[0, 1, 3, 4, 5]),
OnDrawImage(id, 1, 2, 100, 100, null),
]);
});
test('Encodes image data with transform', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
final int id =
codec.writeImage(buffer, 0, Uint8List.fromList(<int>[0, 1, 3, 4, 5]));
codec.writeDrawImage(buffer, id, 1, 2, 100, 100, mat4);
final ByteData data = buffer.done();
final DecodeResponse response = codec.decode(data, listener);
expect(response.complete, false);
expect(listener.commands, <OnImage>[
OnImage(id, 0, const <int>[0, 1, 3, 4, 5]),
]);
final DecodeResponse nextResponse =
codec.decode(data, listener, response: response);
expect(nextResponse.complete, true);
expect(listener.commands, <Object>[
OnImage(id, 0, const <int>[0, 1, 3, 4, 5]),
OnDrawImage(id, 1, 2, 100, 100, mat4),
]);
});
test('Encodes image data with various formats', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
for (final int format in ImageFormatTypes.values) {
expect(
codec.writeImage(
buffer, format, Uint8List.fromList(<int>[0, 1, 3, 4, 5])),
greaterThan(-1),
);
}
});
test('Basic message encode and decode with shaded path and image', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
final int imageId =
codec.writeImage(buffer, 0, Uint8List.fromList(<int>[0, 1, 3, 4, 5]));
final int shaderId = codec.writeLinearGradient(
buffer,
fromX: 0,
fromY: 0,
toX: 1,
toY: 1,
colors: Int32List.fromList(<int>[0, 1]),
offsets: Float32List.fromList(<double>[0, 1]),
tileMode: 1,
);
final int fillId = codec.writeFill(buffer, 23, 0, shaderId);
final int strokeId =
codec.writeStroke(buffer, 44, 1, 2, 3, 4.0, 6.0, shaderId);
final int pathId = codec.writePath(
buffer,
Uint8List.fromList(<int>[
ControlPointTypes.moveTo,
ControlPointTypes.lineTo,
ControlPointTypes.close
]),
Float32List.fromList(<double>[1, 2, 2, 3]),
0,
);
codec.writeDrawPath(buffer, pathId, fillId, null);
codec.writeDrawPath(buffer, pathId, strokeId, null);
codec.writeDrawImage(buffer, imageId, 1, 2, 100, 100, null);
final ByteData data = buffer.done();
DecodeResponse response = codec.decode(data, listener);
expect(response.complete, false);
expect(listener.commands, <Object>[
OnImage(
imageId,
0,
const <int>[0, 1, 3, 4, 5],
),
OnLinearGradient(
fromX: 0,
fromY: 0,
toX: 1,
toY: 1,
colors: Int32List.fromList(<int>[0, 1]),
offsets: Float32List.fromList(<double>[0, 1]),
tileMode: 1,
id: shaderId,
),
OnPaintObject(
color: 23,
strokeCap: null,
strokeJoin: null,
blendMode: 0,
strokeMiterLimit: null,
strokeWidth: null,
paintStyle: 0,
id: fillId,
shaderId: shaderId,
),
OnPaintObject(
color: 44,
strokeCap: 1,
strokeJoin: 2,
blendMode: 3,
strokeMiterLimit: 4.0,
strokeWidth: 6.0,
paintStyle: 1,
id: strokeId,
shaderId: shaderId,
),
OnPathStart(pathId, 0),
const OnPathMoveTo(1, 2),
const OnPathLineTo(2, 3),
const OnPathClose(),
const OnPathFinished(),
]);
response = codec.decode(data, listener, response: response);
expect(response.complete, true);
expect(listener.commands, <Object>[
OnImage(
imageId,
0,
const <int>[0, 1, 3, 4, 5],
),
OnLinearGradient(
fromX: 0,
fromY: 0,
toX: 1,
toY: 1,
colors: Int32List.fromList(<int>[0, 1]),
offsets: Float32List.fromList(<double>[0, 1]),
tileMode: 1,
id: shaderId,
),
OnPaintObject(
color: 23,
strokeCap: null,
strokeJoin: null,
blendMode: 0,
strokeMiterLimit: null,
strokeWidth: null,
paintStyle: 0,
id: fillId,
shaderId: shaderId,
),
OnPaintObject(
color: 44,
strokeCap: 1,
strokeJoin: 2,
blendMode: 3,
strokeMiterLimit: 4.0,
strokeWidth: 6.0,
paintStyle: 1,
id: strokeId,
shaderId: shaderId,
),
OnPathStart(pathId, 0),
const OnPathMoveTo(1, 2),
const OnPathLineTo(2, 3),
const OnPathClose(),
const OnPathFinished(),
OnDrawPath(pathId, fillId, null),
OnDrawPath(pathId, strokeId, null),
OnDrawImage(imageId, 1, 2, 100, 100, null),
]);
});
test('Basic message encode and decode with half precision path', () {
final VectorGraphicsBuffer buffer = VectorGraphicsBuffer();
final TestListener listener = TestListener();
final int fillId = codec.writeFill(buffer, 23, 0);
final int strokeId = codec.writeStroke(buffer, 44, 1, 2, 3, 4.0, 6.0);
final int pathId = codec.writePath(
buffer,
Uint8List.fromList(<int>[
ControlPointTypes.moveTo,
ControlPointTypes.lineTo,
ControlPointTypes.lineTo,
ControlPointTypes.close
]),
Float32List.fromList(<double>[1.25, 24.5, 200.10, -32.4, -10000, 2500.2]),
0,
half: true,
);
codec.writeDrawPath(buffer, pathId, fillId, null);
codec.writeDrawPath(buffer, pathId, strokeId, null);
final ByteData data = buffer.done();
final DecodeResponse response = codec.decode(data, listener);
expect(response.complete, true);
expect(listener.commands, <Object>[
OnPaintObject(
color: 23,
strokeCap: null,
strokeJoin: null,
blendMode: 0,
strokeMiterLimit: null,
strokeWidth: null,
paintStyle: 0,
id: fillId,
shaderId: null,
),
OnPaintObject(
color: 44,
strokeCap: 1,
strokeJoin: 2,
blendMode: 3,
strokeMiterLimit: 4.0,
strokeWidth: 6.0,
paintStyle: 1,
id: strokeId,
shaderId: null,
),
OnPathStart(pathId, 0),
const OnPathMoveTo(1.25, 24.5),
const OnPathLineTo(200.125, -32.40625),
const OnPathLineTo(-10000, 2500.0),
const OnPathClose(),
const OnPathFinished(),
const OnDrawPath(0, 0, null),
const OnDrawPath(0, 1, null),
]);
});
}
class TestListener extends VectorGraphicsCodecListener {
final List<Object> commands = <Object>[];
@override
void onDrawPath(int pathId, int? paintId, int? patternId) {
commands.add(OnDrawPath(pathId, paintId, patternId));
}
@override
void onDrawVertices(Float32List vertices, Uint16List? indices, int? paintId) {
commands.add(OnDrawVertices(vertices, indices, paintId));
}
@override
void onTextPosition(int textPositionId, double? x, double? y, double? dx,
double? dy, bool reset, Float64List? transform) {
commands.add(OnTextPosition(
id: textPositionId,
x: x,
y: y,
dx: dx,
dy: dy,
reset: reset,
transform: transform,
));
}
@override
void onUpdateTextPosition(int textPositionId) {
commands.add(OnUpdateTextPosition(textPositionId));
}
@override
void onPaintObject({
required int color,
required int? strokeCap,
required int? strokeJoin,
required int blendMode,
required double? strokeMiterLimit,
required double? strokeWidth,
required int paintStyle,
required int id,
required int? shaderId,
}) {
commands.add(
OnPaintObject(
color: color,
strokeCap: strokeCap,
strokeJoin: strokeJoin,
blendMode: blendMode,
strokeMiterLimit: strokeMiterLimit,
strokeWidth: strokeWidth,
paintStyle: paintStyle,
id: id,
shaderId: shaderId,
),
);
}
@override
void onPathClose() {
commands.add(const OnPathClose());
}
@override
void onPathCubicTo(
double x1, double y1, double x2, double y2, double x3, double y3) {
commands.add(OnPathCubicTo(x1, y1, x2, y2, x3, y3));
}
@override
void onPathFinished() {
commands.add(const OnPathFinished());
}
@override
void onPathLineTo(double x, double y) {
commands.add(OnPathLineTo(x, y));
}
@override
void onPathMoveTo(double x, double y) {
commands.add(OnPathMoveTo(x, y));
}
@override
void onPathStart(int id, int fillType) {
commands.add(OnPathStart(id, fillType));
}
@override
void onRestoreLayer() {
commands.add(const OnRestoreLayer());
}
@override
void onMask() {
commands.add(const OnMask());
}
@override
void onSaveLayer(int id) {
commands.add(OnSaveLayer(id));
}
@override
void onClipPath(int pathId) {
commands.add(OnClipPath(pathId));
}
@override
void onRadialGradient(
double centerX,
double centerY,
double radius,
double? focalX,
double? focalY,
Int32List colors,
Float32List? offsets,
Float64List? transform,
int tileMode,
int id,
) {
commands.add(
OnRadialGradient(
centerX: centerX,
centerY: centerY,
radius: radius,
focalX: focalX,
focalY: focalY,
colors: colors,
offsets: offsets,
transform: transform,
tileMode: tileMode,
id: id,
),
);
}
@override
void onLinearGradient(
double fromX,
double fromY,
double toX,
double toY,
Int32List colors,
Float32List? offsets,
int tileMode,
int id,
) {
commands.add(OnLinearGradient(
fromX: fromX,
fromY: fromY,
toX: toX,
toY: toY,
colors: colors,
offsets: offsets,
tileMode: tileMode,
id: id,
));
}
@override
void onSize(double width, double height) {
commands.add(OnSize(width, height));
}
@override
void onTextConfig(
String text,
String? fontFamily,
double xAnchorMultiplier,
int fontWeight,
double fontSize,
int decoration,
int decorationStyle,
int decorationColor,
int id,
) {
commands.add(OnTextConfig(
text,
xAnchorMultiplier,
fontSize,
fontFamily,
fontWeight,
decoration,
decorationStyle,
decorationColor,
id,
));
}
@override
void onDrawText(int textId, int? fillId, int? strokeId, int? patternId) {
commands.add(OnDrawText(textId, fillId, strokeId, patternId));
}
@override
void onImage(
int imageId,
int format,
Uint8List data, {
VectorGraphicsErrorListener? onError,
}) {
commands.add(OnImage(
imageId,
format,
data,
onError: onError,
));
}
@override
void onDrawImage(
int imageId,
double x,
double y,
double width,
double height,
Float64List? transform,
) {
commands.add(OnDrawImage(imageId, x, y, width, height, transform));
}
@override
void onPatternStart(int patternId, double x, double y, double width,
double height, Float64List transform) {
commands.add(OnPatternStart(patternId, x, y, width, height, transform));
}
}
@immutable
@immutable
class OnTextPosition {
const OnTextPosition({
required this.id,
this.x,
this.y,
this.dx,
this.dy,
required this.reset,
required this.transform,
});
final int id;
final double? x;
final double? y;
final double? dx;
final double? dy;
final bool reset;
final Float64List? transform;
@override
int get hashCode => Object.hash(
id,
x,
y,
dx,
dy,
reset,
Object.hashAll(transform ?? <Object?>[]),
);
@override
bool operator ==(Object other) {
return other is OnTextPosition &&
other.id == id &&
other.x == x &&
other.y == y &&
other.dx == dx &&
other.dy == dy &&
_listEquals(other.transform, transform);
}
}
@immutable
class OnMask {
const OnMask();
}
@immutable
@immutable
class OnLinearGradient {
const OnLinearGradient({
required this.fromX,
required this.fromY,
required this.toX,
required this.toY,
required this.colors,
required this.offsets,
required this.tileMode,
required this.id,
});
final double fromX;
final double fromY;
final double toX;
final double toY;
final Int32List colors;
final Float32List? offsets;
final int tileMode;
final int id;
@override
int get hashCode => Object.hash(
fromX,
fromY,
toX,
toY,
Object.hashAll(colors),
Object.hashAll(offsets ?? <Object?>[]),
tileMode,
id,
);
@override
bool operator ==(Object other) {
return other is OnLinearGradient &&
other.fromX == fromX &&
other.fromY == fromY &&
other.toX == toX &&
other.toY == toY &&
_listEquals(other.colors, colors) &&
_listEquals(other.offsets, offsets) &&
other.tileMode == tileMode &&
other.id == id;
}
@override
String toString() {
return 'OnLinearGradient('
'fromX: $fromX, '
'toX: $toX, '
'fromY: $fromY, '
'toY: $toY, '
'colors: Int32List.fromList($colors), '
'offsets: Float32List.fromList($offsets), '
'tileMode: $tileMode, '
'id: $id)';
}
}
@immutable
class OnRadialGradient {
const OnRadialGradient({
required this.centerX,
required this.centerY,
required this.radius,
required this.focalX,
required this.focalY,
required this.colors,
required this.offsets,
required this.transform,
required this.tileMode,
required this.id,
});
final double centerX;
final double centerY;
final double radius;
final double? focalX;
final double? focalY;
final Int32List colors;
final Float32List? offsets;
final Float64List? transform;
final int tileMode;
final int id;
@override
int get hashCode => Object.hash(
centerX,
centerY,
radius,
focalX,
focalY,
Object.hashAll(colors),
Object.hashAll(offsets ?? <Object?>[]),
Object.hashAll(transform ?? <Object?>[]),
tileMode,
id,
);
@override
bool operator ==(Object other) {
return other is OnRadialGradient &&
other.centerX == centerX &&
other.centerY == centerY &&
other.radius == radius &&
other.focalX == focalX &&
other.focalX == focalY &&
_listEquals(other.colors, colors) &&
_listEquals(other.offsets, offsets) &&
_listEquals(other.transform, transform) &&
other.tileMode == tileMode &&
other.id == id;
}
}
@immutable
class OnSaveLayer {
const OnSaveLayer(this.id);
final int id;
@override
int get hashCode => id.hashCode;
@override
bool operator ==(Object other) => other is OnSaveLayer && other.id == id;
}
@immutable
class OnClipPath {
const OnClipPath(this.id);
final int id;
@override
int get hashCode => id.hashCode;
@override
bool operator ==(Object other) => other is OnClipPath && other.id == id;
}
@immutable
class OnRestoreLayer {
const OnRestoreLayer();
}
@immutable
class OnDrawPath {
const OnDrawPath(this.pathId, this.paintId, this.patternId);
final int pathId;
final int? paintId;
final int? patternId;
@override
int get hashCode => Object.hash(pathId, paintId, patternId);
@override
bool operator ==(Object other) =>
other is OnDrawPath &&
other.pathId == pathId &&
other.paintId == paintId &&
other.patternId == patternId;
@override
String toString() => 'OnDrawPath($pathId, $paintId, $patternId)';
}
@immutable
class OnDrawVertices {
const OnDrawVertices(this.vertices, this.indices, this.paintId);
final List<double> vertices;
final List<int>? indices;
final int? paintId;
@override
int get hashCode => Object.hash(Object.hashAll(vertices),
Object.hashAll(indices ?? <Object?>[]), paintId);
@override
bool operator ==(Object other) =>
other is OnDrawVertices &&
_listEquals(vertices, other.vertices) &&
_listEquals(indices, other.indices) &&
other.paintId == paintId;
@override
String toString() => 'OnDrawVertices($vertices, $indices, $paintId)';
}
@immutable
class OnPaintObject {
const OnPaintObject({
required this.color,
required this.strokeCap,
required this.strokeJoin,
required this.blendMode,
required this.strokeMiterLimit,
required this.strokeWidth,
required this.paintStyle,
required this.id,
required this.shaderId,
});
final int color;
final int? strokeCap;
final int? strokeJoin;
final int blendMode;
final double? strokeMiterLimit;
final double? strokeWidth;
final int paintStyle;
final int id;
final int? shaderId;
@override
int get hashCode => Object.hash(color, strokeCap, strokeJoin, blendMode,
strokeMiterLimit, strokeWidth, paintStyle, id, shaderId);
@override
bool operator ==(Object other) =>
other is OnPaintObject &&
other.color == color &&
other.strokeCap == strokeCap &&
other.strokeJoin == strokeJoin &&
other.blendMode == blendMode &&
other.strokeMiterLimit == strokeMiterLimit &&
other.strokeWidth == strokeWidth &&
other.paintStyle == paintStyle &&
other.id == id &&
other.shaderId == shaderId;
@override
String toString() =>
'OnPaintObject(color: $color, strokeCap: $strokeCap, strokeJoin: $strokeJoin, '
'blendMode: $blendMode, strokeMiterLimit: $strokeMiterLimit, strokeWidth: $strokeWidth, '
'paintStyle: $paintStyle, id: $id, shaderId: $shaderId)';
}
@immutable
class OnPathClose {
const OnPathClose();
@override
int get hashCode => 44221;
@override
bool operator ==(Object other) => other is OnPathClose;
@override
String toString() => 'OnPathClose';
}
@immutable
class OnPathCubicTo {
const OnPathCubicTo(this.x1, this.y1, this.x2, this.y2, this.x3, this.y3);
final double x1;
final double x2;
final double x3;
final double y1;
final double y2;
final double y3;
@override
int get hashCode => Object.hash(x1, y1, x2, y2, x3, y3);
@override
bool operator ==(Object other) =>
other is OnPathCubicTo &&
other.x1 == x1 &&
other.y1 == y1 &&
other.x2 == x2 &&
other.y2 == y2 &&
other.x3 == x3 &&
other.y3 == y3;
@override
String toString() => 'OnPathCubicTo($x1, $y1, $x2, $y2, $x3, $y3)';
}
@immutable
class OnPathFinished {
const OnPathFinished();
@override
int get hashCode => 1223;
@override
bool operator ==(Object other) => other is OnPathFinished;
@override
String toString() => 'OnPathFinished';
}
@immutable
class OnPathLineTo {
const OnPathLineTo(this.x, this.y);
final double x;
final double y;
@override
int get hashCode => Object.hash(x, y);
@override
bool operator ==(Object other) =>
other is OnPathLineTo && other.x == x && other.y == y;
@override
String toString() => 'OnPathLineTo($x, $y)';
}
@immutable
class OnPathMoveTo {
const OnPathMoveTo(this.x, this.y);
final double x;
final double y;
@override
int get hashCode => Object.hash(x, y);
@override
bool operator ==(Object other) =>
other is OnPathMoveTo && other.x == x && other.y == y;
@override
String toString() => 'OnPathMoveTo($x, $y)';
}
@immutable
class OnPathStart {
const OnPathStart(this.id, this.fillType);
final int id;
final int fillType;
@override
int get hashCode => Object.hash(id, fillType);
@override
bool operator ==(Object other) =>
other is OnPathStart && other.id == id && other.fillType == fillType;
@override
String toString() => 'OnPathStart($id, $fillType)';
}
@immutable
class OnSize {
const OnSize(this.width, this.height);
final double width;
final double height;
@override
int get hashCode => Object.hash(width, height);
@override
bool operator ==(Object other) =>
other is OnSize && other.width == width && other.height == height;
@override
String toString() => 'OnSize($width, $height)';
}
@immutable
class OnTextConfig {
const OnTextConfig(
this.text,
this.xAnchorMultiplier,
this.fontSize,
this.fontFamily,
this.fontWeight,
this.decoration,
this.decorationStyle,
this.decorationColor,
this.id,
);
final String text;
final double xAnchorMultiplier;
final double fontSize;
final String? fontFamily;
final int fontWeight;
final int decoration;
final int decorationStyle;
final int decorationColor;
final int id;
@override
int get hashCode => Object.hash(
text,
xAnchorMultiplier,
fontSize,
fontFamily,
fontWeight,
decoration,
decorationStyle,
decorationColor,
id,
);
@override
bool operator ==(Object other) =>
other is OnTextConfig &&
other.text == text &&
other.xAnchorMultiplier == xAnchorMultiplier &&
other.fontSize == fontSize &&
other.fontFamily == fontFamily &&
other.fontWeight == fontWeight &&
other.decoration == decoration &&
other.decorationStyle == decorationStyle &&
other.decorationColor == decorationColor &&
other.id == id;
@override
String toString() =>
'OnTextConfig($text, $fontSize, $fontFamily, $fontWeight, $decoration, $decorationStyle, $decorationColor, $id)';
}
@immutable
class OnDrawText {
const OnDrawText(this.textId, this.fillId, this.strokeId, this.patternId);
final int textId;
final int? fillId;
final int? strokeId;
final int? patternId;
@override
int get hashCode => Object.hash(textId, fillId, strokeId, patternId);
@override
bool operator ==(Object other) =>
other is OnDrawText &&
other.textId == textId &&
other.fillId == fillId &&
other.strokeId == strokeId &&
other.patternId == patternId;
@override
String toString() => 'OnDrawText($textId, $fillId, $strokeId, $patternId)';
}
@immutable
class OnImage {
const OnImage(this.id, this.format, this.data, {this.onError});
final int id;
final int format;
final List<int> data;
final VectorGraphicsErrorListener? onError;
@override
int get hashCode => Object.hash(id, format, data, onError);
@override
bool operator ==(Object other) =>
other is OnImage &&
other.id == id &&
other.format == format &&
other.onError == onError &&
_listEquals(other.data, data);
@override
String toString() => 'OnImage($id, $format, data:${data.length} bytes)';
}
@immutable
class OnDrawImage {
const OnDrawImage(
this.id, this.x, this.y, this.width, this.height, this.transform);
final int id;
final double x;
final double y;
final double width;
final double height;
final Float64List? transform;
@override
int get hashCode => Object.hash(
id, x, y, width, height, Object.hashAll(transform ?? const <Object?>[]));
@override
bool operator ==(Object other) {
return other is OnDrawImage &&
other.id == id &&
other.x == x &&
other.y == y &&
other.width == width &&
other.height == height &&
_listEquals(other.transform, transform);
}
@override
String toString() => 'OnDrawImage($id, $x, $y, $width, $height, $transform)';
}
@immutable
class OnPatternStart {
const OnPatternStart(
this.patternId, this.x, this.y, this.width, this.height, this.transform);
final int patternId;
final double x;
final double y;
final double width;
final double height;
final Float64List transform;
@override
int get hashCode =>
Object.hash(patternId, x, y, width, height, Object.hashAll(transform));
@override
bool operator ==(Object other) =>
other is OnPatternStart &&
other.patternId == patternId &&
other.x == x &&
other.y == y &&
other.width == width &&
other.height == height &&
_listEquals(other.transform, transform);
@override
String toString() =>
'OnPatternStart($patternId, $x, $y, $width, $height, $transform)';
}
bool _listEquals<E>(List<E>? left, List<E>? right) {
if (left == null && right == null) {
return true;
}
if (left == null || right == null) {
return false;
}
if (left.length != right.length) {
return false;
}
for (int i = 0; i < left.length; i++) {
if (left[i] != right[i]) {
return false;
}
}
return true;
}
@immutable
class OnUpdateTextPosition {
const OnUpdateTextPosition(this.id);
final int id;
@override
int get hashCode => id;
@override
bool operator ==(Object other) =>
other is OnUpdateTextPosition && other.id == id;
}