Query layout to resolve canvas font property value

This commit is contained in:
Utsav Oza 2020-05-28 00:28:42 +05:30
parent f161ab8e57
commit 7883718c12
11 changed files with 161 additions and 9 deletions

View file

@ -522,7 +522,7 @@ impl GenericDrawTarget for raqote::DrawTarget {
text: String,
x: f64,
y: f64,
max_width: Option<f64>,
_max_width: Option<f64>,
pattern: canvas_data::Pattern,
draw_options: &DrawOptions,
) {

View file

@ -29,6 +29,8 @@ 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};
@ -38,9 +40,13 @@ use style::computed_values::visibility::T as Visibility;
use style::context::{StyleContext, ThreadLocalStyleContext};
use style::dom::TElement;
use style::logical_geometry::{BlockFlowDirection, InlineBaseDirection, WritingMode};
use style::properties::{style_structs, LonghandId, PropertyDeclarationId, PropertyId};
use style::properties::{
parse_one_declaration_into, style_structs, 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 +79,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 parse_font_response: Option<ServoArc<ComputedValues>>,
/// A queued response for the offset parent/rect of a node.
pub offset_parent_response: OffsetParentResponse,
@ -170,6 +179,12 @@ impl LayoutRPC for LayoutRPCImpl {
ResolvedStyleResponse(rw_data.resolved_style_response.clone())
}
fn parsed_font(&self) -> Option<ServoArc<ComputedValues>> {
let &LayoutRPCImpl(ref rw_data) = self;
let rw_data = rw_data.lock().unwrap();
rw_data.parse_font_response.clone()
}
fn offset_parent(&self) -> OffsetParentResponse {
let &LayoutRPCImpl(ref rw_data) = self;
let rw_data = rw_data.lock().unwrap();
@ -735,6 +750,68 @@ pub fn process_node_scroll_area_request(
}
}
pub fn process_parse_font_request<'dom, E>(
context: &LayoutContext,
node: E,
font_value: &str,
property: &PropertyId,
url_data: ServoUrl,
shared_lock: &SharedRwLock,
) -> Option<ServoArc<ComputedValues>>
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 mut declarations = SourcePropertyDeclaration::new();
let result = parse_one_declaration_into(
&mut declarations,
property.clone(),
font_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,
};
// 2. Get resolved styles for the parent element
let element = node.as_element().unwrap();
let parent_style = 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()
};
// 3. Resolve the parsed value with resolved styles of the parent element
Some(
context
.style_context
.stylist
.compute_for_declarations::<E::ConcreteElement>(
&context.style_context.guards,
&*parent_style,
ServoArc::new(shared_lock.wrap(declarations)),
),
)
}
/// 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>(

View file

@ -49,12 +49,12 @@ 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_parse_font_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 +558,7 @@ impl LayoutThread {
scroll_id_response: None,
scroll_area_response: Rect::zero(),
resolved_style_response: String::new(),
parse_font_response: None,
offset_parent_response: OffsetParentResponse::empty(),
scroll_offsets: HashMap::new(),
text_index_response: TextIndexResponse(None),
@ -1231,6 +1232,9 @@ impl LayoutThread {
&QueryMsg::ElementInnerTextQuery(_) => {
rw_data.element_inner_text_response = String::new();
},
&QueryMsg::ParseFontQuery(..) => {
rw_data.parse_font_response = None;
},
&QueryMsg::InnerWindowDimensionsQuery(_) => {
rw_data.inner_window_dimensions_response = None;
},
@ -1498,6 +1502,7 @@ impl LayoutThread {
&mut *rw_data,
&mut layout_context,
data.result.borrow_mut().as_mut().unwrap(),
document_shared_lock,
);
}
@ -1507,6 +1512,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 +1555,18 @@ impl LayoutThread {
rw_data.resolved_style_response =
process_resolved_style_request(context, node, pseudo, property, root_flow);
},
&QueryMsg::ParseFontQuery(node, ref property, ref value) => {
let node = unsafe { ServoLayoutNode::new(&node) };
let url = self.url.clone();
rw_data.parse_font_response = process_parse_font_request(
context,
node,
value,
property,
url,
shared_lock,
);
},
&QueryMsg::OffsetParentQuery(node) => {
rw_data.offset_parent_response = process_offset_parent_query(node, root_flow);
},

View file

@ -1242,6 +1242,7 @@ impl LayoutThread {
// builder in order to support query iframe sizing.
rw_data.inner_window_dimensions_response = None;
},
&QueryMsg::ParseFontQuery(_, _) => unimplemented!(),
},
ReflowGoal::Full | ReflowGoal::TickAnimations => {},
}

View file

@ -1006,6 +1006,16 @@ impl CanvasState {
)
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-font
pub fn set_font(&self, _canvas: Option<&HTMLCanvasElement>, _value: DOMString) {
unimplemented!()
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-font
pub fn font(&self) -> DOMString {
unimplemented!()
}
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth
pub fn line_width(&self) -> f64 {
self.state.borrow().line_width

View file

@ -297,6 +297,17 @@ 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-drawimage
fn DrawImage(&self, image: CanvasImageSource, dx: f64, dy: f64) -> ErrorResult {
self.canvas_state

View file

@ -257,6 +257,17 @@ 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-linewidth
fn LineWidth(&self) -> f64 {
self.canvas_state.line_width()

View file

@ -211,7 +211,7 @@ interface mixin CanvasPathDrawingStyles {
[Exposed=(PaintWorklet, Window, Worker)]
interface mixin CanvasTextDrawingStyles {
// text
//attribute DOMString font; // (default 10px sans-serif)
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")

View file

@ -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,7 @@ 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::{ComputedValues, PropertyId, ShorthandId};
use style::selector_parser::PseudoElement;
use style::str::HTML_SPACE_CHARACTERS;
use style::stylesheets::CssRuleType;
@ -1847,6 +1848,21 @@ impl Window {
)
}
pub fn parse_font_query(&self, node: &Node, value: String) -> Option<ServoArc<ComputedValues>> {
if !node.is_connected() {
return None;
}
let id = PropertyId::Shorthand(ShorthandId::Font);
if !self.layout_reflow(QueryMsg::ParseFontQuery(
node.to_trusted_node_address(),
id,
value,
)) {
return None;
}
self.layout_rpc.parsed_font()
}
pub fn layout(&self) -> &dyn LayoutRPC {
&*self.layout_rpc
}
@ -2504,6 +2520,7 @@ fn debug_reflow_events(id: PipelineId, reflow_goal: &ReflowGoal, reason: &Reflow
&QueryMsg::StyleQuery => "\tStyleQuery",
&QueryMsg::TextIndexQuery(..) => "\tTextIndexQuery",
&QueryMsg::ElementInnerTextQuery(_) => "\tElementInnerTextQuery",
&QueryMsg::ParseFontQuery(..) => "\nParseFontQuery",
&QueryMsg::InnerWindowDimensionsQuery(_) => "\tInnerWindowDimensionsQuery",
},
};

View file

@ -117,6 +117,7 @@ pub enum QueryMsg {
ResolvedStyleQuery(TrustedNodeAddress, Option<PseudoElement>, PropertyId),
StyleQuery,
ElementInnerTextQuery(TrustedNodeAddress),
ParseFontQuery(TrustedNodeAddress, PropertyId, String),
InnerWindowDimensionsQuery(BrowsingContextId),
}
@ -145,6 +146,7 @@ impl ReflowGoal {
QueryMsg::NodeScrollGeometryQuery(_) |
QueryMsg::NodeScrollIdQuery(_) |
QueryMsg::ResolvedStyleQuery(..) |
QueryMsg::ParseFontQuery(..) |
QueryMsg::OffsetParentQuery(_) |
QueryMsg::StyleQuery => false,
},
@ -166,6 +168,7 @@ impl ReflowGoal {
QueryMsg::NodeScrollGeometryQuery(_) |
QueryMsg::NodeScrollIdQuery(_) |
QueryMsg::ResolvedStyleQuery(..) |
QueryMsg::ParseFontQuery(..) |
QueryMsg::OffsetParentQuery(_) |
QueryMsg::InnerWindowDimensionsQuery(_) |
QueryMsg::StyleQuery => false,

View file

@ -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::ComputedValues;
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 parsed font property for canvas.
fn parsed_font(&self) -> Option<Arc<ComputedValues>>;
fn offset_parent(&self) -> OffsetParentResponse;
fn text_index(&self) -> TextIndexResponse;
/// Requests the list of nodes from the given point.