Use typed transforms in stacking contexts

This commit is contained in:
Pyfisch 2018-02-10 21:29:46 +01:00
parent 615e38f186
commit 279cda65ed
6 changed files with 51 additions and 53 deletions

View file

@ -14,7 +14,7 @@
//! They are therefore not exactly analogous to constructs like Skia pictures, which consist of //! They are therefore not exactly analogous to constructs like Skia pictures, which consist of
//! low-level drawing primitives. //! low-level drawing primitives.
use euclid::{Transform3D, Vector2D, TypedRect, SideOffsets2D}; use euclid::{Vector2D, TypedRect, SideOffsets2D};
use euclid::num::{One, Zero}; use euclid::num::{One, Zero};
use gfx_traits::{self, StackingContextId}; use gfx_traits::{self, StackingContextId};
use gfx_traits::print_tree::PrintTree; use gfx_traits::print_tree::PrintTree;
@ -33,8 +33,8 @@ use text::glyph::ByteIndex;
use webrender_api::{BorderRadius, BorderWidths, BoxShadowClipMode, ClipMode, ColorF}; use webrender_api::{BorderRadius, BorderWidths, BoxShadowClipMode, ClipMode, ColorF};
use webrender_api::{ComplexClipRegion, ExtendMode, ExternalScrollId, FilterOp, FontInstanceKey}; use webrender_api::{ComplexClipRegion, ExtendMode, ExternalScrollId, FilterOp, FontInstanceKey};
use webrender_api::{GlyphInstance, GradientStop, ImageBorder, ImageKey, ImageRendering}; use webrender_api::{GlyphInstance, GradientStop, ImageBorder, ImageKey, ImageRendering};
use webrender_api::{LayoutPoint, LayoutRect, LayoutSize, LayoutVector2D, LineStyle, LocalClip}; use webrender_api::{LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D, LineStyle};
use webrender_api::{MixBlendMode, NormalBorder, ScrollPolicy, ScrollSensitivity}; use webrender_api::{LocalClip, MixBlendMode, NormalBorder, ScrollPolicy, ScrollSensitivity};
use webrender_api::{StickyOffsetBounds, TransformStyle}; use webrender_api::{StickyOffsetBounds, TransformStyle};
pub use style::dom::OpaqueNode; pub use style::dom::OpaqueNode;
@ -209,13 +209,13 @@ pub struct StackingContext {
pub mix_blend_mode: MixBlendMode, pub mix_blend_mode: MixBlendMode,
/// A transform to be applied to this stacking context. /// A transform to be applied to this stacking context.
pub transform: Option<Transform3D<f32>>, pub transform: Option<LayoutTransform>,
/// The transform style of this stacking context. /// The transform style of this stacking context.
pub transform_style: TransformStyle, pub transform_style: TransformStyle,
/// The perspective matrix to be applied to children. /// The perspective matrix to be applied to children.
pub perspective: Option<Transform3D<f32>>, pub perspective: Option<LayoutTransform>,
/// The scroll policy of this layer. /// The scroll policy of this layer.
pub scroll_policy: ScrollPolicy, pub scroll_policy: ScrollPolicy,
@ -234,9 +234,9 @@ impl StackingContext {
z_index: i32, z_index: i32,
filters: Vec<FilterOp>, filters: Vec<FilterOp>,
mix_blend_mode: MixBlendMode, mix_blend_mode: MixBlendMode,
transform: Option<Transform3D<f32>>, transform: Option<LayoutTransform>,
transform_style: TransformStyle, transform_style: TransformStyle,
perspective: Option<Transform3D<f32>>, perspective: Option<LayoutTransform>,
scroll_policy: ScrollPolicy, scroll_policy: ScrollPolicy,
parent_clipping_and_scrolling: ClippingAndScrolling) parent_clipping_and_scrolling: ClippingAndScrolling)
-> StackingContext { -> StackingContext {
@ -1028,7 +1028,7 @@ pub trait SimpleMatrixDetection {
fn is_identity_or_simple_translation(&self) -> bool; fn is_identity_or_simple_translation(&self) -> bool;
} }
impl SimpleMatrixDetection for Transform3D<f32> { impl SimpleMatrixDetection for LayoutTransform {
#[inline] #[inline]
fn is_identity_or_simple_translation(&self) -> bool { fn is_identity_or_simple_translation(&self) -> bool {
let (_0, _1) = (Zero::zero(), One::one()); let (_0, _1) = (Zero::zero(), One::one());

View file

@ -17,7 +17,7 @@ use context::LayoutContext;
use display_list::ToLayout; use display_list::ToLayout;
use display_list::background::{compute_background_image_size, tile_image_axis}; use display_list::background::{compute_background_image_size, tile_image_axis};
use display_list::background::{convert_linear_gradient, convert_radial_gradient}; use display_list::background::{convert_linear_gradient, convert_radial_gradient};
use euclid::{Point2D, Rect, SideOffsets2D, Size2D, Transform3D, TypedSize2D, Vector2D, rect}; use euclid::{rect, Point2D, Rect, SideOffsets2D, Size2D, TypedSize2D, Vector2D};
use flex::FlexFlow; use flex::FlexFlow;
use flow::{BaseFlow, Flow, FlowFlags}; use flow::{BaseFlow, Flow, FlowFlags};
use flow_ref::FlowRef; use flow_ref::FlowRef;
@ -76,9 +76,9 @@ use style_traits::cursor::CursorKind;
use table_cell::CollapsedBordersForCell; use table_cell::CollapsedBordersForCell;
use webrender_api::{self, BorderRadius, BorderSide, BoxShadowClipMode, ClipMode, ColorF}; use webrender_api::{self, BorderRadius, BorderSide, BoxShadowClipMode, ClipMode, ColorF};
use webrender_api::{ComplexClipRegion, ExternalScrollId, FilterOp, GlyphInstance, ImageBorder}; use webrender_api::{ComplexClipRegion, ExternalScrollId, FilterOp, GlyphInstance, ImageBorder};
use webrender_api::{ImageRendering, LayoutRect, LayoutSize, LayoutVector2D, LineStyle, LocalClip}; use webrender_api::{ImageRendering, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D};
use webrender_api::{NinePatchDescriptor, NormalBorder, ScrollPolicy, ScrollSensitivity}; use webrender_api::{LineStyle, LocalClip, NinePatchDescriptor, NormalBorder, ScrollPolicy};
use webrender_api::StickyOffsetBounds; use webrender_api::{ScrollSensitivity, StickyOffsetBounds};
trait ResolvePercentage { trait ResolvePercentage {
fn resolve(&self, length: u32) -> u32; fn resolve(&self, length: u32) -> u32;
@ -2464,7 +2464,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
let perspective = self.fragment let perspective = self.fragment
.perspective_matrix(&border_box) .perspective_matrix(&border_box)
.unwrap_or_else(Transform3D::identity); .unwrap_or(LayoutTransform::identity());
let transform = transform.pre_mul(&perspective).inverse(); let transform = transform.pre_mul(&perspective).inverse();
let origin = &border_box.origin; let origin = &border_box.origin;
@ -2766,10 +2766,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
let content_size = self.base.overflow.scroll.origin + self.base.overflow.scroll.size; let content_size = self.base.overflow.scroll.origin + self.base.overflow.scroll.size;
let content_size = Size2D::new(content_size.x, content_size.y); let content_size = Size2D::new(content_size.x, content_size.y);
let external_id = ExternalScrollId( let external_id =
self.fragment.unique_id(), ExternalScrollId(self.fragment.unique_id(), state.pipeline_id.to_webrender());
state.pipeline_id.to_webrender()
);
let new_clip_scroll_index = state.add_clip_scroll_node(ClipScrollNode { let new_clip_scroll_index = state.add_clip_scroll_node(ClipScrollNode {
parent_index: self.clipping_and_scrolling().scrolling, parent_index: self.clipping_and_scrolling().scrolling,
clip: clip, clip: clip,

View file

@ -11,8 +11,7 @@ use gfx::display_list::{BorderDetails, ClipScrollNode};
use gfx::display_list::{ClipScrollNodeIndex, ClipScrollNodeType, DisplayItem}; use gfx::display_list::{ClipScrollNodeIndex, ClipScrollNodeType, DisplayItem};
use gfx::display_list::{DisplayList, StackingContextType}; use gfx::display_list::{DisplayList, StackingContextType};
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use webrender_api::{self, ClipAndScrollInfo, ClipId}; use webrender_api::{self, ClipAndScrollInfo, ClipId, DisplayListBuilder};
use webrender_api::{DisplayListBuilder, LayoutTransform};
pub trait WebRenderDisplayListConverter { pub trait WebRenderDisplayListConverter {
fn convert_to_webrender(&self, pipeline_id: PipelineId) -> DisplayListBuilder; fn convert_to_webrender(&self, pipeline_id: PipelineId) -> DisplayListBuilder;
@ -224,19 +223,12 @@ impl WebRenderDisplayItemConverter for DisplayItem {
let stacking_context = &item.stacking_context; let stacking_context = &item.stacking_context;
debug_assert_eq!(stacking_context.context_type, StackingContextType::Real); debug_assert_eq!(stacking_context.context_type, StackingContextType::Real);
let transform = stacking_context
.transform
.map(|transform| LayoutTransform::from_untyped(&transform).into());
let perspective = stacking_context
.perspective
.map(|perspective| LayoutTransform::from_untyped(&perspective));
builder.push_stacking_context( builder.push_stacking_context(
&webrender_api::LayoutPrimitiveInfo::new(stacking_context.bounds), &webrender_api::LayoutPrimitiveInfo::new(stacking_context.bounds),
stacking_context.scroll_policy, stacking_context.scroll_policy,
transform, stacking_context.transform.map(Into::into),
stacking_context.transform_style, stacking_context.transform_style,
perspective, stacking_context.perspective,
stacking_context.mix_blend_mode, stacking_context.mix_blend_mode,
stacking_context.filters.clone(), stacking_context.filters.clone(),
); );

View file

@ -29,7 +29,7 @@ use app_units::Au;
use block::{BlockFlow, FormattingContextType}; use block::{BlockFlow, FormattingContextType};
use context::LayoutContext; use context::LayoutContext;
use display_list::{DisplayListBuildState, StackingContextCollectionState}; use display_list::{DisplayListBuildState, StackingContextCollectionState};
use euclid::{Transform3D, Point2D, Vector2D, Rect, Size2D}; use euclid::{Point2D, Vector2D, Rect, Size2D};
use flex::FlexFlow; use flex::FlexFlow;
use floats::{Floats, SpeculatedFloatPlacement}; use floats::{Floats, SpeculatedFloatPlacement};
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator}; use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
@ -67,6 +67,7 @@ use table_colgroup::TableColGroupFlow;
use table_row::TableRowFlow; use table_row::TableRowFlow;
use table_rowgroup::TableRowGroupFlow; use table_rowgroup::TableRowGroupFlow;
use table_wrapper::TableWrapperFlow; use table_wrapper::TableWrapperFlow;
use webrender_api::LayoutTransform;
/// This marker trait indicates that a type is a struct with `#[repr(C)]` whose first field /// This marker trait indicates that a type is a struct with `#[repr(C)]` whose first field
/// is of type `BaseFlow` or some type that also implements this trait. /// is of type `BaseFlow` or some type that also implements this trait.
@ -335,8 +336,8 @@ pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static {
let transform_2d = self.as_block() let transform_2d = self.as_block()
.fragment .fragment
.transform_matrix(&position) .transform_matrix(&position)
.unwrap_or(Transform3D::identity()) .unwrap_or(LayoutTransform::identity())
.to_2d(); .to_2d().to_untyped();
let transformed_overflow = Overflow { let transformed_overflow = Overflow {
paint: f32_rect_to_au_rect(transform_2d.transform_rect( paint: f32_rect_to_au_rect(transform_2d.transform_rect(
&au_rect_to_f32_rect(overflow.paint))), &au_rect_to_f32_rect(overflow.paint))),

View file

@ -10,7 +10,8 @@ use ServoArc;
use app_units::Au; use app_units::Au;
use canvas_traits::canvas::CanvasMsg; use canvas_traits::canvas::CanvasMsg;
use context::{LayoutContext, with_thread_local_font_context}; use context::{LayoutContext, with_thread_local_font_context};
use euclid::{Transform3D, Point2D, Vector2D, Rect, Size2D}; use display_list::ToLayout;
use euclid::{Point2D, Vector2D, Rect, Size2D};
use floats::ClearType; use floats::ClearType;
use flow::{GetBaseFlow, ImmutableFlowUtils}; use flow::{GetBaseFlow, ImmutableFlowUtils};
use flow_ref::FlowRef; use flow_ref::FlowRef;
@ -65,7 +66,7 @@ use style::values::generics::box_::VerticalAlign;
use style::values::generics::transform; use style::values::generics::transform;
use text; use text;
use text::TextRunScanner; use text::TextRunScanner;
use webrender_api; use webrender_api::{self, LayoutTransform};
use wrapper::ThreadSafeLayoutNodeHelpers; use wrapper::ThreadSafeLayoutNodeHelpers;
// From gfxFontConstants.h in Firefox. // From gfxFontConstants.h in Firefox.
@ -2867,9 +2868,10 @@ impl Fragment {
} }
/// Returns the 4D matrix representing this fragment's transform. /// Returns the 4D matrix representing this fragment's transform.
pub fn transform_matrix(&self, stacking_relative_border_box: &Rect<Au>) -> Option<Transform3D<f32>> { pub fn transform_matrix(&self, stacking_relative_border_box: &Rect<Au>) -> Option<LayoutTransform> {
let list = &self.style.get_box().transform; let list = &self.style.get_box().transform;
let transform = list.to_transform_3d_matrix(Some(stacking_relative_border_box)).ok()?.0; let transform = LayoutTransform::from_untyped(
&list.to_transform_3d_matrix(Some(stacking_relative_border_box)).ok()?.0);
let transform_origin = &self.style.get_box().transform_origin; let transform_origin = &self.style.get_box().transform_origin;
let transform_origin_x = let transform_origin_x =
@ -2882,38 +2884,42 @@ impl Fragment {
.to_f32_px(); .to_f32_px();
let transform_origin_z = transform_origin.depth.px(); let transform_origin_z = transform_origin.depth.px();
let pre_transform = Transform3D::create_translation(transform_origin_x, let pre_transform = LayoutTransform::create_translation(
transform_origin_y, transform_origin_x,
transform_origin_z); transform_origin_y,
let post_transform = Transform3D::create_translation(-transform_origin_x, transform_origin_z);
-transform_origin_y, let post_transform = LayoutTransform::create_translation(
-transform_origin_z); -transform_origin_x,
-transform_origin_y,
-transform_origin_z);
Some(pre_transform.pre_mul(&transform).pre_mul(&post_transform)) Some(pre_transform.pre_mul(&transform).pre_mul(&post_transform))
} }
/// Returns the 4D matrix representing this fragment's perspective. /// Returns the 4D matrix representing this fragment's perspective.
pub fn perspective_matrix(&self, stacking_relative_border_box: &Rect<Au>) -> Option<Transform3D<f32>> { pub fn perspective_matrix(&self, stacking_relative_border_box: &Rect<Au>) -> Option<LayoutTransform> {
match self.style().get_box().perspective { match self.style().get_box().perspective {
Either::First(length) => { Either::First(length) => {
let perspective_origin = self.style().get_box().perspective_origin; let perspective_origin = self.style().get_box().perspective_origin;
let perspective_origin = let perspective_origin =
Point2D::new( Point2D::new(
perspective_origin.horizontal perspective_origin.horizontal
.to_used_value(stacking_relative_border_box.size.width) .to_used_value(stacking_relative_border_box.size.width),
.to_f32_px(),
perspective_origin.vertical perspective_origin.vertical
.to_used_value(stacking_relative_border_box.size.height) .to_used_value(stacking_relative_border_box.size.height)
.to_f32_px()); ).to_layout();
let pre_transform = Transform3D::create_translation(perspective_origin.x, let pre_transform = LayoutTransform::create_translation(
perspective_origin.y, perspective_origin.x,
0.0); perspective_origin.y,
let post_transform = Transform3D::create_translation(-perspective_origin.x, 0.0);
-perspective_origin.y, let post_transform = LayoutTransform::create_translation(
0.0); -perspective_origin.x,
-perspective_origin.y,
0.0);
let perspective_matrix = transform::create_perspective_matrix(length.px()); let perspective_matrix = LayoutTransform::from_untyped(
&transform::create_perspective_matrix(length.px()));
Some(pre_transform.pre_mul(&perspective_matrix).pre_mul(&post_transform)) Some(pre_transform.pre_mul(&perspective_matrix).pre_mul(&post_transform))
} }

View file

@ -17,6 +17,7 @@ use servo_config::opts;
use style::servo::restyle_damage::ServoRestyleDamage; use style::servo::restyle_damage::ServoRestyleDamage;
use traversal::{AssignBSizes, AssignISizes, BubbleISizes, BuildDisplayList}; use traversal::{AssignBSizes, AssignISizes, BubbleISizes, BuildDisplayList};
use traversal::{InorderFlowTraversal, PostorderFlowTraversal, PreorderFlowTraversal}; use traversal::{InorderFlowTraversal, PostorderFlowTraversal, PreorderFlowTraversal};
use webrender_api::LayoutPoint;
pub fn resolve_generated_content(root: &mut Flow, layout_context: &LayoutContext) { pub fn resolve_generated_content(root: &mut Flow, layout_context: &LayoutContext) {
ResolveGeneratedContent::new(&layout_context).traverse(root, 0); ResolveGeneratedContent::new(&layout_context).traverse(root, 0);
@ -98,7 +99,7 @@ pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut Flow, iterator
if let Some(matrix) = kid.as_block() if let Some(matrix) = kid.as_block()
.fragment .fragment
.transform_matrix(&relative_position) { .transform_matrix(&relative_position) {
let transform_matrix = matrix.transform_point2d(&Point2D::zero()); let transform_matrix = matrix.transform_point2d(&LayoutPoint::zero());
stacking_context_position = stacking_context_position + stacking_context_position = stacking_context_position +
Vector2D::new(Au::from_f32_px(transform_matrix.x), Vector2D::new(Au::from_f32_px(transform_matrix.x),
Au::from_f32_px(transform_matrix.y)) Au::from_f32_px(transform_matrix.y))