From f161ab8e57b0149b368f892f11c83d953c55dd5a Mon Sep 17 00:00:00 2001 From: Utsav Oza Date: Sat, 23 May 2020 22:03:04 +0530 Subject: [PATCH] Basic implementation of canvas.fillText --- components/canvas/canvas_data.rs | 36 +++++++++++++++++++++++++---- components/canvas/raqote_backend.rs | 29 +++++++++++++++++++++++ 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index c3e02b674638..a3616f7e3dac 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -264,6 +264,15 @@ pub trait GenericDrawTarget { operator: CompositionOp, ); fn fill(&mut self, path: &Path, pattern: Pattern, draw_options: &DrawOptions); + fn fill_text( + &mut self, + text: String, + x: f64, + y: f64, + max_width: Option, + pattern: Pattern, + draw_options: &DrawOptions, + ); fn fill_rect(&mut self, rect: &Rect, pattern: Pattern, draw_options: Option<&DrawOptions>); fn get_format(&self) -> SurfaceFormat; fn get_size(&self) -> Size2D; @@ -456,10 +465,29 @@ impl<'a> CanvasData<'a> { } } - pub fn fill_text(&self, text: String, x: f64, y: f64, max_width: Option) { - error!( - "Unimplemented canvas2d.fillText. Values received: {}, {}, {}, {:?}.", - text, x, y, max_width + pub fn fill_text(&mut self, text: String, x: f64, y: f64, max_width: Option) { + // 1. If maxWidth was provided but is less than or equal to zero or equal to NaN, + // then return an empty array. + if max_width.map_or(false, |max_width| max_width <= 0.) { + return; + } + + // 2. Replace all ASCII whitespace in text with U+0020 SPACE characters. + let text = text + .chars() + .map(|c| match c { + ' ' | '\t' | '\n' | '\r' | '\x0C' => '\x20', + _ => c, + }) + .collect(); + + self.draw_target.fill_text( + text, + x, + y, + max_width, + self.state.fill_style.clone(), + &self.state.draw_options, ); } diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 72eae8b40c8a..c732d686472c 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -13,6 +13,9 @@ use canvas_traits::canvas::*; use cssparser::RGBA; use euclid::default::{Point2D, Rect, Size2D, Transform2D, Vector2D}; use euclid::Angle; +use font_kit::family_name::FamilyName; +use font_kit::properties::Properties; +use font_kit::source::SystemSource; use lyon_geom::Arc; use raqote::PathOp; use std::marker::PhantomData; @@ -513,6 +516,32 @@ impl GenericDrawTarget for raqote::DrawTarget { ), } } + + fn fill_text( + &mut self, + text: String, + x: f64, + y: f64, + max_width: Option, + pattern: canvas_data::Pattern, + draw_options: &DrawOptions, + ) { + let font = SystemSource::new() + .select_best_match(&[FamilyName::SansSerif], &Properties::new()) + .unwrap() + .load() + .unwrap(); + + self.draw_text( + &font, + 24., + &text, + Point2D::new(x as f32, y as f32), + &pattern.source(), + draw_options.as_raqote(), + ); + } + fn fill_rect( &mut self, rect: &Rect,