Skip to content

Commit bd26d2b

Browse files
committed
refactor image-sampling into filter module
1 parent 930790a commit bd26d2b

File tree

5 files changed

+66
-79
lines changed

5 files changed

+66
-79
lines changed

src/context/api.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -782,22 +782,23 @@ pub fn putImageData(mut cx: FunctionContext) -> JsResult<JsUndefined> {
782782
pub fn get_imageSmoothingEnabled(mut cx: FunctionContext) -> JsResult<JsBoolean> {
783783
let this = cx.argument::<BoxedContext2D>(0)?;
784784
let mut this = this.borrow_mut();
785-
Ok(cx.boolean(this.state.image_smoothing_enabled))
785+
// Ok(cx.boolean(this.state.image_smoothing_enabled))
786+
Ok(cx.boolean(this.state.image_filter.smoothing))
786787
}
787788

788789
pub fn set_imageSmoothingEnabled(mut cx: FunctionContext) -> JsResult<JsUndefined> {
789790
let this = cx.argument::<BoxedContext2D>(0)?;
790791
let mut this = this.borrow_mut();
791792
let flag = bool_arg(&mut cx, 1, "imageSmoothingEnabled")?;
792793

793-
this.state.image_smoothing_enabled = flag;
794+
this.state.image_filter.smoothing = flag;
794795
Ok(cx.undefined())
795796
}
796797

797798
pub fn get_imageSmoothingQuality(mut cx: FunctionContext) -> JsResult<JsString> {
798799
let this = cx.argument::<BoxedContext2D>(0)?;
799800
let mut this = this.borrow_mut();
800-
let mode = from_filter_quality(this.state.image_filter_quality);
801+
let mode = from_filter_quality(this.state.image_filter.quality);
801802
Ok(cx.string(mode))
802803
}
803804

@@ -807,7 +808,7 @@ pub fn set_imageSmoothingQuality(mut cx: FunctionContext) -> JsResult<JsUndefine
807808
let name = string_arg(&mut cx, 1, "imageSmoothingQuality")?;
808809

809810
if let Some(mode) = to_filter_quality(&name){
810-
this.state.image_filter_quality = mode;
811+
this.state.image_filter.quality = mode;
811812
}
812813
Ok(cx.undefined())
813814
}

src/context/mod.rs

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub mod page;
1919
use crate::FONT_LIBRARY;
2020
use crate::utils::*;
2121
use crate::typography::*;
22-
use crate::filter::Filter;
22+
use crate::filter::{Filter, ImageFilter, FilterQuality};
2323
use crate::gradient::{CanvasGradient, BoxedCanvasGradient};
2424
use crate::pattern::{CanvasPattern, BoxedCanvasPattern};
2525
use crate::texture::{CanvasTexture, BoxedCanvasTexture};
@@ -62,8 +62,7 @@ pub struct State{
6262

6363
global_alpha: f32,
6464
global_composite_operation: BlendMode,
65-
image_filter_quality: FilterQuality,
66-
image_smoothing_enabled: bool,
65+
image_filter: ImageFilter,
6766
filter: Filter,
6867

6968
font: String,
@@ -105,8 +104,7 @@ impl Default for State {
105104

106105
global_alpha: 1.0,
107106
global_composite_operation: BlendMode::SrcOver,
108-
image_filter_quality: FilterQuality::Low,
109-
image_smoothing_enabled: true,
107+
image_filter: ImageFilter{ smoothing:true, quality:FilterQuality::Low },
110108
filter: Filter::default(),
111109

112110
shadow_blur: 0.0,
@@ -398,15 +396,9 @@ impl Context2D{
398396

399397
pub fn draw_image(&mut self, img:&Option<Image>, src_rect:&Rect, dst_rect:&Rect){
400398
let paint = self.paint_for_image();
401-
402-
let quality = match self.state.image_smoothing_enabled {
403-
true => self.state.image_filter_quality,
404-
false => FilterQuality::None
405-
};
406-
407399
if let Some(image) = &img {
408400
self.render_to_canvas(&paint, |canvas, paint| {
409-
let sampling = to_sampling_opts(quality);
401+
let sampling = self.state.image_filter.sampling();
410402
canvas.draw_image_rect_with_sampling_options(&image, Some((src_rect, Strict)), dst_rect, sampling, paint);
411403
});
412404
}
@@ -500,7 +492,7 @@ impl Context2D{
500492
pub fn paint_for_drawing(&self, style:PaintStyle) -> Paint{
501493
let mut paint = self.state.paint.clone();
502494
self.state.filter.mix_into(&mut paint, self.state.matrix, false);
503-
self.state.dye(style).mix_into(&mut paint, self.state.global_alpha, self.state.image_smoothing_enabled);
495+
self.state.dye(style).mix_into(&mut paint, self.state.global_alpha, self.state.image_filter);
504496
paint.set_style(style);
505497

506498
if style==PaintStyle::Stroke && !self.state.line_dash_list.is_empty(){
@@ -581,7 +573,7 @@ impl Dye{
581573
}
582574
}
583575

584-
pub fn mix_into(&self, paint: &mut Paint, alpha: f32, smoothing: bool){
576+
pub fn mix_into(&self, paint: &mut Paint, alpha: f32, image_filter: ImageFilter){
585577
match self {
586578
Dye::Color(color) => {
587579
let mut color:Color4f = (*color).into();
@@ -593,7 +585,7 @@ impl Dye{
593585
.set_alpha_f(alpha);
594586
},
595587
Dye::Pattern(pattern) =>{
596-
paint.set_shader(pattern.shader(smoothing))
588+
paint.set_shader(pattern.shader(image_filter))
597589
.set_alpha_f(alpha);
598590
}
599591
Dye::Texture(texture) =>{

src/filter.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![allow(unused_imports)]
33
#![allow(unused_variables)]
44
#![allow(dead_code)]
5+
use skia_safe::{FilterMode, MipmapMode, SamplingOptions, CubicResampler};
56
use skia_safe::{Paint, Matrix, Point, Color, TileMode, MaskFilter, BlurStyle,
67
image_filters, color_filters, table_color_filter};
78

@@ -150,4 +151,36 @@ impl Filter {
150151

151152
paint.set_image_filter(image_filter)
152153
}
153-
}
154+
}
155+
156+
#[derive(Copy, Clone)]
157+
pub enum FilterQuality{
158+
None, Low, Medium, High
159+
}
160+
161+
#[derive(Copy, Clone)]
162+
pub struct ImageFilter {
163+
pub smoothing: bool,
164+
pub quality: FilterQuality
165+
}
166+
167+
impl ImageFilter {
168+
pub fn sampling(&self) -> SamplingOptions {
169+
let quality = if self.smoothing { self.quality } else { FilterQuality::None };
170+
match quality {
171+
FilterQuality::None => SamplingOptions {
172+
use_cubic:false, cubic:CubicResampler{b:0.0, c:0.0}, filter:FilterMode::Nearest, mipmap:MipmapMode::None
173+
},
174+
FilterQuality::Low => SamplingOptions {
175+
use_cubic:false, cubic:CubicResampler{b:0.0, c:0.0}, filter:FilterMode::Linear, mipmap:MipmapMode::Nearest
176+
},
177+
FilterQuality::Medium => SamplingOptions {
178+
use_cubic:true, cubic:CubicResampler::mitchell(), filter:FilterMode::Linear, mipmap:MipmapMode::Nearest
179+
},
180+
FilterQuality::High => SamplingOptions {
181+
use_cubic:true, cubic:CubicResampler::catmull_rom(), filter:FilterMode::Linear, mipmap:MipmapMode::Linear
182+
}
183+
}
184+
}
185+
186+
}

src/pattern.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ use skia_safe::{Shader, TileMode, TileMode::{Decal, Repeat}, SamplingOptions, Si
1010
Image as SkImage, Picture, Matrix, FilterMode};
1111

1212
use crate::utils::*;
13-
use crate::image::{BoxedImage};
14-
use crate::context::{BoxedContext2D};
13+
use crate::image::BoxedImage;
14+
use crate::context::BoxedContext2D;
15+
use crate::filter::ImageFilter;
1516

1617
pub type BoxedCanvasPattern = JsBox<RefCell<CanvasPattern>>;
1718
impl Finalize for CanvasPattern {}
@@ -31,17 +32,12 @@ pub struct CanvasPattern{
3132
}
3233

3334
impl CanvasPattern{
34-
pub fn shader(&self, smoothing: bool) -> Option<Shader>{
35+
pub fn shader(&self, image_filter: ImageFilter) -> Option<Shader>{
3536
let stamp = Arc::clone(&self.stamp);
3637
let stamp = stamp.lock().unwrap();
3738

3839
if let Some(image) = &stamp.image{
39-
let quality = match smoothing{
40-
true => FilterQuality::High,
41-
false => FilterQuality::None
42-
};
43-
44-
image.to_shader(stamp.repeat, to_sampling_opts(quality), None).map(|shader|
40+
image.to_shader(stamp.repeat, image_filter.sampling(), None).map(|shader|
4541
shader.with_local_matrix(&stamp.matrix)
4642
)
4743
}else if let Some(pict) = &stamp.pict{

src/utils.rs

Lines changed: 15 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ pub fn opt_path2d_arg(cx: &mut FunctionContext, idx:usize) -> Option<Path> {
440440
// Filters
441441
//
442442

443-
use crate::filter::FilterSpec;
443+
use crate::filter::{FilterSpec, FilterQuality};
444444

445445
pub fn filter_arg(cx: &mut FunctionContext, idx: usize) -> NeonResult<(String, Vec<FilterSpec>)> {
446446
let arg = cx.argument::<JsObject>(idx as i32)?;
@@ -473,39 +473,6 @@ pub fn filter_arg(cx: &mut FunctionContext, idx: usize) -> NeonResult<(String, V
473473
Ok( (canonical, filters) )
474474
}
475475

476-
//
477-
// Skia Enums
478-
//
479-
480-
use skia_safe::{TileMode, TileMode::{Decal, Repeat}};
481-
// pub fn to_tile_mode(mode_name:&str) -> Option<TileMode>{
482-
// let mode = match mode_name.to_lowercase().as_str(){
483-
// "clamp" => TileMode::Clamp,
484-
// "repeat" => TileMode::Repeat,
485-
// "mirror" => TileMode::Mirror,
486-
// "decal" => TileMode::Decal,
487-
// _ => return None
488-
// };
489-
// Some(mode)
490-
// }
491-
492-
pub fn to_repeat_mode(repeat:&str) -> Option<(TileMode, TileMode)> {
493-
let mode = match repeat.to_lowercase().as_str() {
494-
"repeat" | "" => (Repeat, Repeat),
495-
"repeat-x" => (Repeat, Decal),
496-
"repeat-y" => (Decal, Repeat),
497-
"no-repeat" => (Decal, Decal),
498-
_ => return None
499-
};
500-
Some(mode)
501-
}
502-
503-
504-
#[derive(Copy, Clone)]
505-
pub enum FilterQuality{
506-
None, Low, Medium, High
507-
}
508-
509476
pub fn to_filter_quality(mode_name:&str) -> Option<FilterQuality>{
510477
let mode = match mode_name.to_lowercase().as_str(){
511478
"low" => FilterQuality::Low,
@@ -525,23 +492,21 @@ pub fn from_filter_quality(mode:FilterQuality) -> String{
525492
}.to_string()
526493
}
527494

528-
use skia_safe::{FilterMode, MipmapMode, SamplingOptions, CubicResampler};
529495

530-
pub fn to_sampling_opts(mode:FilterQuality) -> SamplingOptions {
531-
match mode {
532-
FilterQuality::None => SamplingOptions {
533-
use_cubic:false, cubic:CubicResampler{b:0.0, c:0.0}, filter:FilterMode::Nearest, mipmap:MipmapMode::None
534-
},
535-
FilterQuality::Low => SamplingOptions {
536-
use_cubic:false, cubic:CubicResampler{b:0.0, c:0.0}, filter:FilterMode::Linear, mipmap:MipmapMode::Nearest
537-
},
538-
FilterQuality::Medium => SamplingOptions {
539-
use_cubic:true, cubic:CubicResampler::mitchell(), filter:FilterMode::Linear, mipmap:MipmapMode::Nearest
540-
},
541-
FilterQuality::High => SamplingOptions {
542-
use_cubic:true, cubic:CubicResampler::catmull_rom(), filter:FilterMode::Linear, mipmap:MipmapMode::Linear
543-
}
544-
}
496+
//
497+
// Skia Enums
498+
//
499+
500+
use skia_safe::{TileMode, TileMode::{Decal, Repeat}};
501+
pub fn to_repeat_mode(repeat:&str) -> Option<(TileMode, TileMode)> {
502+
let mode = match repeat.to_lowercase().as_str() {
503+
"repeat" | "" => (Repeat, Repeat),
504+
"repeat-x" => (Repeat, Decal),
505+
"repeat-y" => (Decal, Repeat),
506+
"no-repeat" => (Decal, Decal),
507+
_ => return None
508+
};
509+
Some(mode)
545510
}
546511

547512
use skia_safe::{PaintCap};

0 commit comments

Comments
 (0)