2023-02-23 01:54:03 +00:00
|
|
|
use crate::bitmap::BitmapHandle;
|
2023-02-23 02:40:41 +00:00
|
|
|
use swf::{BevelFilterFlags, Color, Fixed16, GradientFilterFlags, GradientRecord};
|
2023-01-29 23:44:56 +00:00
|
|
|
|
2023-02-22 22:22:12 +00:00
|
|
|
#[derive(Debug, Clone)]
|
2023-01-29 23:44:56 +00:00
|
|
|
pub enum Filter {
|
2023-02-23 00:30:41 +00:00
|
|
|
BevelFilter(BevelFilter),
|
2023-01-29 23:44:56 +00:00
|
|
|
BlurFilter(BlurFilter),
|
|
|
|
ColorMatrixFilter(ColorMatrixFilter),
|
2023-02-23 01:05:59 +00:00
|
|
|
ConvolutionFilter(ConvolutionFilter),
|
2023-02-23 01:54:03 +00:00
|
|
|
DisplacementMapFilter(DisplacementMapFilter),
|
2023-02-23 02:06:30 +00:00
|
|
|
DropShadowFilter(DropShadowFilter),
|
2023-02-23 02:15:46 +00:00
|
|
|
GlowFilter(GlowFilter),
|
2023-02-23 02:40:41 +00:00
|
|
|
GradientBevelFilter(GradientBevelFilter),
|
2023-02-23 02:51:37 +00:00
|
|
|
GradientGlowFilter(GradientGlowFilter),
|
2023-01-29 23:44:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for Filter {
|
|
|
|
fn default() -> Self {
|
|
|
|
// A default colormatrix is a filter that essentially does nothing,
|
|
|
|
// making it a useful default in situations that we need a dummy filter
|
|
|
|
Filter::ColorMatrixFilter(ColorMatrixFilter::default())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-23 00:30:41 +00:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
2023-02-23 02:51:37 +00:00
|
|
|
pub enum BitmapFilterType {
|
2023-02-23 00:30:41 +00:00
|
|
|
Inner,
|
|
|
|
Outer,
|
|
|
|
Full,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct BevelFilter {
|
|
|
|
pub shadow_color: Color,
|
|
|
|
pub highlight_color: Color,
|
|
|
|
pub blur_x: f32,
|
|
|
|
pub blur_y: f32,
|
|
|
|
pub angle: f32,
|
|
|
|
pub distance: f32,
|
|
|
|
pub strength: u8,
|
2023-02-23 02:51:37 +00:00
|
|
|
pub bevel_type: BitmapFilterType,
|
2023-02-23 00:30:41 +00:00
|
|
|
pub knockout: bool,
|
|
|
|
pub quality: u8,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<swf::BevelFilter> for BevelFilter {
|
|
|
|
fn from(value: swf::BevelFilter) -> Self {
|
|
|
|
let quality = value.num_passes();
|
|
|
|
Self {
|
|
|
|
shadow_color: value.shadow_color,
|
|
|
|
highlight_color: value.highlight_color,
|
|
|
|
blur_x: value.blur_x.to_f32(),
|
|
|
|
blur_y: value.blur_y.to_f32(),
|
|
|
|
angle: value.angle.to_f32(),
|
|
|
|
distance: value.distance.to_f32(),
|
|
|
|
strength: (value.strength.to_f32() * 255.0) as u8,
|
|
|
|
bevel_type: if value.flags.contains(BevelFilterFlags::ON_TOP) {
|
2023-02-23 02:51:37 +00:00
|
|
|
BitmapFilterType::Full
|
2023-02-23 00:30:41 +00:00
|
|
|
} else if value.flags.contains(BevelFilterFlags::INNER_SHADOW) {
|
2023-02-23 02:51:37 +00:00
|
|
|
BitmapFilterType::Inner
|
2023-02-23 00:30:41 +00:00
|
|
|
} else {
|
2023-02-23 02:51:37 +00:00
|
|
|
BitmapFilterType::Outer
|
2023-02-23 00:30:41 +00:00
|
|
|
},
|
|
|
|
knockout: value.flags.contains(BevelFilterFlags::KNOCKOUT),
|
|
|
|
quality,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for BevelFilter {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
shadow_color: Color::BLACK,
|
|
|
|
highlight_color: Color::WHITE,
|
|
|
|
blur_x: 4.0,
|
|
|
|
blur_y: 4.0,
|
|
|
|
angle: 45.0,
|
|
|
|
distance: 4.0,
|
|
|
|
strength: 1,
|
2023-02-23 02:51:37 +00:00
|
|
|
bevel_type: BitmapFilterType::Inner,
|
2023-02-23 00:30:41 +00:00
|
|
|
knockout: false,
|
|
|
|
quality: 1,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-22 22:22:12 +00:00
|
|
|
#[derive(Debug, Clone)]
|
2023-01-29 23:44:56 +00:00
|
|
|
pub struct BlurFilter {
|
|
|
|
pub blur_x: f32,
|
|
|
|
pub blur_y: f32,
|
|
|
|
pub quality: u8,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<swf::BlurFilter> for BlurFilter {
|
|
|
|
fn from(value: swf::BlurFilter) -> Self {
|
|
|
|
Self {
|
|
|
|
blur_x: value.blur_x.to_f32(),
|
|
|
|
blur_y: value.blur_y.to_f32(),
|
2023-02-17 21:30:44 +00:00
|
|
|
quality: value.num_passes(),
|
2023-01-29 23:44:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for BlurFilter {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
blur_x: 4.0,
|
|
|
|
blur_y: 4.0,
|
|
|
|
quality: 1,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-22 22:22:12 +00:00
|
|
|
#[derive(Debug, Clone)]
|
2023-01-29 23:44:56 +00:00
|
|
|
pub struct ColorMatrixFilter {
|
|
|
|
pub matrix: [f32; 20],
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<swf::ColorMatrixFilter> for ColorMatrixFilter {
|
|
|
|
fn from(value: swf::ColorMatrixFilter) -> Self {
|
|
|
|
Self {
|
|
|
|
matrix: value.matrix.map(Fixed16::to_f32),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for ColorMatrixFilter {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
matrix: [
|
|
|
|
1.0, 0.0, 0.0, 0.0, 0.0, // r
|
|
|
|
0.0, 1.0, 0.0, 0.0, 0.0, // g
|
|
|
|
0.0, 0.0, 1.0, 0.0, 0.0, // b
|
|
|
|
0.0, 0.0, 0.0, 1.0, 0.0, // a
|
|
|
|
],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-02-23 01:05:59 +00:00
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct ConvolutionFilter {
|
|
|
|
pub bias: f32,
|
|
|
|
pub clamp: bool,
|
|
|
|
pub default_color: Color,
|
|
|
|
pub divisor: f32,
|
|
|
|
pub matrix: Vec<f32>,
|
|
|
|
pub matrix_x: u8,
|
|
|
|
pub matrix_y: u8,
|
|
|
|
pub preserve_alpha: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<swf::ConvolutionFilter> for ConvolutionFilter {
|
|
|
|
fn from(value: swf::ConvolutionFilter) -> Self {
|
|
|
|
let preserve_alpha = value.is_preserve_alpha();
|
|
|
|
let clamp = value.is_clamped();
|
|
|
|
Self {
|
|
|
|
bias: value.bias.to_f32(),
|
|
|
|
clamp,
|
|
|
|
default_color: value.default_color,
|
|
|
|
divisor: value.divisor.to_f32(),
|
|
|
|
matrix: value.matrix.iter().map(|v| v.to_f32()).collect(),
|
|
|
|
matrix_x: value.num_matrix_cols,
|
|
|
|
matrix_y: value.num_matrix_rows,
|
|
|
|
preserve_alpha,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for ConvolutionFilter {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
bias: 0.0,
|
|
|
|
clamp: true,
|
|
|
|
default_color: Color::from_rgba(0),
|
|
|
|
divisor: 1.0,
|
|
|
|
matrix: vec![],
|
|
|
|
matrix_x: 0,
|
|
|
|
matrix_y: 0,
|
|
|
|
preserve_alpha: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-02-23 01:54:03 +00:00
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
pub enum DisplacementMapFilterComponent {
|
|
|
|
Alpha,
|
|
|
|
Blue,
|
|
|
|
Green,
|
|
|
|
Red,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
pub enum DisplacementMapFilterMode {
|
|
|
|
Clamp,
|
|
|
|
Color,
|
|
|
|
Ignore,
|
|
|
|
Wrap,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct DisplacementMapFilter {
|
|
|
|
pub color: Color,
|
|
|
|
pub component_x: u8,
|
|
|
|
pub component_y: u8,
|
|
|
|
pub map_bitmap: Option<BitmapHandle>,
|
|
|
|
pub map_point: (u32, u32),
|
|
|
|
pub mode: DisplacementMapFilterMode,
|
|
|
|
pub scale_x: f32,
|
|
|
|
pub scale_y: f32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for DisplacementMapFilter {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
color: Color::from_rgba(0),
|
|
|
|
component_x: 0,
|
|
|
|
component_y: 0,
|
|
|
|
map_bitmap: None,
|
|
|
|
map_point: (0, 0),
|
|
|
|
mode: DisplacementMapFilterMode::Wrap,
|
|
|
|
scale_x: 0.0,
|
|
|
|
scale_y: 0.0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-02-23 02:06:30 +00:00
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct DropShadowFilter {
|
|
|
|
pub color: Color,
|
|
|
|
pub angle: f32,
|
|
|
|
pub blur_x: f32,
|
|
|
|
pub blur_y: f32,
|
|
|
|
pub distance: f32,
|
|
|
|
pub hide_object: bool,
|
|
|
|
pub inner: bool,
|
|
|
|
pub knockout: bool,
|
|
|
|
pub quality: u8,
|
|
|
|
pub strength: u8,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<swf::DropShadowFilter> for DropShadowFilter {
|
|
|
|
fn from(value: swf::DropShadowFilter) -> Self {
|
|
|
|
let inner = value.is_inner();
|
|
|
|
let knockout = value.is_knockout();
|
|
|
|
let quality = value.num_passes();
|
|
|
|
DropShadowFilter {
|
|
|
|
color: value.color,
|
|
|
|
angle: value.angle.to_f32(),
|
|
|
|
blur_x: value.blur_x.to_f32(),
|
|
|
|
blur_y: value.blur_y.to_f32(),
|
|
|
|
distance: value.distance.to_f32(),
|
|
|
|
hide_object: false,
|
|
|
|
inner,
|
|
|
|
knockout,
|
|
|
|
quality,
|
|
|
|
strength: (value.strength.to_f32() * 255.0) as u8,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for DropShadowFilter {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
color: Color::from_rgba(0),
|
|
|
|
angle: 45.0,
|
|
|
|
blur_x: 4.0,
|
|
|
|
blur_y: 4.0,
|
|
|
|
distance: 4.0,
|
|
|
|
hide_object: false,
|
|
|
|
inner: false,
|
|
|
|
knockout: false,
|
|
|
|
quality: 1,
|
|
|
|
strength: 1,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-02-23 02:15:46 +00:00
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct GlowFilter {
|
|
|
|
pub color: Color,
|
|
|
|
pub blur_x: f32,
|
|
|
|
pub blur_y: f32,
|
|
|
|
pub inner: bool,
|
|
|
|
pub knockout: bool,
|
|
|
|
pub quality: u8,
|
|
|
|
pub strength: u8,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<swf::GlowFilter> for GlowFilter {
|
|
|
|
fn from(value: swf::GlowFilter) -> Self {
|
|
|
|
let inner = value.is_inner();
|
|
|
|
let knockout = value.is_knockout();
|
|
|
|
let quality = value.num_passes();
|
|
|
|
GlowFilter {
|
|
|
|
color: value.color,
|
|
|
|
blur_x: value.blur_x.to_f32(),
|
|
|
|
blur_y: value.blur_y.to_f32(),
|
|
|
|
inner,
|
|
|
|
knockout,
|
|
|
|
quality,
|
|
|
|
strength: (value.strength.to_f32() * 255.0) as u8,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for GlowFilter {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
color: Color::from_rgba(0xFF0000FF),
|
|
|
|
blur_x: 6.0,
|
|
|
|
blur_y: 6.0,
|
|
|
|
inner: false,
|
|
|
|
knockout: false,
|
|
|
|
quality: 1,
|
|
|
|
strength: 2,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-02-23 02:40:41 +00:00
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct GradientBevelFilter {
|
|
|
|
pub colors: Vec<GradientRecord>,
|
|
|
|
pub blur_x: f32,
|
|
|
|
pub blur_y: f32,
|
|
|
|
pub angle: f32,
|
|
|
|
pub distance: f32,
|
|
|
|
pub strength: u8,
|
2023-02-23 02:51:37 +00:00
|
|
|
pub bevel_type: BitmapFilterType,
|
2023-02-23 02:40:41 +00:00
|
|
|
pub knockout: bool,
|
|
|
|
pub quality: u8,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<swf::GradientFilter> for GradientBevelFilter {
|
|
|
|
fn from(value: swf::GradientFilter) -> Self {
|
|
|
|
let quality = value.num_passes();
|
|
|
|
Self {
|
|
|
|
colors: value.colors,
|
|
|
|
blur_x: value.blur_x.to_f32(),
|
|
|
|
blur_y: value.blur_y.to_f32(),
|
|
|
|
angle: value.angle.to_f32(),
|
|
|
|
distance: value.distance.to_f32(),
|
|
|
|
strength: (value.strength.to_f32() * 255.0) as u8,
|
|
|
|
bevel_type: if value.flags.contains(GradientFilterFlags::ON_TOP) {
|
2023-02-23 02:51:37 +00:00
|
|
|
BitmapFilterType::Full
|
2023-02-23 02:40:41 +00:00
|
|
|
} else if value.flags.contains(GradientFilterFlags::INNER_SHADOW) {
|
2023-02-23 02:51:37 +00:00
|
|
|
BitmapFilterType::Inner
|
2023-02-23 02:40:41 +00:00
|
|
|
} else {
|
2023-02-23 02:51:37 +00:00
|
|
|
BitmapFilterType::Outer
|
2023-02-23 02:40:41 +00:00
|
|
|
},
|
|
|
|
knockout: value.flags.contains(GradientFilterFlags::KNOCKOUT),
|
|
|
|
quality,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for GradientBevelFilter {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
colors: vec![],
|
|
|
|
blur_x: 4.0,
|
|
|
|
blur_y: 4.0,
|
|
|
|
angle: 45.0,
|
|
|
|
distance: 4.0,
|
|
|
|
strength: 1,
|
2023-02-23 02:51:37 +00:00
|
|
|
bevel_type: BitmapFilterType::Inner,
|
|
|
|
knockout: false,
|
|
|
|
quality: 1,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct GradientGlowFilter {
|
|
|
|
pub colors: Vec<GradientRecord>,
|
|
|
|
pub blur_x: f32,
|
|
|
|
pub blur_y: f32,
|
|
|
|
pub angle: f32,
|
|
|
|
pub distance: f32,
|
|
|
|
pub strength: u8,
|
|
|
|
pub glow_type: BitmapFilterType,
|
|
|
|
pub knockout: bool,
|
|
|
|
pub quality: u8,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<swf::GradientFilter> for GradientGlowFilter {
|
|
|
|
fn from(value: swf::GradientFilter) -> Self {
|
|
|
|
let quality = value.num_passes();
|
|
|
|
Self {
|
|
|
|
colors: value.colors,
|
|
|
|
blur_x: value.blur_x.to_f32(),
|
|
|
|
blur_y: value.blur_y.to_f32(),
|
|
|
|
angle: value.angle.to_f32(),
|
|
|
|
distance: value.distance.to_f32(),
|
|
|
|
strength: (value.strength.to_f32() * 255.0) as u8,
|
|
|
|
glow_type: if value.flags.contains(GradientFilterFlags::ON_TOP) {
|
|
|
|
BitmapFilterType::Full
|
|
|
|
} else if value.flags.contains(GradientFilterFlags::INNER_SHADOW) {
|
|
|
|
BitmapFilterType::Inner
|
|
|
|
} else {
|
|
|
|
BitmapFilterType::Outer
|
|
|
|
},
|
|
|
|
knockout: value.flags.contains(GradientFilterFlags::KNOCKOUT),
|
|
|
|
quality,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for GradientGlowFilter {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
colors: vec![],
|
|
|
|
blur_x: 4.0,
|
|
|
|
blur_y: 4.0,
|
|
|
|
angle: 45.0,
|
|
|
|
distance: 4.0,
|
|
|
|
strength: 1,
|
|
|
|
glow_type: BitmapFilterType::Inner,
|
2023-02-23 02:40:41 +00:00
|
|
|
knockout: false,
|
|
|
|
quality: 1,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|