aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <servo-ops@mozilla.com>2020-06-12 13:43:51 -0400
committerGitHub <noreply@github.com>2020-06-12 13:43:51 -0400
commit721271dcd3c20db5ca8cf146e2b5907647afb4d6 (patch)
tree75360f129a6172fd64040d46d88bdc2a8b0f66d0
parentcb92a15600771a69a796f88975d8100f4be296ae (diff)
parent502f34a9db36202cd89f7a1b48bd138d2ce6f46e (diff)
downloadservo-721271dcd3c20db5ca8cf146e2b5907647afb4d6.tar.gz
servo-721271dcd3c20db5ca8cf146e2b5907647afb4d6.zip
Auto merge of #26697 - utsavoza:ugo/issue-11681/22-05-2020, r=jdm
Implement CanvasRenderingContext2d.fillText The PR consists of broadly two main changes: - Implementation of Canvas2dRenderingContext.font - Basic implementation of Canvas2dRenderingContext.fillText Although I am not fully sure about the long term goals for the canvas backend in Servo, I assumed limited scope for font and text handling (should support simple text drawing with font selection) in the current implementation as I believe a more complete implementation would eventually be brought in as a part of #22957. --- - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #11681 - [x] There are tests for these changes
-rw-r--r--Cargo.lock6
-rw-r--r--components/canvas/Cargo.toml6
-rw-r--r--components/canvas/canvas_data.rs234
-rw-r--r--components/canvas/canvas_paint_thread.rs27
-rw-r--r--components/canvas/raqote_backend.rs24
-rw-r--r--components/canvas_traits/Cargo.toml1
-rw-r--r--components/canvas_traits/canvas.rs94
-rw-r--r--components/layout/query.rs128
-rw-r--r--components/layout_2020/query.rs19
-rw-r--r--components/layout_thread/lib.rs27
-rw-r--r--components/layout_thread_2020/lib.rs12
-rw-r--r--components/script/canvas_state.rs172
-rw-r--r--components/script/dom/bindings/trace.rs8
-rw-r--r--components/script/dom/canvasrenderingcontext2d.rs47
-rw-r--r--components/script/dom/offscreencanvasrenderingcontext2d.rs57
-rw-r--r--components/script/dom/webidls/CanvasRenderingContext2D.webidl8
-rw-r--r--components/script/dom/window.rs17
-rw-r--r--components/script_layout_interface/message.rs3
-rw-r--r--components/script_layout_interface/rpc.rs4
-rw-r--r--components/servo/lib.rs10
-rw-r--r--components/style/Cargo.toml1
-rw-r--r--components/style/lib.rs2
-rw-r--r--components/style/properties/properties.mako.rs1
-rw-r--r--components/style/values/computed/font.rs54
-rw-r--r--components/style/values/specified/font.rs2
-rw-r--r--tests/wpt/metadata/html/canvas/element/manual/text-styles/canvas_text_font_001.htm.ini2
-rw-r--r--tests/wpt/metadata/html/canvas/element/text-styles/2d.text.align.default.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/element/text-styles/2d.text.align.invalid.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/element/text-styles/2d.text.baseline.default.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/element/text-styles/2d.text.baseline.invalid.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.default.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.parse.basic.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.parse.size.percentage.default.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.parse.size.percentage.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.parse.system.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.relative_size.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/element/the-canvas-state/2d.state.saverestore.font.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/element/the-canvas-state/2d.state.saverestore.textAlign.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/element/the-canvas-state/2d.state.saverestore.textBaseline.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/offscreen/text/2d.text.align.default.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/offscreen/text/2d.text.align.default.worker.js.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/offscreen/text/2d.text.align.invalid.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/offscreen/text/2d.text.align.invalid.worker.js.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/offscreen/text/2d.text.baseline.default.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/offscreen/text/2d.text.baseline.default.worker.js.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/offscreen/text/2d.text.baseline.invalid.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/offscreen/text/2d.text.baseline.invalid.worker.js.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.default.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.default.worker.js.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.parse.system.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.parse.system.worker.js.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.parse.tiny.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.parse.tiny.worker.js.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.relative_size.html.ini4
-rw-r--r--tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.relative_size.worker.js.ini4
-rw-r--r--tests/wpt/metadata/html/dom/idlharness.https.html.ini24
-rw-r--r--tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/initial.reset.2dstate.html.ini5
57 files changed, 928 insertions, 183 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 4765c9e5262..ac468c29aa1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -504,6 +504,8 @@ dependencies = [
"cssparser",
"euclid",
"fnv",
+ "font-kit",
+ "gfx",
"gleam 0.11.0",
"half",
"ipc-channel",
@@ -512,8 +514,10 @@ dependencies = [
"num-traits",
"pixels",
"raqote",
+ "servo_arc",
"servo_config",
"sparkle",
+ "style",
"surfman",
"surfman-chains",
"surfman-chains-api",
@@ -541,6 +545,7 @@ dependencies = [
"serde_bytes",
"servo_config",
"sparkle",
+ "style",
"time",
"webrender_api",
"webxr-api",
@@ -5429,6 +5434,7 @@ dependencies = [
"encoding_rs",
"euclid",
"fallible",
+ "font-kit",
"fxhash",
"hashglobe",
"html5ever",
diff --git a/components/canvas/Cargo.toml b/components/canvas/Cargo.toml
index 5486dc4c9ea..7285776ddec 100644
--- a/components/canvas/Cargo.toml
+++ b/components/canvas/Cargo.toml
@@ -22,7 +22,9 @@ canvas_traits = { path = "../canvas_traits" }
crossbeam-channel = "0.4"
cssparser = "0.27"
euclid = "0.20"
+font-kit = "0.7"
fnv = "1.0"
+gfx = { path = "../gfx" }
gleam = "0.11"
half = "1"
ipc-channel = "0.14"
@@ -30,9 +32,11 @@ log = "0.4"
lyon_geom = "0.14"
num-traits = "0.2"
pixels = { path = "../pixels" }
-raqote = "0.8"
+raqote = { version = "0.8", features = ["text"] }
+servo_arc = { path = "../servo_arc" }
servo_config = { path = "../config" }
sparkle = "0.1.24"
+style = { path = "../style" }
# NOTE: the sm-angle feature only enables ANGLE on Windows, not other platforms!
surfman = { version = "0.2", features = ["sm-angle", "sm-angle-default"] }
surfman-chains = "0.3"
diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs
index 33da592c235..402c2690257 100644
--- a/components/canvas/canvas_data.rs
+++ b/components/canvas/canvas_data.rs
@@ -7,12 +7,24 @@ use crate::raqote_backend::Repetition;
use canvas_traits::canvas::*;
use cssparser::RGBA;
use euclid::default::{Point2D, Rect, Size2D, Transform2D, Vector2D};
+use euclid::{point2, vec2};
+use font_kit::family_name::FamilyName;
+use font_kit::font::Font;
+use font_kit::metrics::Metrics;
+use font_kit::properties::Properties;
+use font_kit::source::SystemSource;
+use gfx::font::FontHandleMethods;
+use gfx::font_cache_thread::FontCacheThread;
+use gfx::font_context::FontContext;
use ipc_channel::ipc::{IpcSender, IpcSharedMemory};
use num_traits::ToPrimitive;
+use servo_arc::Arc as ServoArc;
+use std::cell::RefCell;
#[allow(unused_imports)]
use std::marker::PhantomData;
use std::mem;
-use std::sync::Arc;
+use std::sync::{Arc, Mutex};
+use style::properties::style_structs::Font as FontStyleStruct;
use webrender_api::units::RectExt as RectExt_;
/// The canvas data stores a state machine for the current status of
@@ -264,6 +276,15 @@ pub trait GenericDrawTarget {
operator: CompositionOp,
);
fn fill(&mut self, path: &Path, pattern: Pattern, draw_options: &DrawOptions);
+ fn fill_text(
+ &mut self,
+ font: &Font,
+ point_size: f32,
+ text: &str,
+ start: Point2D<f32>,
+ pattern: &Pattern,
+ draw_options: &DrawOptions,
+ );
fn fill_rect(&mut self, rect: &Rect<f32>, pattern: Pattern, draw_options: Option<&DrawOptions>);
fn get_format(&self) -> SurfaceFormat;
fn get_size(&self) -> Size2D<i32>;
@@ -360,6 +381,21 @@ pub enum Filter {
Point,
}
+pub(crate) type CanvasFontContext = FontContext<FontCacheThread>;
+
+thread_local!(static FONT_CONTEXT: RefCell<Option<CanvasFontContext>> = RefCell::new(None));
+
+pub(crate) fn with_thread_local_font_context<F, R>(canvas_data: &CanvasData, f: F) -> R
+where
+ F: FnOnce(&mut CanvasFontContext) -> R,
+{
+ FONT_CONTEXT.with(|font_context| {
+ f(font_context.borrow_mut().get_or_insert_with(|| {
+ FontContext::new(canvas_data.font_cache_thread.lock().unwrap().clone())
+ }))
+ })
+}
+
pub struct CanvasData<'a> {
backend: Box<dyn Backend>,
drawtarget: Box<dyn GenericDrawTarget>,
@@ -372,7 +408,7 @@ pub struct CanvasData<'a> {
old_image_key: Option<webrender_api::ImageKey>,
/// An old webrender image key that can be deleted when the current epoch ends.
very_old_image_key: Option<webrender_api::ImageKey>,
- pub canvas_id: CanvasId,
+ font_cache_thread: Mutex<FontCacheThread>,
}
fn create_backend() -> Box<dyn Backend> {
@@ -384,7 +420,7 @@ impl<'a> CanvasData<'a> {
size: Size2D<u64>,
webrender_api: Box<dyn WebrenderApi>,
antialias: AntialiasMode,
- canvas_id: CanvasId,
+ font_cache_thread: FontCacheThread,
) -> CanvasData<'a> {
let backend = create_backend();
let draw_target = backend.create_drawtarget(size);
@@ -398,7 +434,7 @@ impl<'a> CanvasData<'a> {
image_key: None,
old_image_key: None,
very_old_image_key: None,
- canvas_id: canvas_id,
+ font_cache_thread: Mutex::new(font_cache_thread),
}
}
@@ -456,11 +492,114 @@ impl<'a> CanvasData<'a> {
}
}
- pub fn fill_text(&self, text: String, x: f64, y: f64, max_width: Option<f64>) {
- error!(
- "Unimplemented canvas2d.fillText. Values received: {}, {}, {}, {:?}.",
- text, x, y, max_width
+ // https://html.spec.whatwg.org/multipage/#text-preparation-algorithm
+ pub fn fill_text(
+ &mut self,
+ text: String,
+ x: f64,
+ y: f64,
+ max_width: Option<f64>,
+ is_rtl: bool,
+ ) {
+ // Step 2.
+ let text = replace_ascii_whitespace(text);
+
+ // Step 3.
+ let point_size = self
+ .state
+ .font_style
+ .as_ref()
+ .map_or(10., |style| style.font_size.size().px());
+ let font_style = self.state.font_style.as_ref();
+ let font = font_style.map_or_else(
+ || load_system_font_from_style(None),
+ |style| {
+ with_thread_local_font_context(&self, |font_context| {
+ let font_group = font_context.font_group(ServoArc::new(style.clone()));
+ let font = font_group
+ .borrow_mut()
+ .first(font_context)
+ .expect("couldn't find font");
+ let font = font.borrow_mut();
+ // Retrieving bytes from font template seems to panic for some core text fonts.
+ // This check avoids having to obtain bytes from the font template data if they
+ // are not already in the memory.
+ if let Some(bytes) = font.handle.template().bytes_if_in_memory() {
+ Font::from_bytes(Arc::new(bytes), 0)
+ .unwrap_or_else(|_| load_system_font_from_style(Some(style)))
+ } else {
+ load_system_font_from_style(Some(style))
+ }
+ })
+ },
+ );
+ let font_width = font_width(&text, point_size, &font);
+
+ // Step 6.
+ let max_width = max_width.map(|width| width as f32);
+ let (width, scale_factor) = match max_width {
+ Some(max_width) if max_width > font_width => (max_width, 1.),
+ Some(max_width) => (font_width, max_width / font_width),
+ None => (font_width, 1.),
+ };
+
+ // Step 7.
+ let start = self.text_origin(x as f32, y as f32, &font.metrics(), width, is_rtl);
+
+ // TODO: Bidi text layout
+
+ let old_transform = self.get_transform();
+ self.set_transform(
+ &old_transform
+ .pre_translate(vec2(start.x, 0.))
+ .pre_scale(scale_factor, 1.)
+ .pre_translate(vec2(-start.x, 0.)),
);
+
+ // Step 8.
+ self.drawtarget.fill_text(
+ &font,
+ point_size,
+ &text,
+ start,
+ &self.state.fill_style,
+ &self.state.draw_options,
+ );
+
+ self.set_transform(&old_transform);
+ }
+
+ fn text_origin(
+ &self,
+ x: f32,
+ y: f32,
+ metrics: &Metrics,
+ width: f32,
+ is_rtl: bool,
+ ) -> Point2D<f32> {
+ let text_align = match self.state.text_align {
+ TextAlign::Start if is_rtl => TextAlign::Right,
+ TextAlign::Start => TextAlign::Left,
+ TextAlign::End if is_rtl => TextAlign::Left,
+ TextAlign::End => TextAlign::Right,
+ text_align => text_align,
+ };
+ let anchor_x = match text_align {
+ TextAlign::Center => -width / 2.,
+ TextAlign::Right => -width,
+ _ => 0.,
+ };
+
+ let anchor_y = match self.state.text_baseline {
+ TextBaseline::Top => metrics.ascent,
+ TextBaseline::Hanging => metrics.ascent * HANGING_BASELINE_DEFAULT,
+ TextBaseline::Ideographic => -metrics.descent * IDEOGRAPHIC_BASELINE_DEFAULT,
+ TextBaseline::Middle => (metrics.ascent - metrics.descent) / 2.,
+ TextBaseline::Alphabetic => 0.,
+ TextBaseline::Bottom => -metrics.descent,
+ };
+
+ point2(x + anchor_x, y + anchor_y)
}
pub fn fill_rect(&mut self, rect: &Rect<f32>) {
@@ -1042,6 +1181,18 @@ impl<'a> CanvasData<'a> {
self.backend.set_shadow_color(value, &mut self.state);
}
+ pub fn set_font(&mut self, font_style: FontStyleStruct) {
+ self.state.font_style = Some(font_style)
+ }
+
+ pub fn set_text_align(&mut self, text_align: TextAlign) {
+ self.state.text_align = text_align;
+ }
+
+ pub fn set_text_baseline(&mut self, text_baseline: TextBaseline) {
+ self.state.text_baseline = text_baseline;
+ }
+
// https://html.spec.whatwg.org/multipage/#when-shadows-are-drawn
fn need_to_draw_shadow(&self) -> bool {
self.backend.need_to_draw_shadow(&self.state.shadow_color) &&
@@ -1121,6 +1272,9 @@ impl<'a> Drop for CanvasData<'a> {
}
}
+const HANGING_BASELINE_DEFAULT: f32 = 0.8;
+const IDEOGRAPHIC_BASELINE_DEFAULT: f32 = 0.5;
+
#[derive(Clone)]
pub struct CanvasPaintState<'a> {
pub draw_options: DrawOptions,
@@ -1133,6 +1287,9 @@ pub struct CanvasPaintState<'a> {
pub shadow_offset_y: f64,
pub shadow_blur: f64,
pub shadow_color: Color,
+ pub font_style: Option<FontStyleStruct>,
+ pub text_align: TextAlign,
+ pub text_baseline: TextBaseline,
}
/// It writes an image to the destination target
@@ -1214,3 +1371,64 @@ impl RectExt for Rect<u32> {
self.cast()
}
}
+
+fn load_system_font_from_style(font_style: Option<&FontStyleStruct>) -> Font {
+ let mut properties = Properties::new();
+ let style = match font_style {
+ Some(style) => style,
+ None => return load_default_system_fallback_font(&properties),
+ };
+ let family_names = style
+ .font_family
+ .families
+ .iter()
+ .map(|family_name| family_name.into())
+ .collect::<Vec<FamilyName>>();
+ let properties = properties
+ .style(style.font_style.into())
+ .weight(style.font_weight.into())
+ .stretch(style.font_stretch.into());
+ let font_handle = match SystemSource::new().select_best_match(&family_names, &properties) {
+ Ok(handle) => handle,
+ Err(e) => {
+ error!("error getting font handle for style {:?}: {}", style, e);
+ return load_default_system_fallback_font(&properties);
+ },
+ };
+ font_handle.load().unwrap_or_else(|e| {
+ error!("error loading font for style {:?}: {}", style, e);
+ load_default_system_fallback_font(&properties)
+ })
+}
+
+fn load_default_system_fallback_font(properties: &Properties) -> Font {
+ SystemSource::new()
+ .select_best_match(&[FamilyName::SansSerif], properties)
+ .expect("error getting font handle for default system font")
+ .load()
+ .expect("error loading default system font")
+}
+
+fn replace_ascii_whitespace(text: String) -> String {
+ text.chars()
+ .map(|c| match c {
+ ' ' | '\t' | '\n' | '\r' | '\x0C' => '\x20',
+ _ => c,
+ })
+ .collect()
+}
+
+// TODO: This currently calculates the width using just advances and doesn't
+// determine the fallback font in case a character glyph isn't found.
+fn font_width(text: &str, point_size: f32, font: &Font) -> f32 {
+ let metrics = font.metrics();
+ let mut width = 0.;
+ for c in text.chars() {
+ if let Some(glyph_id) = font.glyph_for_char(c) {
+ if let Ok(advance) = font.advance(glyph_id) {
+ width += advance.x() * point_size / metrics.units_per_em as f32;
+ }
+ }
+ }
+ width
+}
diff --git a/components/canvas/canvas_paint_thread.rs b/components/canvas/canvas_paint_thread.rs
index 3c6bbfb53a8..b426d398a72 100644
--- a/components/canvas/canvas_paint_thread.rs
+++ b/components/canvas/canvas_paint_thread.rs
@@ -7,6 +7,7 @@ use canvas_traits::canvas::*;
use canvas_traits::ConstellationCanvasMsg;
use crossbeam_channel::{select, unbounded, Sender};
use euclid::default::Size2D;
+use gfx::font_cache_thread::FontCacheThread;
use ipc_channel::ipc::{self, IpcSender};
use ipc_channel::router::ROUTER;
use std::borrow::ToOwned;
@@ -35,14 +36,19 @@ pub struct CanvasPaintThread<'a> {
canvases: HashMap<CanvasId, CanvasData<'a>>,
next_canvas_id: CanvasId,
webrender_api: Box<dyn WebrenderApi>,
+ font_cache_thread: FontCacheThread,
}
impl<'a> CanvasPaintThread<'a> {
- fn new(webrender_api: Box<dyn WebrenderApi>) -> CanvasPaintThread<'a> {
+ fn new(
+ webrender_api: Box<dyn WebrenderApi>,
+ font_cache_thread: FontCacheThread,
+ ) -> CanvasPaintThread<'a> {
CanvasPaintThread {
canvases: HashMap::new(),
next_canvas_id: CanvasId(0),
webrender_api,
+ font_cache_thread,
}
}
@@ -50,6 +56,7 @@ impl<'a> CanvasPaintThread<'a> {
/// communicate with it.
pub fn start(
webrender_api: Box<dyn WebrenderApi + Send>,
+ font_cache_thread: FontCacheThread,
) -> (Sender<ConstellationCanvasMsg>, IpcSender<CanvasMsg>) {
let (ipc_sender, ipc_receiver) = ipc::channel::<CanvasMsg>().unwrap();
let msg_receiver = ROUTER.route_ipc_receiver_to_new_crossbeam_receiver(ipc_receiver);
@@ -57,7 +64,7 @@ impl<'a> CanvasPaintThread<'a> {
thread::Builder::new()
.name("CanvasThread".to_owned())
.spawn(move || {
- let mut canvas_paint_thread = CanvasPaintThread::new(webrender_api);
+ let mut canvas_paint_thread = CanvasPaintThread::new(webrender_api, font_cache_thread);
loop {
select! {
recv(msg_receiver) -> msg => {
@@ -118,6 +125,8 @@ impl<'a> CanvasPaintThread<'a> {
AntialiasMode::None
};
+ let font_cache_thread = self.font_cache_thread.clone();
+
let canvas_id = self.next_canvas_id.clone();
self.next_canvas_id.0 += 1;
@@ -125,7 +134,7 @@ impl<'a> CanvasPaintThread<'a> {
size,
self.webrender_api.clone(),
antialias,
- canvas_id.clone(),
+ font_cache_thread,
);
self.canvases.insert(canvas_id.clone(), canvas_data);
@@ -134,9 +143,10 @@ impl<'a> CanvasPaintThread<'a> {
fn process_canvas_2d_message(&mut self, message: Canvas2dMsg, canvas_id: CanvasId) {
match message {
- Canvas2dMsg::FillText(text, x, y, max_width, style) => {
+ Canvas2dMsg::FillText(text, x, y, max_width, style, is_rtl) => {
self.canvas(canvas_id).set_fill_style(style);
- self.canvas(canvas_id).fill_text(text, x, y, max_width);
+ self.canvas(canvas_id)
+ .fill_text(text, x, y, max_width, is_rtl);
},
Canvas2dMsg::FillRect(rect, style) => {
self.canvas(canvas_id).set_fill_style(style);
@@ -247,6 +257,13 @@ impl<'a> CanvasPaintThread<'a> {
},
Canvas2dMsg::SetShadowBlur(value) => self.canvas(canvas_id).set_shadow_blur(value),
Canvas2dMsg::SetShadowColor(color) => self.canvas(canvas_id).set_shadow_color(color),
+ Canvas2dMsg::SetFont(font_style) => self.canvas(canvas_id).set_font(font_style),
+ Canvas2dMsg::SetTextAlign(text_align) => {
+ self.canvas(canvas_id).set_text_align(text_align)
+ },
+ Canvas2dMsg::SetTextBaseline(text_baseline) => {
+ self.canvas(canvas_id).set_text_baseline(text_baseline)
+ },
}
}
diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs
index 72eae8b40c8..5f39a1260b3 100644
--- a/components/canvas/raqote_backend.rs
+++ b/components/canvas/raqote_backend.rs
@@ -13,6 +13,7 @@ use canvas_traits::canvas::*;
use cssparser::RGBA;
use euclid::default::{Point2D, Rect, Size2D, Transform2D, Vector2D};
use euclid::Angle;
+use font_kit::font::Font;
use lyon_geom::Arc;
use raqote::PathOp;
use std::marker::PhantomData;
@@ -87,6 +88,9 @@ impl<'a> CanvasPaintState<'a> {
shadow_offset_y: 0.0,
shadow_blur: 0.0,
shadow_color: Color::Raqote(raqote::SolidSource::from_unpremultiplied_argb(0, 0, 0, 0)),
+ font_style: None,
+ text_align: TextAlign::default(),
+ text_baseline: TextBaseline::default(),
}
}
}
@@ -513,6 +517,26 @@ impl GenericDrawTarget for raqote::DrawTarget {
),
}
}
+
+ fn fill_text(
+ &mut self,
+ font: &Font,
+ point_size: f32,
+ text: &str,
+ start: Point2D<f32>,
+ pattern: &canvas_data::Pattern,
+ options: &DrawOptions,
+ ) {
+ self.draw_text(
+ font,
+ point_size,
+ text,
+ start,
+ &pattern.source(),
+ options.as_raqote(),
+ );
+ }
+
fn fill_rect(
&mut self,
rect: &Rect<f32>,
diff --git a/components/canvas_traits/Cargo.toml b/components/canvas_traits/Cargo.toml
index 0625221a484..8414349939c 100644
--- a/components/canvas_traits/Cargo.toml
+++ b/components/canvas_traits/Cargo.toml
@@ -27,6 +27,7 @@ serde = "1.0"
serde_bytes = "0.11"
servo_config = { path = "../config" }
sparkle = "0.1"
+style = { path = "../style" }
time = { version = "0.1.0", optional = true }
webrender_api = { git = "https://github.com/servo/webrender" }
webxr-api = { git = "https://github.com/servo/webxr", features = ["ipc"] }
diff --git a/components/canvas_traits/canvas.rs b/components/canvas_traits/canvas.rs
index 13fc6eaa800..f302aaa8e3e 100644
--- a/components/canvas_traits/canvas.rs
+++ b/components/canvas_traits/canvas.rs
@@ -8,6 +8,7 @@ use ipc_channel::ipc::{IpcBytesReceiver, IpcBytesSender, IpcSender, IpcSharedMem
use serde_bytes::ByteBuf;
use std::default::Default;
use std::str::FromStr;
+use style::properties::style_structs::Font as FontStyleStruct;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum FillRule {
@@ -45,7 +46,7 @@ pub enum Canvas2dMsg {
ClosePath,
Ellipse(Point2D<f32>, f32, f32, f32, f32, f32, bool),
Fill(FillOrStrokeStyle),
- FillText(String, f64, f64, Option<f64>, FillOrStrokeStyle),
+ FillText(String, f64, f64, Option<f64>, FillOrStrokeStyle, bool),
FillRect(Rect<f32>, FillOrStrokeStyle),
GetImageData(Rect<u64>, Size2D<u64>, IpcBytesSender),
GetTransform(IpcSender<Transform2D<f32>>),
@@ -70,6 +71,9 @@ pub enum Canvas2dMsg {
SetShadowOffsetY(f64),
SetShadowBlur(f64),
SetShadowColor(RGBA),
+ SetFont(FontStyleStruct),
+ SetTextAlign(TextAlign),
+ SetTextBaseline(TextBaseline),
}
#[derive(Clone, Debug, Deserialize, Serialize)]
@@ -392,3 +396,91 @@ impl FromStr for CompositionOrBlending {
Err(())
}
}
+
+#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
+pub enum TextAlign {
+ Start,
+ End,
+ Left,
+ Right,
+ Center,
+}
+
+impl FromStr for TextAlign {
+ type Err = ();
+
+ fn from_str(string: &str) -> Result<TextAlign, ()> {
+ match string {
+ "start" => Ok(TextAlign::Start),
+ "end" => Ok(TextAlign::End),
+ "left" => Ok(TextAlign::Left),
+ "right" => Ok(TextAlign::Right),
+ "center" => Ok(TextAlign::Center),
+ _ => Err(()),
+ }
+ }
+}
+
+impl Default for TextAlign {
+ fn default() -> TextAlign {
+ TextAlign::Start
+ }
+}
+
+#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
+pub enum TextBaseline {
+ Top,
+ Hanging,
+ Middle,
+ Alphabetic,
+ Ideographic,
+ Bottom,
+}
+
+impl FromStr for TextBaseline {
+ type Err = ();
+
+ fn from_str(string: &str) -> Result<TextBaseline, ()> {
+ match string {
+ "top" => Ok(TextBaseline::Top),
+ "hanging" => Ok(TextBaseline::Hanging),
+ "middle" => Ok(TextBaseline::Middle),
+ "alphabetic" => Ok(TextBaseline::Alphabetic),
+ "ideographic" => Ok(TextBaseline::Ideographic),
+ "bottom" => Ok(TextBaseline::Bottom),
+ _ => Err(()),
+ }
+ }
+}
+
+impl Default for TextBaseline {
+ fn default() -> TextBaseline {
+ TextBaseline::Alphabetic
+ }
+}
+
+#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
+pub enum Direction {
+ Ltr,
+ Rtl,
+ Inherit,
+}
+
+impl FromStr for Direction {
+ type Err = ();
+
+ fn from_str(string: &str) -> Result<Direction, ()> {
+ match string {
+ "ltr" => Ok(Direction::Ltr),
+ "rtl" => Ok(Direction::Rtl),
+ "inherit" => Ok(Direction::Inherit),
+ _ => Err(()),
+ }
+ }
+}
+
+impl Default for Direction {
+ fn default() -> Direction {
+ Direction::Inherit
+ }
+}
diff --git a/components/layout/query.rs b/components/layout/query.rs
index a5f66cb9dcd..56b1fc7d0f8 100644
--- a/components/layout/query.rs
+++ b/components/layout/query.rs
@@ -29,18 +29,25 @@ use script_layout_interface::wrapper_traits::{
use script_layout_interface::{LayoutElementType, LayoutNodeType};
use script_traits::LayoutMsg as ConstellationMsg;
use script_traits::UntrustedNodeAddress;
+use servo_arc::Arc as ServoArc;
+use servo_url::ServoUrl;
use std::cmp::{max, min};
use std::ops::Deref;
use std::sync::{Arc, Mutex};
use style::computed_values::display::T as Display;
use style::computed_values::position::T as Position;
use style::computed_values::visibility::T as Visibility;
-use style::context::{StyleContext, ThreadLocalStyleContext};
+use style::context::{QuirksMode, SharedStyleContext, StyleContext, ThreadLocalStyleContext};
use style::dom::TElement;
use style::logical_geometry::{BlockFlowDirection, InlineBaseDirection, WritingMode};
-use style::properties::{style_structs, LonghandId, PropertyDeclarationId, PropertyId};
+use style::properties::style_structs::{self, Font};
+use style::properties::{
+ parse_one_declaration_into, ComputedValues, Importance, LonghandId, PropertyDeclarationBlock,
+ PropertyDeclarationId, PropertyId, SourcePropertyDeclaration,
+};
use style::selector_parser::PseudoElement;
-use style_traits::{CSSPixel, ToCss};
+use style::shared_lock::SharedRwLock;
+use style_traits::{CSSPixel, ParsingMode, ToCss};
use webrender_api::ExternalScrollId;
/// Mutable data belonging to the LayoutThread.
@@ -73,6 +80,9 @@ pub struct LayoutThreadData {
/// A queued response for the resolved style property of an element.
pub resolved_style_response: String,
+ /// A queued response for the resolved font style for canvas.
+ pub resolved_font_style_response: Option<ServoArc<Font>>,
+
/// A queued response for the offset parent/rect of a node.
pub offset_parent_response: OffsetParentResponse,
@@ -170,6 +180,12 @@ impl LayoutRPC for LayoutRPCImpl {
ResolvedStyleResponse(rw_data.resolved_style_response.clone())
}
+ fn resolved_font_style(&self) -> Option<ServoArc<Font>> {
+ let &LayoutRPCImpl(ref rw_data) = self;
+ let rw_data = rw_data.lock().unwrap();
+ rw_data.resolved_font_style_response.clone()
+ }
+
fn offset_parent(&self) -> OffsetParentResponse {
let &LayoutRPCImpl(ref rw_data) = self;
let rw_data = rw_data.lock().unwrap();
@@ -735,6 +751,112 @@ pub fn process_node_scroll_area_request(
}
}
+fn create_font_declaration(
+ value: &str,
+ property: &PropertyId,
+ url_data: &ServoUrl,
+ quirks_mode: QuirksMode,
+) -> Option<PropertyDeclarationBlock> {
+ let mut declarations = SourcePropertyDeclaration::new();
+ let result = parse_one_declaration_into(
+ &mut declarations,
+ property.clone(),
+ value,
+ url_data,
+ None,
+ ParsingMode::DEFAULT,
+ quirks_mode,
+ );
+ let declarations = match result {
+ Ok(()) => {
+ let mut block = PropertyDeclarationBlock::new();
+ block.extend(declarations.drain(), Importance::Normal);
+ block
+ },
+ Err(_) => return None,
+ };
+ // TODO: Force to set line-height property to 'normal' font property.
+ Some(declarations)
+}
+
+fn resolve_for_declarations<'dom, E>(
+ context: &SharedStyleContext,
+ parent_style: Option<&ComputedValues>,
+ declarations: PropertyDeclarationBlock,
+ shared_lock: &SharedRwLock,
+) -> ServoArc<ComputedValues>
+where
+ E: LayoutNode<'dom>,
+{
+ let parent_style = match parent_style {
+ Some(parent) => &*parent,
+ None => context.stylist.device().default_computed_values(),
+ };
+ context
+ .stylist
+ .compute_for_declarations::<E::ConcreteElement>(
+ &context.guards,
+ &*parent_style,
+ ServoArc::new(shared_lock.wrap(declarations)),
+ )
+}
+
+pub fn process_resolved_font_style_request<'dom, E>(
+ context: &LayoutContext,
+ node: E,
+ value: &str,
+ property: &PropertyId,
+ url_data: ServoUrl,
+ shared_lock: &SharedRwLock,
+) -> Option<ServoArc<Font>>
+where
+ E: LayoutNode<'dom>,
+{
+ use style::stylist::RuleInclusion;
+ use style::traversal::resolve_style;
+
+ // 1. Parse the given font property value
+ let quirks_mode = context.style_context.quirks_mode();
+ let declarations = create_font_declaration(value, property, &url_data, quirks_mode)?;
+
+ // TODO: Reject 'inherit' and 'initial' values for the font property.
+
+ // 2. Get resolved styles for the parent element
+ let element = node.as_element().unwrap();
+ let parent_style = if node.is_connected() {
+ if element.has_data() {
+ node.to_threadsafe().as_element().unwrap().resolved_style()
+ } else {
+ let mut tlc = ThreadLocalStyleContext::new(&context.style_context);
+ let mut context = StyleContext {
+ shared: &context.style_context,
+ thread_local: &mut tlc,
+ };
+ let styles = resolve_style(&mut context, element, RuleInclusion::All, None);
+ styles.primary().clone()
+ }
+ } else {
+ let default_declarations =
+ create_font_declaration("10px sans-serif", property, &url_data, quirks_mode).unwrap();
+ resolve_for_declarations::<E>(
+ &context.style_context,
+ None,
+ default_declarations,
+ shared_lock,
+ )
+ };
+
+ // 3. Resolve the parsed value with resolved styles of the parent element
+ let computed_values = resolve_for_declarations::<E>(
+ &context.style_context,
+ Some(&*parent_style),
+ declarations,
+ shared_lock,
+ );
+
+ Some(computed_values.clone_font())
+}
+
/// Return the resolved value of property for a given (pseudo)element.
/// <https://drafts.csswg.org/cssom/#resolved-value>
pub fn process_resolved_style_request<'dom>(
diff --git a/components/layout_2020/query.rs b/components/layout_2020/query.rs
index 4b895025e11..6df2e789e64 100644
--- a/components/layout_2020/query.rs
+++ b/components/layout_2020/query.rs
@@ -21,12 +21,14 @@ use script_layout_interface::wrapper_traits::{
};
use script_traits::LayoutMsg as ConstellationMsg;
use script_traits::UntrustedNodeAddress;
+use servo_arc::Arc as ServoArc;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use style::computed_values::position::T as Position;
use style::context::{StyleContext, ThreadLocalStyleContext};
use style::dom::OpaqueNode;
use style::dom::TElement;
+use style::properties::style_structs::Font;
use style::properties::{LonghandId, PropertyDeclarationId, PropertyId};
use style::selector_parser::PseudoElement;
use style::stylist::RuleInclusion;
@@ -65,6 +67,9 @@ pub struct LayoutThreadData {
/// A queued response for the resolved style property of an element.
pub resolved_style_response: String,
+ /// A queued response for the resolved font style for canvas.
+ pub resolved_font_style_response: Option<ServoArc<Font>>,
+
/// A queued response for the offset parent/rect of a node.
pub offset_parent_response: OffsetParentResponse,
@@ -139,6 +144,12 @@ impl LayoutRPC for LayoutRPCImpl {
ResolvedStyleResponse(rw_data.resolved_style_response.clone())
}
+ fn resolved_font_style(&self) -> Option<ServoArc<Font>> {
+ let &LayoutRPCImpl(ref rw_data) = self;
+ let rw_data = rw_data.lock().unwrap();
+ rw_data.resolved_font_style_response.clone()
+ }
+
fn offset_parent(&self) -> OffsetParentResponse {
let &LayoutRPCImpl(ref rw_data) = self;
let rw_data = rw_data.lock().unwrap();
@@ -376,3 +387,11 @@ pub fn process_element_inner_text_query<'dom>(_node: impl LayoutNode<'dom>) -> S
pub fn process_text_index_request(_node: OpaqueNode, _point: Point2D<Au>) -> TextIndexResponse {
TextIndexResponse(None)
}
+
+pub fn process_resolved_font_style_query<'dom>(
+ _node: impl LayoutNode<'dom>,
+ _property: &PropertyId,
+ _value: &str,
+) -> Option<ServoArc<Font>> {
+ None
+}
diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs
index 6819027564c..14dbfc0c80e 100644
--- a/components/layout_thread/lib.rs
+++ b/components/layout_thread/lib.rs
@@ -49,12 +49,13 @@ use layout::flow_ref::FlowRef;
use layout::incremental::{RelayoutMode, SpecialRestyleDamage};
use layout::layout_debug;
use layout::parallel;
-use layout::query::{process_client_rect_query, process_element_inner_text_query};
use layout::query::{
- process_content_box_request, process_content_boxes_request, LayoutRPCImpl, LayoutThreadData,
+ process_client_rect_query, process_content_box_request, process_content_boxes_request,
+ process_element_inner_text_query, process_node_scroll_area_request,
+ process_node_scroll_id_request, process_offset_parent_query,
+ process_resolved_font_style_request, process_resolved_style_request, LayoutRPCImpl,
+ LayoutThreadData,
};
-use layout::query::{process_node_scroll_area_request, process_node_scroll_id_request};
-use layout::query::{process_offset_parent_query, process_resolved_style_request};
use layout::sequential;
use layout::traversal::{
construct_flows_at_ancestors, ComputeStackingRelativePositions, PreorderFlowTraversal,
@@ -558,6 +559,7 @@ impl LayoutThread {
scroll_id_response: None,
scroll_area_response: Rect::zero(),
resolved_style_response: String::new(),
+ resolved_font_style_response: None,
offset_parent_response: OffsetParentResponse::empty(),
scroll_offsets: HashMap::new(),
text_index_response: TextIndexResponse(None),
@@ -1231,6 +1233,9 @@ impl LayoutThread {
&QueryMsg::ElementInnerTextQuery(_) => {
rw_data.element_inner_text_response = String::new();
},
+ &QueryMsg::ResolvedFontStyleQuery(..) => {
+ rw_data.resolved_font_style_response = None;
+ },
&QueryMsg::InnerWindowDimensionsQuery(_) => {
rw_data.inner_window_dimensions_response = None;
},
@@ -1498,6 +1503,7 @@ impl LayoutThread {
&mut *rw_data,
&mut layout_context,
data.result.borrow_mut().as_mut().unwrap(),
+ document_shared_lock,
);
}
@@ -1507,6 +1513,7 @@ impl LayoutThread {
rw_data: &mut LayoutThreadData,
context: &mut LayoutContext,
reflow_result: &mut ReflowComplete,
+ shared_lock: &SharedRwLock,
) {
reflow_result.pending_images =
std::mem::replace(&mut *context.pending_images.lock().unwrap(), vec![]);
@@ -1549,6 +1556,18 @@ impl LayoutThread {
rw_data.resolved_style_response =
process_resolved_style_request(context, node, pseudo, property, root_flow);
},
+ &QueryMsg::ResolvedFontStyleQuery(node, ref property, ref value) => {
+ let node = unsafe { ServoLayoutNode::new(&node) };
+ let url = self.url.clone();
+ rw_data.resolved_font_style_response = process_resolved_font_style_request(
+ context,
+ node,
+ value,
+ property,
+ url,
+ shared_lock,
+ );
+ },
&QueryMsg::OffsetParentQuery(node) => {
rw_data.offset_parent_response = process_offset_parent_query(node, root_flow);
},
diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs
index 3bb0a7a3353..4ae69e6255a 100644
--- a/components/layout_thread_2020/lib.rs
+++ b/components/layout_thread_2020/lib.rs
@@ -37,7 +37,8 @@ use layout::context::LayoutContext;
use layout::display_list::{DisplayListBuilder, WebRenderImageInfo};
use layout::layout_debug;
use layout::query::{
- process_content_box_request, process_content_boxes_request, LayoutRPCImpl, LayoutThreadData,
+ process_content_box_request, process_content_boxes_request, process_resolved_font_style_query,
+ LayoutRPCImpl, LayoutThreadData,
};
use layout::query::{process_element_inner_text_query, process_node_geometry_request};
use layout::query::{process_node_scroll_area_request, process_node_scroll_id_request};
@@ -525,6 +526,7 @@ impl LayoutThread {
scroll_id_response: None,
scroll_area_response: Rect::zero(),
resolved_style_response: String::new(),
+ resolved_font_style_response: None,
offset_parent_response: OffsetParentResponse::empty(),
scroll_offsets: HashMap::new(),
text_index_response: TextIndexResponse(None),
@@ -914,6 +916,9 @@ impl LayoutThread {
&QueryMsg::ResolvedStyleQuery(_, _, _) => {
rw_data.resolved_style_response = String::new();
},
+ &QueryMsg::ResolvedFontStyleQuery(_, _, _) => {
+ rw_data.resolved_font_style_response = None;
+ },
&QueryMsg::OffsetParentQuery(_) => {
rw_data.offset_parent_response = OffsetParentResponse::empty();
},
@@ -1206,6 +1211,11 @@ impl LayoutThread {
fragment_tree,
);
},
+ &QueryMsg::ResolvedFontStyleQuery(node, ref property, ref value) => {
+ let node = unsafe { ServoLayoutNode::new(&node) };
+ rw_data.resolved_font_style_response =
+ process_resolved_font_style_query(node, property, value);
+ },
&QueryMsg::OffsetParentQuery(node) => {
rw_data.offset_parent_response = process_offset_parent_query(node);
},
diff --git a/components/script/canvas_state.rs b/components/script/canvas_state.rs
index 2376d6f8d85..0a6fba842e4 100644
--- a/components/script/canvas_state.rs
+++ b/components/script/canvas_state.rs
@@ -3,10 +3,13 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::dom::bindings::cell::DomRefCell;
+use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasDirection;
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasFillRule;
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasImageSource;
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineCap;
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineJoin;
+use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasTextAlign;
+use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasTextBaseline;
use crate::dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods;
use crate::dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern;
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
@@ -22,12 +25,12 @@ use crate::dom::element::Element;
use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlcanvaselement::{CanvasContext, HTMLCanvasElement};
use crate::dom::imagedata::ImageData;
-use crate::dom::node::{Node, NodeDamage};
+use crate::dom::node::{window_from_node, Node, NodeDamage};
use crate::dom::offscreencanvas::{OffscreenCanvas, OffscreenCanvasContext};
use crate::dom::paintworkletglobalscope::PaintWorkletGlobalScope;
use crate::dom::textmetrics::TextMetrics;
use crate::unpremultiplytable::UNPREMULTIPLY_TABLE;
-use canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg};
+use canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg, Direction, TextAlign, TextBaseline};
use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule};
use canvas_traits::canvas::{LineCapStyle, LineJoinStyle, LinearGradientStyle};
use canvas_traits::canvas::{RadialGradientStyle, RepetitionStyle};
@@ -49,6 +52,10 @@ use std::cell::Cell;
use std::fmt;
use std::str::FromStr;
use std::sync::Arc;
+use style::properties::longhands::font_variant_caps::computed_value::T as FontVariantCaps;
+use style::properties::style_structs::Font;
+use style::values::computed::font::FontStyle;
+use style_traits::values::ToCss;
#[unrooted_must_root_lint::must_root]
#[derive(Clone, JSTraceable, MallocSizeOf)]
@@ -86,9 +93,15 @@ pub(crate) struct CanvasContextState {
shadow_offset_y: f64,
shadow_blur: f64,
shadow_color: RGBA,
+ font_style: Option<Font>,
+ text_align: TextAlign,
+ text_baseline: TextBaseline,
+ direction: Direction,
}
impl CanvasContextState {
+ const DEFAULT_FONT_STYLE: &'static str = "10px sans-serif";
+
pub(crate) fn new() -> CanvasContextState {
let black = RGBA::new(0, 0, 0, 255);
CanvasContextState {
@@ -106,6 +119,10 @@ impl CanvasContextState {
shadow_offset_y: 0.0,
shadow_blur: 0.0,
shadow_color: RGBA::transparent(),
+ font_style: None,
+ text_align: Default::default(),
+ text_baseline: Default::default(),
+ direction: Default::default(),
}
}
}
@@ -987,10 +1004,39 @@ impl CanvasState {
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-filltext
- pub fn fill_text(&self, text: DOMString, x: f64, y: f64, max_width: Option<f64>) {
- let parsed_text: String = text.into();
+ pub fn fill_text(
+ &self,
+ canvas: Option<&HTMLCanvasElement>,
+ text: DOMString,
+ x: f64,
+ y: f64,
+ max_width: Option<f64>,
+ ) {
+ if !x.is_finite() || !y.is_finite() {
+ return;
+ }
+ if max_width.map_or(false, |max_width| !max_width.is_finite() || max_width <= 0.) {
+ return;
+ }
+ if self.state.borrow().font_style.is_none() {
+ self.set_font(canvas, CanvasContextState::DEFAULT_FONT_STYLE.into())
+ }
+
+ let is_rtl = match self.state.borrow().direction {
+ Direction::Ltr => false,
+ Direction::Rtl => true,
+ Direction::Inherit => false, // TODO: resolve direction wrt to canvas element
+ };
+
let style = self.state.borrow().fill_style.to_fill_or_stroke_style();
- self.send_canvas_2d_msg(Canvas2dMsg::FillText(parsed_text, x, y, max_width, style));
+ self.send_canvas_2d_msg(Canvas2dMsg::FillText(
+ text.into(),
+ x,
+ y,
+ max_width,
+ style,
+ is_rtl,
+ ));
}
// https://html.spec.whatwg.org/multipage/#textmetrics
@@ -1002,6 +1048,101 @@ impl CanvasState {
)
}
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-font
+ pub fn set_font(&self, canvas: Option<&HTMLCanvasElement>, value: DOMString) {
+ let canvas = match canvas {
+ Some(element) => element,
+ None => return, // offscreen canvas doesn't have a placeholder canvas
+ };
+ let node = canvas.upcast::<Node>();
+ let window = window_from_node(&*canvas);
+ let resolved_font_style = match window.resolved_font_style_query(&node, value.to_string()) {
+ Some(value) => value,
+ None => return, // syntax error
+ };
+ self.state.borrow_mut().font_style = Some((*resolved_font_style).clone());
+ self.send_canvas_2d_msg(Canvas2dMsg::SetFont((*resolved_font_style).clone()));
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-font
+ pub fn font(&self) -> DOMString {
+ self.state.borrow().font_style.as_ref().map_or_else(
+ || CanvasContextState::DEFAULT_FONT_STYLE.into(),
+ |style| {
+ let mut result = String::new();
+ serialize_font(style, &mut result).unwrap();
+ DOMString::from(result)
+ },
+ )
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-textalign
+ pub fn text_align(&self) -> CanvasTextAlign {
+ match self.state.borrow().text_align {
+ TextAlign::Start => CanvasTextAlign::Start,
+ TextAlign::End => CanvasTextAlign::End,
+ TextAlign::Left => CanvasTextAlign::Left,
+ TextAlign::Right => CanvasTextAlign::Right,
+ TextAlign::Center => CanvasTextAlign::Center,
+ }
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-textalign
+ pub fn set_text_align(&self, value: CanvasTextAlign) {
+ let text_align = match value {
+ CanvasTextAlign::Start => TextAlign::Start,
+ CanvasTextAlign::End => TextAlign::End,
+ CanvasTextAlign::Left => TextAlign::Left,
+ CanvasTextAlign::Right => TextAlign::Right,
+ CanvasTextAlign::Center => TextAlign::Center,
+ };
+ self.state.borrow_mut().text_align = text_align;
+ self.send_canvas_2d_msg(Canvas2dMsg::SetTextAlign(text_align));
+ }
+
+ pub fn text_baseline(&self) -> CanvasTextBaseline {
+ match self.state.borrow().text_baseline {
+ TextBaseline::Top => CanvasTextBaseline::Top,
+ TextBaseline::Hanging => CanvasTextBaseline::Hanging,
+ TextBaseline::Middle => CanvasTextBaseline::Middle,
+ TextBaseline::Alphabetic => CanvasTextBaseline::Alphabetic,
+ TextBaseline::Ideographic => CanvasTextBaseline::Ideographic,
+ TextBaseline::Bottom => CanvasTextBaseline::Bottom,
+ }
+ }
+
+ pub fn set_text_baseline(&self, value: CanvasTextBaseline) {
+ let text_baseline = match value {
+ CanvasTextBaseline::Top => TextBaseline::Top,
+ CanvasTextBaseline::Hanging => TextBaseline::Hanging,
+ CanvasTextBaseline::Middle => TextBaseline::Middle,
+ CanvasTextBaseline::Alphabetic => TextBaseline::Alphabetic,
+ CanvasTextBaseline::Ideographic => TextBaseline::Ideographic,
+ CanvasTextBaseline::Bottom => TextBaseline::Bottom,
+ };
+ self.state.borrow_mut().text_baseline = text_baseline;
+ self.send_canvas_2d_msg(Canvas2dMsg::SetTextBaseline(text_baseline));
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-direction
+ pub fn direction(&self) -> CanvasDirection {
+ match self.state.borrow().direction {
+ Direction::Ltr => CanvasDirection::Ltr,
+ Direction::Rtl => CanvasDirection::Rtl,
+ Direction::Inherit => CanvasDirection::Inherit,
+ }
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-direction
+ pub fn set_direction(&self, value: CanvasDirection) {
+ let direction = match value {
+ CanvasDirection::Ltr => Direction::Ltr,
+ CanvasDirection::Rtl => Direction::Rtl,
+ CanvasDirection::Inherit => Direction::Inherit,
+ };
+ self.state.borrow_mut().direction = direction;
+ }
+
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth
pub fn line_width(&self) -> f64 {
self.state.borrow().line_width
@@ -1627,3 +1768,24 @@ pub fn adjust_size_sign(
}
(origin, size.to_u32())
}
+
+fn serialize_font<W>(style: &Font, dest: &mut W) -> fmt::Result
+where
+ W: fmt::Write,
+{
+ if style.font_style == FontStyle::Italic {
+ write!(dest, "{} ", style.font_style.to_css_string())?;
+ }
+ if style.font_weight.is_bold() {
+ write!(dest, "{} ", style.font_weight.to_css_string())?;
+ }
+ if style.font_variant_caps == FontVariantCaps::SmallCaps {
+ write!(dest, "{} ", style.font_variant_caps.to_css_string())?;
+ }
+ write!(
+ dest,
+ "{} {}",
+ style.font_size.to_css_string(),
+ style.font_family.to_css_string()
+ )
+}
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index 1f6d15a191a..9518a2c0989 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -47,7 +47,10 @@ use app_units::Au;
use canvas_traits::canvas::{
CanvasGradientStop, CanvasId, LinearGradientStyle, RadialGradientStyle,
};
-use canvas_traits::canvas::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle};
+use canvas_traits::canvas::{
+ CompositionOrBlending, Direction, LineCapStyle, LineJoinStyle, RepetitionStyle, TextAlign,
+ TextBaseline,
+};
use canvas_traits::webgl::WebGLVertexArrayId;
use canvas_traits::webgl::{
ActiveAttribInfo, ActiveUniformBlockInfo, ActiveUniformInfo, GlType, TexDataType, TexFormat,
@@ -144,6 +147,7 @@ use style::context::QuirksMode;
use style::dom::OpaqueNode;
use style::element_state::*;
use style::media_queries::MediaList;
+use style::properties::style_structs::Font;
use style::properties::PropertyDeclarationBlock;
use style::selector_parser::{PseudoElement, Snapshot};
use style::shared_lock::{Locked as StyleLocked, SharedRwLock as StyleSharedRwLock};
@@ -479,6 +483,7 @@ unsafe_no_jsmanaged_fields!(NetworkError);
unsafe_no_jsmanaged_fields!(Atom, Prefix, LocalName, Namespace, QualName);
unsafe_no_jsmanaged_fields!(TrustedPromise);
unsafe_no_jsmanaged_fields!(PropertyDeclarationBlock);
+unsafe_no_jsmanaged_fields!(Font);
// These three are interdependent, if you plan to put jsmanaged data
// in one of these make sure it is propagated properly to containing structs
unsafe_no_jsmanaged_fields!(DocumentActivity, WindowSizeData, WindowSizeType);
@@ -501,6 +506,7 @@ unsafe_no_jsmanaged_fields!(RGBA);
unsafe_no_jsmanaged_fields!(StorageType);
unsafe_no_jsmanaged_fields!(CanvasGradientStop, LinearGradientStyle, RadialGradientStyle);
unsafe_no_jsmanaged_fields!(LineCapStyle, LineJoinStyle, CompositionOrBlending);
+unsafe_no_jsmanaged_fields!(TextAlign, TextBaseline, Direction);
unsafe_no_jsmanaged_fields!(RepetitionStyle);
unsafe_no_jsmanaged_fields!(WebGLError, GLLimits, GlType);
unsafe_no_jsmanaged_fields!(TimeProfilerChan);
diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs
index 4820a3bbfd7..3ebf8f130d9 100644
--- a/components/script/dom/canvasrenderingcontext2d.rs
+++ b/components/script/dom/canvasrenderingcontext2d.rs
@@ -3,11 +3,14 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::canvas_state::CanvasState;
+use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasDirection;
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasFillRule;
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasImageSource;
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineCap;
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineJoin;
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods;
+use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasTextAlign;
+use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasTextBaseline;
use crate::dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern;
use crate::dom::bindings::error::{ErrorResult, Fallible};
use crate::dom::bindings::num::Finite;
@@ -288,7 +291,8 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
// https://html.spec.whatwg.org/multipage/#dom-context-2d-filltext
fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option<f64>) {
- self.canvas_state.fill_text(text, x, y, max_width);
+ self.canvas_state
+ .fill_text(self.canvas.as_ref().map(|c| &**c), text, x, y, max_width);
self.mark_as_dirty();
}
@@ -297,6 +301,47 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
self.canvas_state.measure_text(&self.global(), text)
}
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-font
+ fn Font(&self) -> DOMString {
+ self.canvas_state.font()
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-font
+ fn SetFont(&self, value: DOMString) {
+ self.canvas_state
+ .set_font(self.canvas.as_ref().map(|c| &**c), value)
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-textalign
+ fn TextAlign(&self) -> CanvasTextAlign {
+ self.canvas_state.text_align()
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-textalign
+ fn SetTextAlign(&self, value: CanvasTextAlign) {
+ self.canvas_state.set_text_align(value)
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-textbaseline
+ fn TextBaseline(&self) -> CanvasTextBaseline {
+ self.canvas_state.text_baseline()
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-textbaseline
+ fn SetTextBaseline(&self, value: CanvasTextBaseline) {
+ self.canvas_state.set_text_baseline(value)
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-direction
+ fn Direction(&self) -> CanvasDirection {
+ self.canvas_state.direction()
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-direction
+ fn SetDirection(&self, value: CanvasDirection) {
+ self.canvas_state.set_direction(value)
+ }
+
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
fn DrawImage(&self, image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult {
self.canvas_state
diff --git a/components/script/dom/offscreencanvasrenderingcontext2d.rs b/components/script/dom/offscreencanvasrenderingcontext2d.rs
index a3a873250f1..8c3deb001f4 100644
--- a/components/script/dom/offscreencanvasrenderingcontext2d.rs
+++ b/components/script/dom/offscreencanvasrenderingcontext2d.rs
@@ -3,10 +3,13 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::canvas_state::CanvasState;
+use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasDirection;
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasFillRule;
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasImageSource;
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineCap;
use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasLineJoin;
+use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasTextAlign;
+use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasTextBaseline;
use crate::dom::bindings::codegen::Bindings::OffscreenCanvasRenderingContext2DBinding::OffscreenCanvasRenderingContext2DMethods;
use crate::dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern;
use crate::dom::bindings::error::ErrorResult;
@@ -60,11 +63,6 @@ impl OffscreenCanvasRenderingContext2D {
));
reflect_dom_object(boxed, global)
}
- /*
- pub fn get_canvas_state(&self) -> Ref<CanvasState> {
- self.canvas_state.borrow()
- }
- */
pub fn set_canvas_bitmap_dimensions(&self, size: Size2D<u64>) {
self.canvas_state.set_bitmap_dimensions(size);
@@ -249,7 +247,13 @@ impl OffscreenCanvasRenderingContext2DMethods for OffscreenCanvasRenderingContex
// https://html.spec.whatwg.org/multipage/#dom-context-2d-filltext
fn FillText(&self, text: DOMString, x: f64, y: f64, max_width: Option<f64>) {
- self.canvas_state.fill_text(text, x, y, max_width)
+ self.canvas_state.fill_text(
+ self.htmlcanvas.as_ref().map(|c| &**c),
+ text,
+ x,
+ y,
+ max_width,
+ )
}
// https://html.spec.whatwg.org/multipage/#textmetrics
@@ -257,6 +261,47 @@ impl OffscreenCanvasRenderingContext2DMethods for OffscreenCanvasRenderingContex
self.canvas_state.measure_text(&self.global(), text)
}
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-font
+ fn Font(&self) -> DOMString {
+ self.canvas_state.font()
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-font
+ fn SetFont(&self, value: DOMString) {
+ self.canvas_state
+ .set_font(self.htmlcanvas.as_ref().map(|c| &**c), value)
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-textalign
+ fn TextAlign(&self) -> CanvasTextAlign {
+ self.canvas_state.text_align()
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-textalign
+ fn SetTextAlign(&self, value: CanvasTextAlign) {
+ self.canvas_state.set_text_align(value)
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-textbaseline
+ fn TextBaseline(&self) -> CanvasTextBaseline {
+ self.canvas_state.text_baseline()
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-textbaseline
+ fn SetTextBaseline(&self, value: CanvasTextBaseline) {
+ self.canvas_state.set_text_baseline(value)
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-direction
+ fn Direction(&self) -> CanvasDirection {
+ self.canvas_state.direction()
+ }
+
+ // https://html.spec.whatwg.org/multipage/#dom-context-2d-direction
+ fn SetDirection(&self, value: CanvasDirection) {
+ self.canvas_state.set_direction(value)
+ }
+
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth
fn LineWidth(&self) -> f64 {
self.canvas_state.line_width()
diff --git a/components/script/dom/webidls/CanvasRenderingContext2D.webidl b/components/script/dom/webidls/CanvasRenderingContext2D.webidl
index af88cfe9281..62669f4c2ba 100644
--- a/components/script/dom/webidls/CanvasRenderingContext2D.webidl
+++ b/components/script/dom/webidls/CanvasRenderingContext2D.webidl
@@ -211,11 +211,11 @@ interface mixin CanvasPathDrawingStyles {
[Exposed=(PaintWorklet, Window, Worker)]
interface mixin CanvasTextDrawingStyles {
// text
- //attribute DOMString font; // (default 10px sans-serif)
- //attribute CanvasTextAlign textAlign; // "start", "end", "left", "right", "center" (default: "start")
- //attribute CanvasTextBaseline textBaseline; // "top", "hanging", "middle", "alphabetic",
+ attribute DOMString font; // (default 10px sans-serif)
+ attribute CanvasTextAlign textAlign; // "start", "end", "left", "right", "center" (default: "start")
+ attribute CanvasTextBaseline textBaseline; // "top", "hanging", "middle", "alphabetic",
// "ideographic", "bottom" (default: "alphabetic")
- //attribute CanvasDirection direction; // "ltr", "rtl", "inherit" (default: "inherit")
+ attribute CanvasDirection direction; // "ltr", "rtl", "inherit" (default: "inherit")
};
[Exposed=(PaintWorklet, Window, Worker)]
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index c050579918e..d7fde4f27d5 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -118,6 +118,7 @@ use script_traits::{
};
use script_traits::{TimerSchedulerMsg, WebrenderIpcSender, WindowSizeData, WindowSizeType};
use selectors::attr::CaseSensitivity;
+use servo_arc::Arc as ServoArc;
use servo_geometry::{f32_rect_to_au_rect, MaxRect};
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
use std::borrow::Cow;
@@ -136,7 +137,8 @@ use style::dom::OpaqueNode;
use style::error_reporting::{ContextualParseError, ParseErrorReporter};
use style::media_queries;
use style::parser::ParserContext as CssParserContext;
-use style::properties::PropertyId;
+use style::properties::style_structs::Font;
+use style::properties::{PropertyId, ShorthandId};
use style::selector_parser::PseudoElement;
use style::str::HTML_SPACE_CHARACTERS;
use style::stylesheets::CssRuleType;
@@ -1847,6 +1849,18 @@ impl Window {
)
}
+ pub fn resolved_font_style_query(&self, node: &Node, value: String) -> Option<ServoArc<Font>> {
+ let id = PropertyId::Shorthand(ShorthandId::Font);
+ if !self.layout_reflow(QueryMsg::ResolvedFontStyleQuery(
+ node.to_trusted_node_address(),
+ id,
+ value,
+ )) {
+ return None;
+ }
+ self.layout_rpc.resolved_font_style()
+ }
+
pub fn layout(&self) -> &dyn LayoutRPC {
&*self.layout_rpc
}
@@ -2500,6 +2514,7 @@ fn debug_reflow_events(id: PipelineId, reflow_goal: &ReflowGoal, reason: &Reflow
&QueryMsg::NodeScrollGeometryQuery(_n) => "\tNodeScrollGeometryQuery",
&QueryMsg::NodeScrollIdQuery(_n) => "\tNodeScrollIdQuery",
&QueryMsg::ResolvedStyleQuery(_, _, _) => "\tResolvedStyleQuery",
+ &QueryMsg::ResolvedFontStyleQuery(..) => "\nResolvedFontStyleQuery",
&QueryMsg::OffsetParentQuery(_n) => "\tOffsetParentQuery",
&QueryMsg::StyleQuery => "\tStyleQuery",
&QueryMsg::TextIndexQuery(..) => "\tTextIndexQuery",
diff --git a/components/script_layout_interface/message.rs b/components/script_layout_interface/message.rs
index 8495d61fc8a..724cd2b79e7 100644
--- a/components/script_layout_interface/message.rs
+++ b/components/script_layout_interface/message.rs
@@ -117,6 +117,7 @@ pub enum QueryMsg {
ResolvedStyleQuery(TrustedNodeAddress, Option<PseudoElement>, PropertyId),
StyleQuery,
ElementInnerTextQuery(TrustedNodeAddress),
+ ResolvedFontStyleQuery(TrustedNodeAddress, PropertyId, String),
InnerWindowDimensionsQuery(BrowsingContextId),
}
@@ -145,6 +146,7 @@ impl ReflowGoal {
QueryMsg::NodeScrollGeometryQuery(_) |
QueryMsg::NodeScrollIdQuery(_) |
QueryMsg::ResolvedStyleQuery(..) |
+ QueryMsg::ResolvedFontStyleQuery(..) |
QueryMsg::OffsetParentQuery(_) |
QueryMsg::StyleQuery => false,
},
@@ -166,6 +168,7 @@ impl ReflowGoal {
QueryMsg::NodeScrollGeometryQuery(_) |
QueryMsg::NodeScrollIdQuery(_) |
QueryMsg::ResolvedStyleQuery(..) |
+ QueryMsg::ResolvedFontStyleQuery(..) |
QueryMsg::OffsetParentQuery(_) |
QueryMsg::InnerWindowDimensionsQuery(_) |
QueryMsg::StyleQuery => false,
diff --git a/components/script_layout_interface/rpc.rs b/components/script_layout_interface/rpc.rs
index 991437553cd..232fecabe6b 100644
--- a/components/script_layout_interface/rpc.rs
+++ b/components/script_layout_interface/rpc.rs
@@ -6,6 +6,8 @@ use app_units::Au;
use euclid::default::Rect;
use euclid::Size2D;
use script_traits::UntrustedNodeAddress;
+use servo_arc::Arc;
+use style::properties::style_structs::Font;
use style_traits::CSSPixel;
use webrender_api::ExternalScrollId;
@@ -30,6 +32,8 @@ pub trait LayoutRPC {
fn node_scroll_id(&self) -> NodeScrollIdResponse;
/// Query layout for the resolved value of a given CSS property
fn resolved_style(&self) -> ResolvedStyleResponse;
+ /// Query layout to get the resolved font style for canvas.
+ fn resolved_font_style(&self) -> Option<Arc<Font>>;
fn offset_parent(&self) -> OffsetParentResponse;
fn text_index(&self) -> TextIndexResponse;
/// Requests the list of nodes from the given point.
diff --git a/components/servo/lib.rs b/components/servo/lib.rs
index 390bd2c6ea0..83527952666 100644
--- a/components/servo/lib.rs
+++ b/components/servo/lib.rs
@@ -879,8 +879,13 @@ fn create_constellation(
Box::new(FontCacheWR(compositor_proxy.clone())),
);
+ let (canvas_chan, ipc_canvas_chan) = CanvasPaintThread::start(
+ Box::new(CanvasWebrenderApi(compositor_proxy.clone())),
+ font_cache_thread.clone(),
+ );
+
let initial_state = InitialConstellationState {
- compositor_proxy: compositor_proxy.clone(),
+ compositor_proxy,
embedder_proxy,
debugger_chan,
devtools_chan,
@@ -899,9 +904,6 @@ fn create_constellation(
user_agent,
};
- let (canvas_chan, ipc_canvas_chan) =
- CanvasPaintThread::start(Box::new(CanvasWebrenderApi(compositor_proxy)));
-
let constellation_chan = Constellation::<
script_layout_interface::message::Msg,
layout_thread::LayoutThread,
diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml
index bf66228c8fb..956a2c3f3d7 100644
--- a/components/style/Cargo.toml
+++ b/components/style/Cargo.toml
@@ -39,6 +39,7 @@ derive_more = "0.99"
encoding_rs = { version = "0.8", optional = true }
euclid = "0.20"
fallible = { path = "../fallible" }
+font-kit = "0.7"
fxhash = "0.2"
hashglobe = { path = "../hashglobe" }
html5ever = { version = "0.25", optional = true }
diff --git a/components/style/lib.rs b/components/style/lib.rs
index 52b77a7507e..7ff69ed3c7b 100644
--- a/components/style/lib.rs
+++ b/components/style/lib.rs
@@ -40,6 +40,8 @@ extern crate debug_unreachable;
extern crate derive_more;
extern crate euclid;
extern crate fallible;
+#[cfg(feature = "servo")]
+extern crate font_kit;
extern crate fxhash;
#[cfg(feature = "gecko")]
#[macro_use]
diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs
index 619b5b2fc54..b9cd617027b 100644
--- a/components/style/properties/properties.mako.rs
+++ b/components/style/properties/properties.mako.rs
@@ -2602,6 +2602,7 @@ pub mod style_structs {
% for style_struct in data.active_style_structs():
% if style_struct.name == "Font":
#[derive(Clone, Debug, MallocSizeOf)]
+ #[cfg_attr(feature = "servo", derive(Serialize, Deserialize))]
% else:
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
% endif
diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs
index ed00f42d678..25a93d68348 100644
--- a/components/style/values/computed/font.rs
+++ b/components/style/values/computed/font.rs
@@ -22,6 +22,12 @@ use crate::values::specified::length::{FontBaseSize, NoCalcLength};
use crate::values::CSSFloat;
use crate::Atom;
use cssparser::{serialize_identifier, CssStringWriter, Parser};
+#[cfg(feature = "servo")]
+use font_kit::family_name::FamilyName as FontKitFamilyName;
+#[cfg(feature = "servo")]
+use font_kit::properties::{
+ Stretch as FontKitFontStretch, Style as FontKitFontStyle, Weight as FontKitFontWeight,
+};
#[cfg(feature = "gecko")]
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use std::fmt::{self, Write};
@@ -69,6 +75,13 @@ impl ToAnimatedValue for FontWeight {
}
}
+#[cfg(feature = "servo")]
+impl From<FontWeight> for FontKitFontWeight {
+ fn from(font_weight: FontWeight) -> Self {
+ FontKitFontWeight(font_weight.0)
+ }
+}
+
#[derive(
Animate,
Clone,
@@ -81,6 +94,7 @@ impl ToAnimatedValue for FontWeight {
ToCss,
ToResolvedValue,
)]
+#[cfg_attr(feature = "servo", derive(Serialize, Deserialize))]
/// The computed value of font-size
pub struct FontSize {
/// The size.
@@ -179,7 +193,7 @@ impl ToAnimatedValue for FontSize {
}
#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToResolvedValue)]
-#[cfg_attr(feature = "servo", derive(Hash, MallocSizeOf))]
+#[cfg_attr(feature = "servo", derive(Hash, MallocSizeOf, Serialize, Deserialize))]
/// Specifies a prioritized list of font family names or generic family names.
pub struct FontFamily {
/// The actual list of family names.
@@ -444,9 +458,29 @@ impl SingleFontFamily {
}
#[cfg(feature = "servo")]
+impl From<&SingleFontFamily> for FontKitFamilyName {
+ fn from(font_family: &SingleFontFamily) -> Self {
+ match font_family {
+ SingleFontFamily::FamilyName(family_name) => {
+ FontKitFamilyName::Title(family_name.to_css_string())
+ },
+ SingleFontFamily::Generic(GenericFontFamily::Serif) => FontKitFamilyName::Serif,
+ SingleFontFamily::Generic(GenericFontFamily::SansSerif) => FontKitFamilyName::SansSerif,
+ SingleFontFamily::Generic(GenericFontFamily::Monospace) => FontKitFamilyName::Monospace,
+ SingleFontFamily::Generic(GenericFontFamily::Fantasy) => FontKitFamilyName::Fantasy,
+ SingleFontFamily::Generic(GenericFontFamily::Cursive) => FontKitFamilyName::Cursive,
+ SingleFontFamily::Generic(family_name) => {
+ warn!("unsupported font family name: {:?}", family_name);
+ FontKitFamilyName::SansSerif
+ },
+ }
+ }
+}
+
#[derive(
Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem,
)]
+#[cfg_attr(feature = "servo", derive(Serialize, Deserialize))]
/// A list of SingleFontFamily
pub struct FontFamilyList(Box<[SingleFontFamily]>);
@@ -931,6 +965,17 @@ impl ToCss for FontStyle {
}
}
+#[cfg(feature = "servo")]
+impl From<FontStyle> for FontKitFontStyle {
+ fn from(font_style: FontStyle) -> Self {
+ match font_style {
+ FontStyle::Normal => FontKitFontStyle::Normal,
+ FontStyle::Italic => FontKitFontStyle::Italic,
+ FontStyle::Oblique(_) => FontKitFontStyle::Oblique,
+ }
+ }
+}
+
/// A value for the font-stretch property per:
///
/// https://drafts.csswg.org/css-fonts-4/#propdef-font-stretch
@@ -953,6 +998,13 @@ impl FontStretch {
}
}
+#[cfg(feature = "servo")]
+impl From<FontStretch> for FontKitFontStretch {
+ fn from(stretch: FontStretch) -> Self {
+ FontKitFontStretch(stretch.value())
+ }
+}
+
impl ToAnimatedValue for FontStretch {
type AnimatedValue = Percentage;
diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs
index dd9f9d3b86d..1a77a3864ef 100644
--- a/components/style/values/specified/font.rs
+++ b/components/style/values/specified/font.rs
@@ -497,6 +497,7 @@ impl ToComputedValue for FontStretch {
ToResolvedValue,
ToShmem,
)]
+#[cfg_attr(feature = "servo", derive(Serialize, Deserialize))]
#[allow(missing_docs)]
pub enum KeywordSize {
#[css(keyword = "xx-small")]
@@ -541,6 +542,7 @@ impl Default for KeywordSize {
ToResolvedValue,
ToShmem,
)]
+#[cfg_attr(feature = "servo", derive(Serialize, Deserialize))]
/// Additional information for keyword-derived font sizes.
pub struct KeywordInfo {
/// The keyword used
diff --git a/tests/wpt/metadata/html/canvas/element/manual/text-styles/canvas_text_font_001.htm.ini b/tests/wpt/metadata/html/canvas/element/manual/text-styles/canvas_text_font_001.htm.ini
new file mode 100644
index 00000000000..7b5158316c0
--- /dev/null
+++ b/tests/wpt/metadata/html/canvas/element/manual/text-styles/canvas_text_font_001.htm.ini
@@ -0,0 +1,2 @@
+[canvas_text_font_001.htm]
+ expected: FAIL
diff --git a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.align.default.html.ini b/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.align.default.html.ini
deleted file mode 100644
index 2b8793d28be..00000000000
--- a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.align.default.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.align.default.html]
- [Canvas test: 2d.text.align.default]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.align.invalid.html.ini b/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.align.invalid.html.ini
deleted file mode 100644
index 100c6551344..00000000000
--- a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.align.invalid.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.align.invalid.html]
- [Canvas test: 2d.text.align.invalid]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.baseline.default.html.ini b/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.baseline.default.html.ini
deleted file mode 100644
index f09249c129c..00000000000
--- a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.baseline.default.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.baseline.default.html]
- [Canvas test: 2d.text.baseline.default]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.baseline.invalid.html.ini b/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.baseline.invalid.html.ini
deleted file mode 100644
index 23f93163a60..00000000000
--- a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.baseline.invalid.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.baseline.invalid.html]
- [Canvas test: 2d.text.baseline.invalid]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.default.html.ini b/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.default.html.ini
deleted file mode 100644
index 71a00e76d9d..00000000000
--- a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.default.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.font.default.html]
- [Canvas test: 2d.text.font.default]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.parse.basic.html.ini b/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.parse.basic.html.ini
deleted file mode 100644
index cbfa7e019c8..00000000000
--- a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.parse.basic.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.font.parse.basic.html]
- [Canvas test: 2d.text.font.parse.basic]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.parse.size.percentage.default.html.ini b/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.parse.size.percentage.default.html.ini
deleted file mode 100644
index e38e31fc416..00000000000
--- a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.parse.size.percentage.default.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.font.parse.size.percentage.default.html]
- [Canvas test: 2d.text.font.parse.size.percentage.default]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.parse.size.percentage.html.ini b/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.parse.size.percentage.html.ini
deleted file mode 100644
index f88a6906139..00000000000
--- a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.parse.size.percentage.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.font.parse.size.percentage.html]
- [Canvas test: 2d.text.font.parse.size.percentage]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.parse.system.html.ini b/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.parse.system.html.ini
deleted file mode 100644
index 4011e6441bf..00000000000
--- a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.parse.system.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.font.parse.system.html]
- [System fonts must be computed to explicit values]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.relative_size.html.ini b/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.relative_size.html.ini
deleted file mode 100644
index 5353ddbe2dc..00000000000
--- a/tests/wpt/metadata/html/canvas/element/text-styles/2d.text.font.relative_size.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.font.relative_size.html]
- [Canvas test: 2d.text.font.relative_size]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/element/the-canvas-state/2d.state.saverestore.font.html.ini b/tests/wpt/metadata/html/canvas/element/the-canvas-state/2d.state.saverestore.font.html.ini
deleted file mode 100644
index afb4feba894..00000000000
--- a/tests/wpt/metadata/html/canvas/element/the-canvas-state/2d.state.saverestore.font.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.state.saverestore.font.html]
- [save()/restore() works for font]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/element/the-canvas-state/2d.state.saverestore.textAlign.html.ini b/tests/wpt/metadata/html/canvas/element/the-canvas-state/2d.state.saverestore.textAlign.html.ini
deleted file mode 100644
index 0b2a17d1d9d..00000000000
--- a/tests/wpt/metadata/html/canvas/element/the-canvas-state/2d.state.saverestore.textAlign.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.state.saverestore.textAlign.html]
- [save()/restore() works for textAlign]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/element/the-canvas-state/2d.state.saverestore.textBaseline.html.ini b/tests/wpt/metadata/html/canvas/element/the-canvas-state/2d.state.saverestore.textBaseline.html.ini
deleted file mode 100644
index 4c754240145..00000000000
--- a/tests/wpt/metadata/html/canvas/element/the-canvas-state/2d.state.saverestore.textBaseline.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.state.saverestore.textBaseline.html]
- [save()/restore() works for textBaseline]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.align.default.html.ini b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.align.default.html.ini
deleted file mode 100644
index cfc8b5f9e74..00000000000
--- a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.align.default.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.align.default.html]
- [OffscreenCanvas test: 2d.text.align.default]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.align.default.worker.js.ini b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.align.default.worker.js.ini
deleted file mode 100644
index 38fffadbee9..00000000000
--- a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.align.default.worker.js.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.align.default.worker.html]
- [2d]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.align.invalid.html.ini b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.align.invalid.html.ini
deleted file mode 100644
index 1e8afd14191..00000000000
--- a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.align.invalid.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.align.invalid.html]
- [OffscreenCanvas test: 2d.text.align.invalid]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.align.invalid.worker.js.ini b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.align.invalid.worker.js.ini
deleted file mode 100644
index fd2751fa4fe..00000000000
--- a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.align.invalid.worker.js.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.align.invalid.worker.html]
- [2d]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.baseline.default.html.ini b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.baseline.default.html.ini
deleted file mode 100644
index 660b1093d74..00000000000
--- a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.baseline.default.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.baseline.default.html]
- [OffscreenCanvas test: 2d.text.baseline.default]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.baseline.default.worker.js.ini b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.baseline.default.worker.js.ini
deleted file mode 100644
index 15f63c7a2f4..00000000000
--- a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.baseline.default.worker.js.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.baseline.default.worker.html]
- [2d]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.baseline.invalid.html.ini b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.baseline.invalid.html.ini
deleted file mode 100644
index fc890c7ba66..00000000000
--- a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.baseline.invalid.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.baseline.invalid.html]
- [OffscreenCanvas test: 2d.text.baseline.invalid]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.baseline.invalid.worker.js.ini b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.baseline.invalid.worker.js.ini
deleted file mode 100644
index 15d3ef67d1e..00000000000
--- a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.baseline.invalid.worker.js.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.baseline.invalid.worker.html]
- [2d]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.default.html.ini b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.default.html.ini
deleted file mode 100644
index cbef4aaf060..00000000000
--- a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.default.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.font.default.html]
- [OffscreenCanvas test: 2d.text.font.default]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.default.worker.js.ini b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.default.worker.js.ini
deleted file mode 100644
index 181525db750..00000000000
--- a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.default.worker.js.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.font.default.worker.html]
- [2d]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.parse.system.html.ini b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.parse.system.html.ini
deleted file mode 100644
index 4011e6441bf..00000000000
--- a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.parse.system.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.font.parse.system.html]
- [System fonts must be computed to explicit values]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.parse.system.worker.js.ini b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.parse.system.worker.js.ini
deleted file mode 100644
index 38ba0ec527b..00000000000
--- a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.parse.system.worker.js.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.font.parse.system.worker.html]
- [System fonts must be computed to explicit values]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.parse.tiny.html.ini b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.parse.tiny.html.ini
new file mode 100644
index 00000000000..f69fc85b936
--- /dev/null
+++ b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.parse.tiny.html.ini
@@ -0,0 +1,4 @@
+[2d.text.font.parse.tiny.html]
+ [OffscreenCanvas test: 2d.text.font.parse.tiny]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.parse.tiny.worker.js.ini b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.parse.tiny.worker.js.ini
new file mode 100644
index 00000000000..c2449239def
--- /dev/null
+++ b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.parse.tiny.worker.js.ini
@@ -0,0 +1,4 @@
+[2d.text.font.parse.tiny.worker.html]
+ [2d]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.relative_size.html.ini b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.relative_size.html.ini
deleted file mode 100644
index 3b0a22523af..00000000000
--- a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.relative_size.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.font.relative_size.html]
- [OffscreenCanvas test: 2d.text.font.relative_size]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.relative_size.worker.js.ini b/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.relative_size.worker.js.ini
deleted file mode 100644
index d8ba1ee8817..00000000000
--- a/tests/wpt/metadata/html/canvas/offscreen/text/2d.text.font.relative_size.worker.js.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.text.font.relative_size.worker.html]
- [2d]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/dom/idlharness.https.html.ini b/tests/wpt/metadata/html/dom/idlharness.https.html.ini
index b0b337f71d8..bbc23fe7631 100644
--- a/tests/wpt/metadata/html/dom/idlharness.https.html.ini
+++ b/tests/wpt/metadata/html/dom/idlharness.https.html.ini
@@ -110,9 +110,6 @@
[History interface: window.history must inherit property "scrollRestoration" with the proper type]
expected: FAIL
- [CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "direction" with the proper type]
- expected: FAIL
-
[ApplicationCache interface: constant UPDATEREADY on interface prototype object]
expected: FAIL
@@ -152,9 +149,6 @@
[Navigator interface: attribute hardwareConcurrency]
expected: FAIL
- [CanvasRenderingContext2D interface: attribute textAlign]
- expected: FAIL
-
[OffscreenCanvasRenderingContext2D interface: operation restore()]
expected: FAIL
@@ -341,9 +335,6 @@
[DataTransfer interface: existence and properties of interface prototype object]
expected: FAIL
- [CanvasRenderingContext2D interface: attribute direction]
- expected: FAIL
-
[DataTransferItemList interface: existence and properties of interface object]
expected: FAIL
@@ -419,9 +410,6 @@
[SVGElement interface: attribute onsecuritypolicyviolation]
expected: FAIL
- [CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "font" with the proper type]
- expected: FAIL
-
[OffscreenCanvasRenderingContext2D interface: operation quadraticCurveTo(unrestricted double, unrestricted double, unrestricted double, unrestricted double)]
expected: FAIL
@@ -899,9 +887,6 @@
[ApplicationCache interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
- [CanvasRenderingContext2D interface: attribute font]
- expected: FAIL
-
[OffscreenCanvas interface: existence and properties of interface prototype object's @@unscopables property]
expected: FAIL
@@ -1076,9 +1061,6 @@
[OffscreenCanvasRenderingContext2D interface: operation closePath()]
expected: FAIL
- [CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "textAlign" with the proper type]
- expected: FAIL
-
[Path2D interface: operation arcTo(unrestricted double, unrestricted double, unrestricted double, unrestricted double, unrestricted double)]
expected: FAIL
@@ -1136,9 +1118,6 @@
[SVGElement interface: attribute onvolumechange]
expected: FAIL
- [CanvasRenderingContext2D interface: attribute textBaseline]
- expected: FAIL
-
[ImageBitmapRenderingContext interface object length]
expected: FAIL
@@ -1259,9 +1238,6 @@
[ElementInternals interface: attribute validity]
expected: FAIL
- [CanvasRenderingContext2D interface: document.createElement("canvas").getContext("2d") must inherit property "textBaseline" with the proper type]
- expected: FAIL
-
[SVGElement interface: attribute autofocus]
expected: FAIL
diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/initial.reset.2dstate.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/initial.reset.2dstate.html.ini
deleted file mode 100644
index 2f98ac94dff..00000000000
--- a/tests/wpt/metadata/html/semantics/embedded-content/the-canvas-element/initial.reset.2dstate.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[initial.reset.2dstate.html]
- type: testharness
- [Resetting the canvas state resets 2D state variables]
- expected: FAIL
-