-
Notifications
You must be signed in to change notification settings - Fork 5.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This implements flutter/flutter#126342 This implements `ImageFilter`, `ColorFilter` and `MaskFilter` in Skwasm. This includes support on the `Paint` object, as well as the `SceneBuilder` layers that use these types.
- Loading branch information
1 parent
90b44e3
commit 18aec20
Showing
21 changed files
with
912 additions
and
71 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// 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 'package:ui/ui.dart' as ui; | ||
|
||
// These are additional APIs that are not part of the `dart:ui` interface that | ||
// are needed internally to properly implement a `SceneBuilder` on top of the | ||
// generic Canvas/Picture api. | ||
abstract class SceneCanvas implements ui.Canvas { | ||
// This is the same as a normal `saveLayer` call, but we can pass a backdrop image filter. | ||
void saveLayerWithFilter(ui.Rect? bounds, ui.Paint paint, ui.ImageFilter backdropFilter); | ||
} | ||
|
||
abstract class ScenePicture implements ui.Picture { | ||
// This is a conservative bounding box of all the drawing primitives in this picture. | ||
ui.Rect get cullRect; | ||
} | ||
|
||
abstract class SceneImageFilter implements ui.ImageFilter { | ||
// Since some image filters affect the actual drawing bounds of a given picture, this | ||
// gives the maximum draw boundary for a picture with the given input bounds after it | ||
// has been processed by the filter. | ||
ui.Rect filterBounds(ui.Rect inputBounds); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
132 changes: 132 additions & 0 deletions
132
lib/web_ui/lib/src/engine/skwasm/skwasm_impl/filters.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
// 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:ffi'; | ||
import 'dart:typed_data'; | ||
|
||
import 'package:ui/src/engine.dart'; | ||
import 'package:ui/src/engine/skwasm/skwasm_impl.dart'; | ||
import 'package:ui/ui.dart' as ui; | ||
|
||
class SkwasmImageFilter implements SceneImageFilter { | ||
SkwasmImageFilter._(this.handle); | ||
|
||
factory SkwasmImageFilter.blur({ | ||
double sigmaX = 0.0, | ||
double sigmaY = 0.0, | ||
ui.TileMode tileMode = ui.TileMode.clamp, | ||
}) => SkwasmImageFilter._(imageFilterCreateBlur(sigmaX, sigmaY, tileMode.index)); | ||
|
||
factory SkwasmImageFilter.dilate({ | ||
double radiusX = 0.0, | ||
double radiusY = 0.0, | ||
}) => SkwasmImageFilter._(imageFilterCreateDilate(radiusX, radiusY)); | ||
|
||
factory SkwasmImageFilter.erode({ | ||
double radiusX = 0.0, | ||
double radiusY = 0.0, | ||
}) => SkwasmImageFilter._(imageFilterCreateErode(radiusX, radiusY)); | ||
|
||
factory SkwasmImageFilter.matrix( | ||
Float64List matrix4, { | ||
ui.FilterQuality filterQuality = ui.FilterQuality.low | ||
}) => withStackScope((StackScope scope) => SkwasmImageFilter._(imageFilterCreateMatrix( | ||
scope.convertMatrix4toSkMatrix(matrix4), | ||
filterQuality.index | ||
))); | ||
|
||
factory SkwasmImageFilter.fromColorFilter(SkwasmColorFilter filter) => | ||
SkwasmImageFilter._(imageFilterCreateFromColorFilter(filter.handle)); | ||
|
||
factory SkwasmImageFilter.fromUiFilter(ui.ImageFilter filter) { | ||
if (filter is ui.ColorFilter) { | ||
final SkwasmColorFilter colorFilter = | ||
SkwasmColorFilter.fromEngineColorFilter(filter as EngineColorFilter); | ||
final SkwasmImageFilter outputFilter = SkwasmImageFilter.fromColorFilter(colorFilter); | ||
colorFilter.dispose(); | ||
return outputFilter; | ||
} else { | ||
return filter as SkwasmImageFilter; | ||
} | ||
} | ||
|
||
factory SkwasmImageFilter.compose( | ||
ui.ImageFilter outer, | ||
ui.ImageFilter inner, | ||
) { | ||
final SkwasmImageFilter nativeOuter = SkwasmImageFilter.fromUiFilter(outer); | ||
final SkwasmImageFilter nativeInner = SkwasmImageFilter.fromUiFilter(inner); | ||
return SkwasmImageFilter._(imageFilterCompose(nativeOuter.handle, nativeInner.handle)); | ||
} | ||
|
||
void dispose() { | ||
if (!_isDisposed) { | ||
imageFilterDispose(handle); | ||
_isDisposed = true; | ||
} | ||
} | ||
|
||
final ImageFilterHandle handle; | ||
bool _isDisposed = false; | ||
|
||
@override | ||
ui.Rect filterBounds(ui.Rect inputBounds) => withStackScope((StackScope scope) { | ||
final RawIRect rawRect = scope.convertIRectToNative(inputBounds); | ||
imageFilterGetFilterBounds(handle, rawRect); | ||
return scope.convertIRectFromNative(rawRect); | ||
}); | ||
} | ||
|
||
class SkwasmColorFilter { | ||
SkwasmColorFilter._(this.handle); | ||
|
||
factory SkwasmColorFilter.fromEngineColorFilter(EngineColorFilter colorFilter) => | ||
switch (colorFilter.type) { | ||
ColorFilterType.mode => SkwasmColorFilter._(colorFilterCreateMode( | ||
colorFilter.color!.value, | ||
colorFilter.blendMode!.index, | ||
)), | ||
ColorFilterType.linearToSrgbGamma => SkwasmColorFilter._(colorFilterCreateLinearToSRGBGamma()), | ||
ColorFilterType.srgbToLinearGamma => SkwasmColorFilter._(colorFilterCreateSRGBToLinearGamma()), | ||
ColorFilterType.matrix => withStackScope((StackScope scope) { | ||
final Pointer<Float> nativeMatrix = scope.convertDoublesToNative(colorFilter.matrix!); | ||
return SkwasmColorFilter._(colorFilterCreateMatrix(nativeMatrix)); | ||
}), | ||
}; | ||
|
||
factory SkwasmColorFilter.composed( | ||
SkwasmColorFilter outer, | ||
SkwasmColorFilter inner, | ||
) => SkwasmColorFilter._(colorFilterCompose(outer.handle, inner.handle)); | ||
|
||
void dispose() { | ||
if (!_isDisposed) { | ||
colorFilterDispose(handle); | ||
_isDisposed = true; | ||
} | ||
} | ||
|
||
final ColorFilterHandle handle; | ||
bool _isDisposed = false; | ||
} | ||
|
||
class SkwasmMaskFilter { | ||
SkwasmMaskFilter._(this.handle); | ||
|
||
factory SkwasmMaskFilter.fromUiMaskFilter(ui.MaskFilter maskFilter) => | ||
SkwasmMaskFilter._(maskFilterCreateBlur( | ||
maskFilter.webOnlyBlurStyle.index, | ||
maskFilter.webOnlySigma | ||
)); | ||
|
||
final MaskFilterHandle handle; | ||
bool _isDisposed = false; | ||
|
||
void dispose() { | ||
if (!_isDisposed) { | ||
maskFilterDispose(handle); | ||
_isDisposed = true; | ||
} | ||
} | ||
} |
Oops, something went wrong.