Skip to content

Commit

Permalink
test: canvas paint test.
Browse files Browse the repository at this point in the history
  • Loading branch information
andycall committed Dec 28, 2024
1 parent 31d56a9 commit 725b40b
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 68 deletions.
31 changes: 15 additions & 16 deletions webf/lib/src/html/canvas/canvas.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,19 @@ class RenderCanvasPaint extends RenderCustomPaint {
@override
bool get isRepaintBoundary => true;

RenderCanvasPaint(
{required CustomPainter painter, required Size preferredSize})
@override
CanvasPainter? get painter => super.painter as CanvasPainter;

RenderCanvasPaint({required CustomPainter painter, required Size preferredSize})
: super(
painter: painter,
foregroundPainter: null, // Ignore foreground painter
preferredSize: preferredSize,
);
painter: painter,
foregroundPainter: null, // Ignore foreground painter
preferredSize: preferredSize);

@override
void paint(PaintingContext context, Offset offset) {
context.pushClipRect(needsCompositing, offset,
Rect.fromLTWH(0, 0, preferredSize.width, preferredSize.height),
if (painter?.context == null) return;
context.pushClipRect(true, offset, Rect.fromLTWH(0, 0, preferredSize.width, preferredSize.height),
(context, offset) {
super.paint(context, offset);
});
Expand Down Expand Up @@ -71,18 +72,15 @@ class CanvasElement extends Element {
@override
void initializeMethods(Map<String, BindingObjectMethod> methods) {
super.initializeMethods(methods);
methods['getContext'] = BindingObjectMethodSync(
call: (args) => getContext(castToType<String>(args[0])));
methods['getContext'] = BindingObjectMethodSync(call: (args) => getContext(castToType<String>(args[0])));
}

@override
void initializeProperties(Map<String, BindingObjectProperty> properties) {
super.initializeProperties(properties);
properties['width'] = BindingObjectProperty(
getter: () => width, setter: (value) => width = castToType<int>(value));
properties['height'] = BindingObjectProperty(
getter: () => height,
setter: (value) => height = castToType<int>(value));
properties['width'] = BindingObjectProperty(getter: () => width, setter: (value) => width = castToType<int>(value));
properties['height'] =
BindingObjectProperty(getter: () => height, setter: (value) => height = castToType<int>(value));
}

@override
Expand Down Expand Up @@ -113,7 +111,8 @@ class CanvasElement extends Element {
painter.dispose();
}

context2d = CanvasRenderingContext2D(BindingContext(ownerView, ownerView.contextId, allocateNewBindingObject()), this);
context2d =
CanvasRenderingContext2D(BindingContext(ownerView, ownerView.contextId, allocateNewBindingObject()), this);
painter.context = context2d;

return context2d!;
Expand Down
9 changes: 0 additions & 9 deletions webf/lib/src/html/canvas/canvas_context_2d.dart
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,6 @@ class CanvasRenderingContext2D extends DynamicBindingObject {
// HACK: We need record the current matrix state because flutter canvas not export resetTransform now.
// https://github.com/flutter/engine/pull/25449
Matrix4 _matrix = Matrix4.identity();
Matrix4 _lastMatrix = Matrix4.identity();

int get actionCount => _actions.length;

Expand All @@ -408,10 +407,6 @@ class CanvasRenderingContext2D extends DynamicBindingObject {

// Perform canvas drawing.
List<CanvasAction> performActions(Canvas canvas, Size size) {
// HACK: Must sync transform first because each paint will saveLayer and restore that make the transform not effect
if (!_lastMatrix.isIdentity()) {
canvas.transform(_lastMatrix.storage);
}
_pendingActions = _actions;
_actions = [];
for (int i = 0; i < _pendingActions.length; i++) {
Expand All @@ -422,9 +417,6 @@ class CanvasRenderingContext2D extends DynamicBindingObject {

// Clear the saved pending actions.
void clearActions(List<CanvasAction> actions) {
if (_lastMatrix != _matrix) {
_lastMatrix = _matrix.clone();
}
actions.clear();
}

Expand Down Expand Up @@ -1276,7 +1268,6 @@ class CanvasRenderingContext2D extends DynamicBindingObject {
_actions = [];
_states.clear();
_matrix = Matrix4.identity();
_lastMatrix = Matrix4.identity();
_textAlign = TextAlign.start;
_textBaseline = CanvasTextBaseline.alphabetic;
_direction = TextDirection.ltr;
Expand Down
46 changes: 3 additions & 43 deletions webf/lib/src/html/canvas/canvas_painter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class CanvasPainter extends CustomPainter {

CanvasRenderingContext2D? context;

final Paint _saveLayerPaint = Paint();
final Paint _snapshotPaint = Paint();

// Cache the last paint image.
Expand Down Expand Up @@ -49,62 +48,23 @@ class CanvasPainter extends CustomPainter {
}

@override
void paint(Canvas canvas, Size size) async {
if (_hasSnapshot && !_shouldPainting) {
return canvas.drawImage(_snapshot!, Offset.zero, _snapshotPaint);
}

final PictureRecorder pictureRecorder = PictureRecorder();
final Canvas recordCanvas = Canvas(pictureRecorder);

void paint(Canvas canvas, Size size) {
if (_scaleX != 1.0 || _scaleY != 1.0) {
recordCanvas.scale(_scaleX, _scaleY);
}

// This lets you create composite effects, for example making a group of drawing commands semi-transparent.
// Without using saveLayer, each part of the group would be painted individually,
// so where they overlap would be darker than where they do not. By using saveLayer to group them together,
// they can be drawn with an opaque color at first,
// and then the entire group can be made transparent using the saveLayer's paint.
recordCanvas.saveLayer(null, _saveLayerPaint);

// Paint last content
if (_hasSnapshot) {
recordCanvas.drawImage(_snapshot!, Offset.zero, _snapshotPaint);
_disposeSnapshot();
canvas.scale(_scaleX, _scaleY);
}

// Paint new actions
List<CanvasAction>? actions;
if (_shouldPainting) {
actions = context!.performActions(recordCanvas, size);
actions = context!.performActions(canvas, size);
}

// Must pair each call to save()/saveLayer() with a later matching call to restore().
recordCanvas.restore();

// After calling this function, both the picture recorder
// and the canvas objects are invalid and cannot be used further.
final Picture picture = pictureRecorder.endRecording();
canvas.drawPicture(picture);

// Must flat picture to image, or raster will accept a growing command buffer.
await _createSnapshot(picture, size);

// Dispose the used picture.
picture.dispose();
// Clear actions after snapshot was created, or next frame call may empty.
if (actions != null) {
context!.clearActions(actions);
}
}

Future<void> _createSnapshot(Picture picture, Size size) async {
_updatingSnapshot = true;
_snapshot = await picture.toImage(size.width.toInt(), size.height.toInt());
_updatingSnapshot = false;
}

@override
bool shouldRepaint(CanvasPainter oldDelegate) {
if (_shouldRepaint) {
Expand Down

0 comments on commit 725b40b

Please sign in to comment.