mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Query layout to resolve canvas font property value
This commit is contained in:
parent
f161ab8e57
commit
7883718c12
11 changed files with 161 additions and 9 deletions
|
@ -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,
|
||||
) {
|
||||
|
|
|
@ -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>(
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
|
|
|
@ -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 => {},
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue