From e185ca3faa1a13a22af37a20284a00114b9669ae Mon Sep 17 00:00:00 2001 From: LongYinan Date: Thu, 3 Dec 2020 13:44:34 +0800 Subject: [PATCH] feat: strokeStyle --- .github/workflows/CI.yaml | 3 +- example/simple.js | 4 +- example/simple.png | Bin 4297 -> 4520 bytes src/ctx.rs | 79 +++++++++++++++++++++++++------------- src/gradient.rs | 4 +- 5 files changed, 58 insertions(+), 32 deletions(-) diff --git a/.github/workflows/CI.yaml b/.github/workflows/CI.yaml index 47948154..73432c9e 100644 --- a/.github/workflows/CI.yaml +++ b/.github/workflows/CI.yaml @@ -6,7 +6,8 @@ env: on: push: - branches: [master, develop] + branches: + - main tags-ignore: - '**' pull_request: diff --git a/example/simple.js b/example/simple.js index 164c87be..e33441ed 100644 --- a/example/simple.js +++ b/example/simple.js @@ -8,12 +8,12 @@ const canvas = createCanvas(1024, 768) const ctx = canvas.getContext('2d') ctx.lineWidth = 10 +ctx.strokeStyle = '#03a9f4' +ctx.fillStyle = '#03a9f4' // Wall ctx.strokeRect(75, 140, 150, 110) -ctx.fillStyle = '#03a9f4' - // Door ctx.fillRect(130, 190, 40, 60) diff --git a/example/simple.png b/example/simple.png index 85c7a08f254bf4c87e8917d79ba702d7012131b3..613b1e1edf23f6ac81319fa193cab7bc07cdaca9 100644 GIT binary patch literal 4520 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 diff --git a/src/ctx.rs b/src/ctx.rs index 01260cf2..1e264dd1 100644 --- a/src/ctx.rs +++ b/src/ctx.rs @@ -52,6 +52,9 @@ impl Context { Property::new(&env, "fillStyle")? .with_setter(set_fill_style) .with_getter(get_fill_style), + Property::new(&env, "strokeStyle")? + .with_setter(set_stroke_style) + .with_getter(get_stroke_style), // methods Property::new(&env, "arc")?.with_method(arc), Property::new(&env, "arcTo")?.with_method(arc_to), @@ -84,7 +87,7 @@ impl Context { #[inline(always)] pub fn new(width: u32, height: u32) -> Result { let surface = Surface::new_rgba(width, height) - .ok_or(Error::from_reason("Create skia surface failed".to_owned()))?; + .ok_or_else(|| Error::from_reason("Create skia surface failed".to_owned()))?; let mut states = Vec::new(); states.push(Context2dRenderingState::default()); Ok(Context { @@ -443,25 +446,17 @@ impl Context { #[inline(always)] pub fn set_fill_style(&mut self, pattern: Pattern) -> result::Result<(), SkError> { let last_state = self.states.last_mut().unwrap(); - match &pattern { - Pattern::Color(color, _) => { - self - .paint - .set_color(color.red, color.green, color.blue, color.alpha); - } - Pattern::Gradient(gradient) => { - let current_transform = self.surface.canvas.get_transform(); - self - .paint - .set_shader(&gradient.get_shader(¤t_transform)?); - } - // TODO, image pattern - Pattern::ImagePattern(image) => {} - }; last_state.fill_style = pattern; Ok(()) } + #[inline(always)] + pub fn set_stroke_style(&mut self, pattern: Pattern) -> result::Result<(), SkError> { + let last_state = self.states.last_mut().unwrap(); + last_state.stroke_style = pattern; + Ok(()) + } + #[inline(always)] fn fill_paint(&self) -> result::Result { let mut paint = self.paint.clone(); @@ -488,9 +483,7 @@ impl Context { last_state.line_dash_list.as_slice(), last_state.line_dash_offset, ) - .ok_or(SkError::Generic(format!( - "Make line dash path effect failed" - )))?; + .ok_or_else(|| SkError::Generic(format!("Make line dash path effect failed")))?; paint.set_path_effect(&path_effect); } Ok(paint) @@ -501,30 +494,28 @@ impl Context { let mut paint = self.paint.clone(); paint.set_style(PaintStyle::Stroke); let last_state = self.states.last().unwrap(); + let global_alpha = self.paint.get_alpha(); match &last_state.stroke_style { Pattern::Color(c, _) => { let mut color = c.clone(); - color.alpha = - ((color.alpha as f32) * (self.paint.get_alpha() as f32 / 255.0)).round() as u8; + color.alpha = ((color.alpha as f32) * (global_alpha as f32 / 255.0)).round() as u8; paint.set_color(color.red, color.green, color.blue, color.alpha); } Pattern::Gradient(g) => { let current_transform = self.surface.canvas.get_transform(); let shader = g.get_shader(¤t_transform)?; - paint.set_color(0, 0, 0, self.paint.get_alpha()); + paint.set_color(0, 0, 0, global_alpha); paint.set_shader(&shader); } // TODO, image pattern Pattern::ImagePattern(p) => {} }; - if last_state.line_dash_list.len() != 0 { + if !last_state.line_dash_list.is_empty() { let path_effect = PathEffect::new_dash_path( last_state.line_dash_list.as_slice(), last_state.line_dash_offset, ) - .ok_or(SkError::Generic(format!( - "Make line dash path effect failed" - )))?; + .ok_or_else(|| SkError::Generic(format!("Make line dash path effect failed")))?; paint.set_path_effect(&path_effect); } Ok(paint) @@ -561,7 +552,7 @@ impl Context { let current_transform = surface.canvas.get_transform_matrix(); let invert = current_transform .invert() - .ok_or(SkError::Generic("Invert matrix failed".to_owned()))?; + .ok_or_else(|| SkError::Generic("Invert matrix failed".to_owned()))?; surface.canvas.concat(invert.into_transform()); let mut shadow_offset = current_transform.clone(); shadow_offset.pre_translate(shadow_offset_x, shadow_offset_y); @@ -1085,3 +1076,37 @@ fn get_fill_style(ctx: CallContext) -> Result { let this = ctx.this_unchecked::(); this.get_named_property("_fillStyle") } + +#[js_function(1)] +fn set_stroke_style(ctx: CallContext) -> Result { + let mut this = ctx.this_unchecked::(); + let context_2d = ctx.env.unwrap::(&this)?; + + let js_stroke_style = ctx.get::(0)?; + + match js_stroke_style.get_type()? { + ValueType::String => { + let js_color = unsafe { JsString::from_raw_unchecked(ctx.env.raw(), js_stroke_style.raw()) } + .into_utf8()?; + context_2d.set_stroke_style(Pattern::from_color(js_color.as_str()?)?)?; + } + // TODO, image and gradient + ValueType::External => {} + _ => { + return Err(Error::new( + Status::InvalidArg, + format!("Invalid strokeStyle"), + )) + } + } + + this.set_named_property("_strokeStyle", js_stroke_style)?; + + ctx.env.get_undefined() +} + +#[js_function] +fn get_stroke_style(ctx: CallContext) -> Result { + let this = ctx.this_unchecked::(); + this.get_named_property("_strokeStyle") +} diff --git a/src/gradient.rs b/src/gradient.rs index d47f8943..839f7c89 100644 --- a/src/gradient.rs +++ b/src/gradient.rs @@ -97,7 +97,7 @@ impl CanvasGradient { end_point: (sx2, sy2), base: linear_gradient.base.clone(), }) - .ok_or(SkError::Generic("Create linear gradient failed".to_owned()))?, + .ok_or_else(|| SkError::Generic("Create linear gradient failed".to_owned()))?, ) } Self::Radial(ref radial_gradient) => { @@ -128,7 +128,7 @@ impl CanvasGradient { Ok( Shader::new_two_point_conical_gradient(&new_radial_gradient) - .ok_or(SkError::Generic("Create radial gradient failed".to_owned()))?, + .ok_or_else(|| SkError::Generic("Create radial gradient failed".to_owned()))?, ) } }