diff options
author | Glenn Watson <gw@intuitionlibrary.com> | 2015-06-18 13:06:31 +1000 |
---|---|---|
committer | Glenn Watson <gw@intuitionlibrary.com> | 2015-06-23 14:10:44 +1000 |
commit | 39ddbbb0e1a20e7165740860b63cdf892951a5ec (patch) | |
tree | 26d78ca5b184929c5d3859f2e3f53e8e986e3101 | |
parent | d86c5879255ec9ced621412d4565a9a66ee4dc72 (diff) | |
download | servo-39ddbbb0e1a20e7165740860b63cdf892951a5ec.tar.gz servo-39ddbbb0e1a20e7165740860b63cdf892951a5ec.zip |
Implement enough of 3d transforms spec to run the CSS FPS demo.
-rw-r--r-- | components/compositing/compositor.rs | 49 | ||||
-rw-r--r-- | components/compositing/compositor_layer.rs | 5 | ||||
-rw-r--r-- | components/gfx/display_list/mod.rs | 74 | ||||
-rw-r--r-- | components/gfx/paint_context.rs | 3 | ||||
-rw-r--r-- | components/gfx/paint_task.rs | 117 | ||||
-rw-r--r-- | components/layout/block.rs | 51 | ||||
-rw-r--r-- | components/layout/display_list_builder.rs | 75 | ||||
-rw-r--r-- | components/layout/fragment.rs | 7 | ||||
-rw-r--r-- | components/layout/layout_task.rs | 8 | ||||
-rw-r--r-- | components/msg/compositor_msg.rs | 15 | ||||
-rw-r--r-- | components/script/dom/webidls/CSSStyleDeclaration.webidl | 4 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 44 | ||||
-rw-r--r-- | components/style/properties.mako.rs | 172 | ||||
-rw-r--r-- | components/style/values.rs | 69 | ||||
-rw-r--r-- | ports/cef/Cargo.lock | 42 | ||||
-rw-r--r-- | ports/gonk/Cargo.lock | 40 | ||||
-rw-r--r-- | tests/html/test_3d_transform_1.html | 131 | ||||
-rw-r--r-- | tests/html/test_3d_transform_2.html | 81 | ||||
-rw-r--r-- | tests/html/test_3d_transform_zsort.html | 52 |
19 files changed, 894 insertions, 145 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 8a4d1191b7f..0613d337bad 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -11,6 +11,7 @@ use scrolling::ScrollingTimerProxy; use windowing; use windowing::{MouseWindowEvent, WindowEvent, WindowMethods, WindowNavigateMsg}; +use euclid::Matrix4; use euclid::point::{Point2D, TypedPoint2D}; use euclid::rect::{Rect, TypedRect}; use euclid::scale_factor::ScaleFactor; @@ -26,7 +27,7 @@ use layers::rendergl::RenderContext; use layers::rendergl; use layers::scene::Scene; use layout_traits::{LayoutControlChan, LayoutControlMsg}; -use msg::compositor_msg::{Epoch, FrameTreeId, LayerId}; +use msg::compositor_msg::{Epoch, FrameTreeId, LayerId, LayerKind}; use msg::compositor_msg::{LayerProperties, ScrollPolicy}; use msg::constellation_msg::AnimationState; use msg::constellation_msg::Msg as ConstellationMsg; @@ -357,6 +358,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { self.create_or_update_descendant_layer(pipeline_id, *layer_properties); } } + self.send_buffer_requests_for_all_layers(); } (Msg::GetGraphicsMetadata(chan), ShutdownState::NotShuttingDown) => { @@ -560,9 +562,13 @@ impl<Window: WindowMethods> IOCompositor<Window> { -> Rc<Layer<CompositorData>> { let layer_properties = LayerProperties { id: LayerId::null(), + parent_id: None, rect: Rect::zero(), background_color: color::transparent(), scroll_policy: ScrollPolicy::Scrollable, + transform: Matrix4::identity(), + perspective: Matrix4::identity(), + establishes_3d_context: true, }; let root_layer = CompositorData::new_layer(pipeline.id, @@ -624,6 +630,8 @@ impl<Window: WindowMethods> IOCompositor<Window> { } fn create_or_update_base_layer(&mut self, pipeline_id: PipelineId, layer_properties: LayerProperties) { + debug_assert!(layer_properties.parent_id.is_none()); + let root_layer = match self.find_pipeline_root_layer(pipeline_id) { Some(root_layer) => root_layer, None => { @@ -653,29 +661,29 @@ impl<Window: WindowMethods> IOCompositor<Window> { self.scroll_layer_to_fragment_point_if_necessary(pipeline_id, layer_properties.id); - self.send_buffer_requests_for_all_layers(); } fn create_or_update_descendant_layer(&mut self, pipeline_id: PipelineId, layer_properties: LayerProperties) { + debug_assert!(layer_properties.parent_id.is_some()); + if !self.update_layer_if_exists(pipeline_id, layer_properties) { self.create_descendant_layer(pipeline_id, layer_properties); } self.scroll_layer_to_fragment_point_if_necessary(pipeline_id, layer_properties.id); - self.send_buffer_requests_for_all_layers(); } fn create_descendant_layer(&self, pipeline_id: PipelineId, layer_properties: LayerProperties) { - let root_layer = match self.find_pipeline_root_layer(pipeline_id) { - Some(root_layer) => root_layer, - None => return, // This pipeline is in the process of shutting down. - }; + let parent_id = layer_properties.parent_id.unwrap(); - let new_layer = CompositorData::new_layer(pipeline_id, - layer_properties, - WantsScrollEventsFlag::DoesntWantScrollEvents, - root_layer.tile_size); - root_layer.add_child(new_layer); + if let Some(parent_layer) = self.find_layer_with_pipeline_and_layer_id(pipeline_id, + parent_id) { + let new_layer = CompositorData::new_layer(pipeline_id, + layer_properties, + WantsScrollEventsFlag::DoesntWantScrollEvents, + parent_layer.tile_size); + parent_layer.add_child(new_layer); + } } fn send_window_size(&self) { @@ -1143,11 +1151,18 @@ impl<Window: WindowMethods> IOCompositor<Window> { request.page_rect = request.page_rect / scale.get(); } + let layer_kind = if layer.transform_state.borrow().is_3d { + LayerKind::Layer3D + } else { + LayerKind::Layer2D + }; + vec.push(PaintRequest { buffer_requests: layer_requests, scale: scale.get(), layer_id: layer.extra_data.borrow().id, epoch: layer.extra_data.borrow().requested_epoch, + layer_kind: layer_kind, }); } @@ -1188,6 +1203,12 @@ impl<Window: WindowMethods> IOCompositor<Window> { /// Returns true if any buffer requests were sent or false otherwise. fn send_buffer_requests_for_all_layers(&mut self) -> bool { + if let Some(ref root_layer) = self.scene.root { + root_layer.update_transform_state(&Matrix4::identity(), + &Matrix4::identity(), + &Point2D::zero()); + } + let mut layers_and_requests = Vec::new(); let mut unused_buffers = Vec::new(); self.scene.get_buffer_requests(&mut layers_and_requests, &mut unused_buffers); @@ -1417,7 +1438,9 @@ impl<Window: WindowMethods> IOCompositor<Window> { fn initialize_compositing(&mut self) { let context = CompositorTask::create_graphics_context(&self.window.native_metadata()); let show_debug_borders = opts::get().show_debug_borders; - self.context = Some(rendergl::RenderContext::new(context, show_debug_borders)) + self.context = Some(rendergl::RenderContext::new(context, + show_debug_borders, + opts::get().output_file.is_some())) } fn find_topmost_layer_at_point_for_layer(&self, diff --git a/components/compositing/compositor_layer.rs b/components/compositing/compositor_layer.rs index 6a34fc785ce..1be9df64ca9 100644 --- a/components/compositing/compositor_layer.rs +++ b/components/compositing/compositor_layer.rs @@ -7,7 +7,6 @@ use windowing::{MouseWindowEvent, WindowMethods}; use azure::azure_hl; use euclid::length::Length; -use euclid::matrix::Matrix4; use euclid::point::{Point2D, TypedPoint2D}; use euclid::size::TypedSize2D; use euclid::rect::Rect; @@ -66,6 +65,7 @@ impl CompositorData { tile_size, to_layers_color(&layer_properties.background_color), 1.0, + layer_properties.establishes_3d_context, new_compositor_data)) } } @@ -190,6 +190,8 @@ pub enum ScrollEventResult { impl CompositorLayer for Layer<CompositorData> { fn update_layer_except_bounds(&self, layer_properties: LayerProperties) { self.extra_data.borrow_mut().scroll_policy = layer_properties.scroll_policy; + *self.transform.borrow_mut() = layer_properties.transform; + *self.perspective.borrow_mut() = layer_properties.perspective; *self.background_color.borrow_mut() = to_layers_color(&layer_properties.background_color); @@ -392,7 +394,6 @@ impl CompositorLayer for Layer<CompositorData> { // Only scroll this layer if it's not fixed-positioned. if self.extra_data.borrow().scroll_policy != ScrollPolicy::FixedPosition { let new_offset = new_offset.to_untyped(); - *self.transform.borrow_mut() = Matrix4::identity().translate(new_offset.x, new_offset.y, 0.0); *self.content_offset.borrow_mut() = Point2D::from_untyped(&new_offset); result = true } diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index 22ca879b417..93a11d6b605 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -32,7 +32,7 @@ use euclid::approxeq::ApproxEq; use euclid::num::Zero; use libc::uintptr_t; use paint_task::PaintLayer; -use msg::compositor_msg::LayerId; +use msg::compositor_msg::{LayerId, LayerKind}; use net_traits::image::base::Image; use util::opts; use util::cursor::Cursor; @@ -246,6 +246,12 @@ pub struct StackingContext { /// A transform to be applied to this stacking context. pub transform: Matrix4, + + /// The perspective matrix to be applied to children. + pub perspective: Matrix4, + + /// Whether this stacking context creates a new 3d rendering context. + pub establishes_3d_context: bool, } impl StackingContext { @@ -255,30 +261,40 @@ impl StackingContext { bounds: &Rect<Au>, overflow: &Rect<Au>, z_index: i32, - transform: &Matrix4, filters: filter::T, blend_mode: mix_blend_mode::T, - layer: Option<Arc<PaintLayer>>) + layer: Option<Arc<PaintLayer>>, + transform: Matrix4, + perspective: Matrix4, + establishes_3d_context: bool) -> StackingContext { StackingContext { display_list: display_list, - layer: layer, bounds: *bounds, overflow: *overflow, z_index: z_index, - transform: *transform, filters: filters, blend_mode: blend_mode, + layer: layer, + transform: transform, + perspective: perspective, + establishes_3d_context: establishes_3d_context, } } /// Draws the stacking context in the proper order according to the steps in CSS 2.1 § E.2. - pub fn optimize_and_draw_into_context(&self, - paint_context: &mut PaintContext, - tile_bounds: &Rect<AzFloat>, - transform: &Matrix4, - clip_rect: Option<&Rect<Au>>) { - let transform = transform.mul(&self.transform); + pub fn draw_into_context(&self, + display_list: &DisplayList, + paint_context: &mut PaintContext, + tile_bounds: &Rect<AzFloat>, + transform: &Matrix4, + clip_rect: Option<&Rect<Au>>) { + // If a layer is being used, the transform for this layer + // will be handled by the compositor. + let transform = match self.layer { + Some(..) => *transform, + None => transform.mul(&self.transform), + }; let temporary_draw_target = paint_context.get_or_create_temporary_draw_target(&self.filters, self.blend_mode); { @@ -289,12 +305,9 @@ impl StackingContext { screen_rect: paint_context.screen_rect, clip_rect: clip_rect.map(|clip_rect| *clip_rect), transient_clip: None, + layer_kind: paint_context.layer_kind, }; - // Optimize the display list to throw out out-of-bounds display items and so forth. - let display_list = - DisplayListOptimizer::new(tile_bounds).optimize(&*self.display_list); - if opts::get().dump_display_list_optimized { println!("**** optimized display list. Tile bounds: {:?}", tile_bounds); display_list.print_items("*".to_owned()); @@ -409,6 +422,35 @@ impl StackingContext { paint_context.draw_temporary_draw_target_if_necessary(&temporary_draw_target, &self.filters, self.blend_mode) + + } + + /// Optionally optimize and then draws the stacking context. + pub fn optimize_and_draw_into_context(&self, + paint_context: &mut PaintContext, + tile_bounds: &Rect<AzFloat>, + transform: &Matrix4, + clip_rect: Option<&Rect<Au>>) { + // TODO(gw): This is a hack to avoid running the DL optimizer + // on 3d transformed tiles. We should have a better solution + // than just disabling the opts here. + if paint_context.layer_kind == LayerKind::Layer3D { + self.draw_into_context(&self.display_list, + paint_context, + tile_bounds, + transform, + clip_rect); + + } else { + // Optimize the display list to throw out out-of-bounds display items and so forth. + let display_list = DisplayListOptimizer::new(tile_bounds).optimize(&*self.display_list); + + self.draw_into_context(&display_list, + paint_context, + tile_bounds, + transform, + clip_rect); + } } /// Translate the given tile rect into the coordinate system of a child stacking context. @@ -1005,7 +1047,7 @@ impl<'a> Iterator for DisplayItemIterator<'a> { impl DisplayItem { /// Paints this display item into the given painting context. fn draw_into_context(&self, paint_context: &mut PaintContext) { - { + if paint_context.layer_kind == LayerKind::Layer2D { let this_clip = &self.base().clip; match paint_context.transient_clip { Some(ref transient_clip) if transient_clip == this_clip => {} diff --git a/components/gfx/paint_context.rs b/components/gfx/paint_context.rs index 2098b5c9c19..57b6b1feba2 100644 --- a/components/gfx/paint_context.rs +++ b/components/gfx/paint_context.rs @@ -29,6 +29,7 @@ use euclid::rect::Rect; use euclid::side_offsets::SideOffsets2D; use euclid::size::Size2D; use libc::types::common::c99::uint32_t; +use msg::compositor_msg::LayerKind; use net_traits::image::base::Image; use png::PixelsByColorType; use std::default::Default; @@ -54,6 +55,8 @@ pub struct PaintContext<'a> { /// clipping region used by the last display item. We cache the last value so that we avoid /// pushing and popping clipping regions unnecessarily. pub transient_clip: Option<ClippingRegion>, + /// A temporary hack to disable clipping optimizations on 3d layers. + pub layer_kind: LayerKind, } #[derive(Copy, Clone)] diff --git a/components/gfx/paint_task.rs b/components/gfx/paint_task.rs index b711b14e98e..1d02c153f78 100644 --- a/components/gfx/paint_task.rs +++ b/components/gfx/paint_task.rs @@ -21,7 +21,7 @@ use layers::platform::surface::NativeSurface; use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet}; use layers; use canvas_traits::CanvasMsg; -use msg::compositor_msg::{Epoch, FrameTreeId, LayerId}; +use msg::compositor_msg::{Epoch, FrameTreeId, LayerId, LayerKind}; use msg::compositor_msg::{LayerProperties, PaintListener, ScrollPolicy}; use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::{ConstellationChan, Failure, PipelineId}; @@ -69,6 +69,7 @@ pub struct PaintRequest { pub scale: f32, pub layer_id: LayerId, pub epoch: Epoch, + pub layer_kind: LayerKind, } pub enum Msg { @@ -272,10 +273,10 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static { } let mut replies = Vec::new(); - for PaintRequest { buffer_requests, scale, layer_id, epoch } + for PaintRequest { buffer_requests, scale, layer_id, epoch, layer_kind } in requests.into_iter() { if self.current_epoch == Some(epoch) { - self.paint(&mut replies, buffer_requests, scale, layer_id); + self.paint(&mut replies, buffer_requests, scale, layer_id, layer_kind); } else { debug!("painter epoch mismatch: {:?} != {:?}", self.current_epoch, epoch); } @@ -405,7 +406,8 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static { replies: &mut Vec<(LayerId, Box<LayerBufferSet>)>, mut tiles: Vec<BufferRequest>, scale: f32, - layer_id: LayerId) { + layer_id: LayerId, + layer_kind: LayerKind) { time::profile(time::ProfilerCategory::Painting, None, self.time_profiler_chan.clone(), || { // Bail out if there is no appropriate stacking context. let stacking_context = if let Some(ref stacking_context) = self.root_stacking_context { @@ -429,7 +431,8 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static { tile, layer_buffer, stacking_context.clone(), - scale); + scale, + layer_kind); } let new_buffers = (0..tile_count).map(|i| { let thread_id = i % self.worker_threads.len(); @@ -450,32 +453,72 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static { }; let mut properties = Vec::new(); - build(&mut properties, &**root_stacking_context, &ZERO_POINT); + build(&mut properties, + &**root_stacking_context, + &ZERO_POINT, + &Matrix4::identity(), + &Matrix4::identity(), + None); self.compositor.initialize_layers_for_pipeline(self.id, properties, self.current_epoch.unwrap()); fn build(properties: &mut Vec<LayerProperties>, stacking_context: &StackingContext, - page_position: &Point2D<Au>) { - let page_position = stacking_context.bounds.origin + *page_position; - if let Some(ref paint_layer) = stacking_context.layer { - // Layers start at the top left of their overflow rect, as far as the info we give to - // the compositor is concerned. - let overflow_relative_page_position = page_position + stacking_context.overflow.origin; - let layer_position = - Rect::new(Point2D::new(overflow_relative_page_position.x.to_nearest_px() as f32, - overflow_relative_page_position.y.to_nearest_px() as f32), - Size2D::new(stacking_context.overflow.size.width.to_nearest_px() as f32, - stacking_context.overflow.size.height.to_nearest_px() as f32)); - properties.push(LayerProperties { - id: paint_layer.id, - rect: layer_position, - background_color: paint_layer.background_color, - scroll_policy: paint_layer.scroll_policy, - }) - } + page_position: &Point2D<Au>, + transform: &Matrix4, + perspective: &Matrix4, + parent_id: Option<LayerId>) { + + let transform = transform.mul(&stacking_context.transform); + let perspective = perspective.mul(&stacking_context.perspective); + + let (next_parent_id, page_position, transform, perspective) = match stacking_context.layer { + Some(ref paint_layer) => { + // Layers start at the top left of their overflow rect, as far as the info we give to + // the compositor is concerned. + let overflow_relative_page_position = *page_position + + stacking_context.bounds.origin + + stacking_context.overflow.origin; + let layer_position = + Rect::new(Point2D::new(overflow_relative_page_position.x.to_nearest_px() as f32, + overflow_relative_page_position.y.to_nearest_px() as f32), + Size2D::new(stacking_context.overflow.size.width.to_nearest_px() as f32, + stacking_context.overflow.size.height.to_nearest_px() as f32)); + + let establishes_3d_context = stacking_context.establishes_3d_context; + + properties.push(LayerProperties { + id: paint_layer.id, + parent_id: parent_id, + rect: layer_position, + background_color: paint_layer.background_color, + scroll_policy: paint_layer.scroll_policy, + transform: transform, + perspective: perspective, + establishes_3d_context: establishes_3d_context, + }); + + // When there is a new layer, the transforms and origin + // are handled by the compositor. + (Some(paint_layer.id), + Point2D::zero(), + Matrix4::identity(), + Matrix4::identity()) + } + None => { + (parent_id, + stacking_context.bounds.origin + *page_position, + transform, + perspective) + } + }; for kid in stacking_context.display_list.children.iter() { - build(properties, &**kid, &page_position) + build(properties, + &**kid, + &page_position, + &transform, + &perspective, + next_parent_id); } } } @@ -522,8 +565,14 @@ impl WorkerThreadProxy { tile: BufferRequest, layer_buffer: Option<Box<LayerBuffer>>, stacking_context: Arc<StackingContext>, - scale: f32) { - let msg = MsgToWorkerThread::PaintTile(thread_id, tile, layer_buffer, stacking_context, scale); + scale: f32, + layer_kind: LayerKind) { + let msg = MsgToWorkerThread::PaintTile(thread_id, + tile, + layer_buffer, + stacking_context, + scale, + layer_kind); self.sender.send(msg).unwrap() } @@ -568,8 +617,12 @@ impl WorkerThread { loop { match self.receiver.recv().unwrap() { MsgToWorkerThread::Exit => break, - MsgToWorkerThread::PaintTile(thread_id, tile, layer_buffer, stacking_context, scale) => { - let draw_target = self.optimize_and_paint_tile(thread_id, &tile, stacking_context, scale); + MsgToWorkerThread::PaintTile(thread_id, tile, layer_buffer, stacking_context, scale, layer_kind) => { + let draw_target = self.optimize_and_paint_tile(thread_id, + &tile, + stacking_context, + scale, + layer_kind); let buffer = self.create_layer_buffer_for_painted_tile(&tile, layer_buffer, draw_target, @@ -584,7 +637,8 @@ impl WorkerThread { thread_id: usize, tile: &BufferRequest, stacking_context: Arc<StackingContext>, - scale: f32) + scale: f32, + layer_kind: LayerKind) -> DrawTarget { let size = Size2D::new(tile.screen_rect.size.width as i32, tile.screen_rect.size.height as i32); let draw_target = if !opts::get().gpu_painting { @@ -612,6 +666,7 @@ impl WorkerThread { screen_rect: tile.screen_rect, clip_rect: None, transient_clip: None, + layer_kind: layer_kind, }; // Apply a translation to start at the boundaries of the stacking context, since the @@ -708,7 +763,7 @@ impl WorkerThread { enum MsgToWorkerThread { Exit, - PaintTile(usize, BufferRequest, Option<Box<LayerBuffer>>, Arc<StackingContext>, f32), + PaintTile(usize, BufferRequest, Option<Box<LayerBuffer>>, Arc<StackingContext>, f32, LayerKind), } enum MsgFromWorkerThread { diff --git a/components/layout/block.rs b/components/layout/block.rs index 0ce4d5a9539..0e8990702c3 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -56,10 +56,10 @@ use std::cmp::{max, min}; use std::fmt; use std::sync::Arc; use style::computed_values::{border_collapse, box_sizing, display, float, overflow_x, overflow_y}; -use style::computed_values::{position, text_align}; +use style::computed_values::{transform, transform_style, position, text_align}; use style::properties::ComputedValues; use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto}; -use style::values::computed::{LengthOrPercentageOrNone}; +use style::values::computed::{LengthOrNone, LengthOrPercentageOrNone}; use util::geometry::{Au, MAX_AU, MAX_RECT}; use util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize, WritingMode}; use util::opts; @@ -617,6 +617,33 @@ impl BlockFlow { } } + pub fn transform_requires_layer(&self) -> bool { + // Check if the transform matrix is 2D or 3D + if let Some(ref transform_list) = self.fragment.style().get_effects().transform { + for transform in transform_list { + match transform { + &transform::ComputedOperation::Perspective(..) => { + return true; + } + &transform::ComputedOperation::Matrix(m) => { + // See http://dev.w3.org/csswg/css-transforms/#2d-matrix + if m.m31 != 0.0 || m.m32 != 0.0 || + m.m13 != 0.0 || m.m23 != 0.0 || + m.m43 != 0.0 || m.m14 != 0.0 || + m.m24 != 0.0 || m.m34 != 0.0 || + m.m33 != 1.0 || m.m44 != 1.0 { + return true; + } + } + _ => {} + } + } + } + + // Neither perspective nor transform present + false + } + /// Compute the actual inline size and position for this block. pub fn compute_used_inline_size(&mut self, layout_context: &LayoutContext, @@ -1676,6 +1703,16 @@ impl Flow for BlockFlow { self.base.stacking_relative_position_of_display_port = MAX_RECT; } + // This flow needs a layer if it has a 3d transform, or provides perspective + // to child layers. See http://dev.w3.org/csswg/css-transforms/#3d-rendering-contexts. + let transform_style = self.fragment.style().get_used_transform_style(); + let has_3d_transform = self.transform_requires_layer(); + let has_perspective = self.fragment.style().get_effects().perspective != LengthOrNone::None; + + if has_3d_transform || has_perspective { + self.base.flags.insert(NEEDS_LAYER); + } + if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) { let position_start = self.base.position.start.to_physical(self.base.writing_mode, container_size); @@ -1818,6 +1855,16 @@ impl Flow for BlockFlow { // Process children. for kid in self.base.child_iter() { + // If this layer preserves the 3d context of children, + // then children will need a render layer. + // TODO(gw): This isn't always correct. In some cases + // this may create extra layers than needed. I think + // there are also some edge cases where children don't + // get a layer when they should. + if transform_style == transform_style::T::preserve_3d { + flow::mut_base(kid).flags.insert(NEEDS_LAYER); + } + if flow::base(kid).flags.contains(INLINE_POSITION_IS_STATIC) || flow::base(kid).flags.contains(BLOCK_POSITION_IS_STATIC) { let kid_base = flow::mut_base(kid); diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 0ab4fe91fe1..e97dca0c17b 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -21,7 +21,7 @@ use list_item::ListItemFlow; use model::{self, MaybeAuto, ToGfxMatrix, ToAu}; use table_cell::CollapsedBordersForCell; -use euclid::{Point2D, Rect, Size2D, SideOffsets2D}; +use euclid::{Point2D, Point3D, Rect, Size2D, SideOffsets2D}; use euclid::Matrix4; use gfx_traits::color; use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDisplayItem}; @@ -46,11 +46,12 @@ use style::computed_values::filter::Filter; use style::computed_values::{background_attachment, background_clip, background_origin, background_repeat, background_size}; use style::computed_values::{border_style, image_rendering, overflow_x, position, - visibility, transform}; + visibility, transform, transform_style}; use style::properties::ComputedValues; use style::properties::style_structs::Border; use style::values::RGBA; -use style::values::computed::{Image, LinearGradient, LengthOrPercentage, LengthOrPercentageOrAuto}; +use style::values::computed::{Image, LinearGradient}; +use style::values::computed::{LengthOrNone, LengthOrPercentage, LengthOrPercentageOrAuto}; use style::values::specified::{AngleOrCorner, HorizontalDirection, VerticalDirection}; use url::Url; use util::cursor::Cursor; @@ -1146,17 +1147,18 @@ impl FragmentDisplayListBuilding for Fragment { if let Some(ref operations) = self.style().get_effects().transform { let transform_origin = self.style().get_effects().transform_origin; let transform_origin = - Point2D::new(model::specified(transform_origin.horizontal, + Point3D::new(model::specified(transform_origin.horizontal, border_box.size.width).to_f32_px(), model::specified(transform_origin.vertical, - border_box.size.height).to_f32_px()); + border_box.size.height).to_f32_px(), + transform_origin.depth.to_f32_px()); let pre_transform = Matrix4::create_translation(transform_origin.x, transform_origin.y, - 0.0); + transform_origin.z); let post_transform = Matrix4::create_translation(-transform_origin.x, -transform_origin.y, - 0.0); + -transform_origin.z); for operation in operations { let matrix = match operation { @@ -1190,6 +1192,31 @@ impl FragmentDisplayListBuilding for Fragment { transform = pre_transform.mul(&transform).mul(&post_transform); } + let perspective = match self.style().get_effects().perspective { + LengthOrNone::Length(d) => { + let perspective_origin = self.style().get_effects().perspective_origin; + let perspective_origin = + Point2D::new(model::specified(perspective_origin.horizontal, + border_box.size.width).to_f32_px(), + model::specified(perspective_origin.vertical, + border_box.size.height).to_f32_px()); + + let pre_transform = Matrix4::create_translation(perspective_origin.x, + perspective_origin.y, + 0.0); + let post_transform = Matrix4::create_translation(-perspective_origin.x, + -perspective_origin.y, + 0.0); + + let perspective_matrix = Matrix4::create_perspective(d.to_f32_px()); + + pre_transform.mul(&perspective_matrix).mul(&post_transform) + } + LengthOrNone::None => { + Matrix4::identity() + } + }; + // FIXME(pcwalton): Is this vertical-writing-direction-safe? let margin = self.margin.to_physical(base_flow.writing_mode); let overflow = base_flow.overflow.translate(&-Point2D::new(margin.left, Au(0))); @@ -1221,16 +1248,19 @@ impl FragmentDisplayListBuilding for Fragment { .send((layer_id, fragment_info.renderer.clone())).unwrap(); } + let transform_style = self.style().get_used_transform_style(); let layer = layer.map(|l| Arc::new(l)); Arc::new(StackingContext::new(display_list, &border_box, &overflow, self.style().get_box().z_index.number_or_zero(), - &transform, filters, self.style().get_effects().mix_blend_mode, - layer)) + layer, + transform, + perspective, + transform_style == transform_style::T::flat)) } #[inline(never)] @@ -1489,11 +1519,28 @@ impl BlockFlowDisplayListBuilding for BlockFlow { background_border_level); self.base.display_list_building_result = if self.fragment.establishes_stacking_context() { - DisplayListBuildingResult::StackingContext( - self.fragment.create_stacking_context(&self.base, - display_list, - layout_context, - StackingContextLayer::IfCanvas(self.layer_id(0)))) + if self.will_get_layer() { + // If we got here, then we need a new layer. + let scroll_policy = if self.is_fixed() { + ScrollPolicy::FixedPosition + } else { + ScrollPolicy::Scrollable + }; + + let paint_layer = PaintLayer::new(self.layer_id(0), color::transparent(), scroll_policy); + let layer = StackingContextLayer::Existing(paint_layer); + let stacking_context = self.fragment.create_stacking_context(&self.base, + display_list, + layout_context, + layer); + DisplayListBuildingResult::StackingContext(stacking_context) + } else { + DisplayListBuildingResult::StackingContext( + self.fragment.create_stacking_context(&self.base, + display_list, + layout_context, + StackingContextLayer::IfCanvas(self.layer_id(0)))) + } } else { match self.fragment.style.get_box().position { position::T::static_ => {} diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 36225040c4e..4a5fe56393c 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -40,6 +40,7 @@ use string_cache::Atom; use style::computed_values::content::ContentItem; use style::computed_values::{border_collapse, clear, mix_blend_mode, overflow_wrap, position}; use style::computed_values::{text_align, text_decoration, white_space, word_break}; +use style::computed_values::transform_style; use style::node::TNode; use style::properties::{self, ComputedValues, cascade_anonymous}; use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto}; @@ -1990,6 +1991,12 @@ impl Fragment { if self.style().get_effects().transform.is_some() { return true } + match self.style().get_used_transform_style() { + transform_style::T::flat | transform_style::T::preserve_3d => { + return true + } + transform_style::T::auto => {} + } // Canvas always layerizes, as an special case // FIXME(pcwalton): Don't unconditionally form stacking contexts for each canvas. diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index 1cad8855750..b4d74ced074 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -35,7 +35,7 @@ use euclid::scale_factor::ScaleFactor; use euclid::size::Size2D; use gfx_traits::color; use gfx::display_list::{ClippingRegion, DisplayItemMetadata, DisplayList, OpaqueNode}; -use gfx::display_list::{StackingContext}; +use gfx::display_list::StackingContext; use gfx::font_cache_task::FontCacheTask; use gfx::paint_task::Msg as PaintMsg; use gfx::paint_task::{PaintChan, PaintLayer}; @@ -872,10 +872,12 @@ impl LayoutTask { &origin, &origin, 0, - &Matrix4::identity(), filter::T::new(Vec::new()), mix_blend_mode::T::normal, - Some(paint_layer))); + Some(paint_layer), + Matrix4::identity(), + Matrix4::identity(), + true)); if opts::get().dump_display_list { println!("#### start printing display list."); diff --git a/components/msg/compositor_msg.rs b/components/msg/compositor_msg.rs index f6af5e02f22..b3f07a04e1d 100644 --- a/components/msg/compositor_msg.rs +++ b/components/msg/compositor_msg.rs @@ -6,6 +6,7 @@ use azure::azure_hl::Color; use constellation_msg::{Key, KeyState, KeyModifiers}; use euclid::point::Point2D; use euclid::rect::Rect; +use euclid::Matrix4; use layers::platform::surface::NativeGraphicsMetadata; use layers::layers::LayerBufferSet; use std::fmt::{Formatter, Debug}; @@ -51,6 +52,12 @@ impl LayerId { } } +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum LayerKind { + Layer2D, + Layer3D, +} + /// The scrolling policy of a layer. #[derive(Clone, PartialEq, Eq, Copy)] pub enum ScrollPolicy { @@ -66,12 +73,20 @@ pub enum ScrollPolicy { pub struct LayerProperties { /// An opaque ID. This is usually the address of the flow and index of the box within it. pub id: LayerId, + /// The id of the parent layer. + pub parent_id: Option<LayerId>, /// The position and size of the layer in pixels. pub rect: Rect<f32>, /// The background color of the layer. pub background_color: Color, /// The scrolling policy of this layer. pub scroll_policy: ScrollPolicy, + /// The transform for this layer + pub transform: Matrix4, + /// The perspective transform for this layer + pub perspective: Matrix4, + /// Whether this layer establishes a new 3d rendering context. + pub establishes_3d_context: bool, } /// The interface used by the painter to acquire draw targets for each paint frame and diff --git a/components/script/dom/webidls/CSSStyleDeclaration.webidl b/components/script/dom/webidls/CSSStyleDeclaration.webidl index d85dfc8f8ca..63220ad1ecd 100644 --- a/components/script/dom/webidls/CSSStyleDeclaration.webidl +++ b/components/script/dom/webidls/CSSStyleDeclaration.webidl @@ -93,6 +93,10 @@ partial interface CSSStyleDeclaration { [TreatNullAs=EmptyString] attribute DOMString transform; [TreatNullAs=EmptyString] attribute DOMString transformOrigin; + [TreatNullAs=EmptyString] attribute DOMString perspective; + [TreatNullAs=EmptyString] attribute DOMString perspectiveOrigin; + [TreatNullAs=EmptyString] attribute DOMString transformStyle; + [TreatNullAs=EmptyString] attribute DOMString backfaceVisibility; [TreatNullAs=EmptyString] attribute DOMString direction; diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 2760747c721..379d9e0fa06 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -48,7 +48,7 @@ dependencies = [ "core-graphics 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-text 0.1.0 (git+https://github.com/servo/core-text-rs)", "egl 0.1.0 (git+https://github.com/servo/rust-egl)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "freetype 0.1.0 (git+https://github.com/servo/rust-freetype)", "freetype-sys 2.4.11 (git+https://github.com/servo/libfreetype2)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -78,7 +78,7 @@ dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "canvas_traits 0.0.1", "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_traits 0.0.1", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", @@ -94,7 +94,7 @@ version = "0.0.1" dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_traits 0.0.1", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "offscreen_gl_context 0.0.1 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)", @@ -145,7 +145,7 @@ dependencies = [ "core-graphics 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-text 0.1.0 (git+https://github.com/servo/core-text-rs)", "devtools_traits 0.0.1", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.0.1", "gfx_traits 0.0.1", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -321,7 +321,7 @@ dependencies = [ [[package]] name = "euclid" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -403,7 +403,7 @@ dependencies = [ "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-text 0.1.0 (git+https://github.com/servo/core-text-rs)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "fontconfig 0.1.0 (git+https://github.com/servo/rust-fontconfig)", "freetype 0.1.0 (git+https://github.com/servo/rust-freetype)", @@ -504,7 +504,7 @@ dependencies = [ "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "compositing 0.0.1", "egl 0.1.0 (git+https://github.com/servo/rust-egl)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "glutin 0.0.26 (git+https://github.com/servo/glutin?branch=servo)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", @@ -592,7 +592,7 @@ source = "git+https://github.com/servo/io-surface-rs#401cf1d0a90290aa832b6220612 dependencies = [ "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -625,13 +625,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "layers" version = "0.1.0" -source = "git+https://github.com/servo/rust-layers#65001b9e18631172a457c31c04be990639c02c35" +source = "git+https://github.com/servo/rust-layers#d7defb1fbc84e90322d7b1c6f3fde6cf9ffb736d" dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "egl 0.1.0 (git+https://github.com/servo/rust-egl)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "glx 0.0.1 (git+https://github.com/servo/rust-glx)", "io-surface 0.1.0 (git+https://github.com/servo/io-surface-rs)", @@ -653,7 +653,7 @@ dependencies = [ "clock_ticks 0.0.6 (git+https://github.com/tomaka/clock_ticks)", "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.0.1", "gfx_traits 0.0.1", @@ -681,7 +681,7 @@ dependencies = [ name = "layout_traits" version = "0.0.1" dependencies = [ - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.0.1", "msg 0.0.1", "net_traits 0.0.1", @@ -764,7 +764,7 @@ dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "bitflags 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "io-surface 0.1.0 (git+https://github.com/servo/io-surface-rs)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", @@ -781,7 +781,7 @@ version = "0.0.1" dependencies = [ "cookie 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "devtools_traits 0.0.1", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -813,7 +813,7 @@ dependencies = [ name = "net_traits" version = "0.0.1" dependencies = [ - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", @@ -857,7 +857,7 @@ dependencies = [ "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "egl 0.1.0 (git+https://github.com/servo/rust-egl)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "glx 0.0.1 (git+https://github.com/servo/rust-glx)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", @@ -1034,7 +1034,7 @@ dependencies = [ "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "devtools_traits 0.0.1", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.0.1", "html5ever 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1077,7 +1077,7 @@ name = "script_traits" version = "0.0.1" dependencies = [ "devtools_traits 0.0.1", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "net_traits 0.0.1", @@ -1166,7 +1166,7 @@ dependencies = [ "bitflags 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1187,7 +1187,7 @@ name = "style_tests" version = "0.0.1" dependencies = [ "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "selectors 0.1.0 (git+https://github.com/servo/rust-selectors)", "string_cache 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1266,7 +1266,7 @@ dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "bitflags 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "lazy_static 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1288,7 +1288,7 @@ dependencies = [ name = "util_tests" version = "0.0.1" dependencies = [ - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", "util 0.0.1", diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs index 78ff721e8a6..ac0de8cbb4b 100644 --- a/components/style/properties.mako.rs +++ b/components/style/properties.mako.rs @@ -34,7 +34,6 @@ use computed_values; use self::property_bit_field::PropertyBitField; - <%! import re @@ -3498,8 +3497,151 @@ pub mod longhands { } </%self:longhand> + ${single_keyword("backface-visibility", "visible hidden")} + + ${single_keyword("transform-style", "auto flat preserve-3d")} + <%self:longhand name="transform-origin"> use values::computed::{ToComputedValue, Context}; + use values::specified::{Length, LengthOrPercentage}; + + use cssparser::ToCss; + use std::fmt; + use util::geometry::Au; + + pub mod computed_value { + use values::computed::{Length, LengthOrPercentage}; + + #[derive(Clone, Copy, Debug, PartialEq)] + pub struct T { + pub horizontal: LengthOrPercentage, + pub vertical: LengthOrPercentage, + pub depth: Length, + } + } + + #[derive(Clone, Copy, Debug, PartialEq)] + pub struct SpecifiedValue { + horizontal: LengthOrPercentage, + vertical: LengthOrPercentage, + depth: Length, + } + + impl ToCss for SpecifiedValue { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + try!(self.horizontal.to_css(dest)); + try!(dest.write_str(" ")); + try!(self.vertical.to_css(dest)); + try!(dest.write_str(" ")); + self.depth.to_css(dest) + } + } + + #[inline] + pub fn get_initial_value() -> computed_value::T { + computed_value::T { + horizontal: computed::LengthOrPercentage::Percentage(0.5), + vertical: computed::LengthOrPercentage::Percentage(0.5), + depth: Au(0), + } + } + + pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> { + let (mut horizontal, mut vertical, mut depth) = (None, None, None); + loop { + if let Err(_) = input.try(|input| { + let token = try!(input.expect_ident()); + match_ignore_ascii_case! { + token, + "left" => { + if horizontal.is_none() { + horizontal = Some(LengthOrPercentage::Percentage(0.0)) + } else { + return Err(()) + } + }, + "center" => { + if horizontal.is_none() { + horizontal = Some(LengthOrPercentage::Percentage(0.5)) + } else if vertical.is_none() { + vertical = Some(LengthOrPercentage::Percentage(0.5)) + } else { + return Err(()) + } + }, + "right" => { + if horizontal.is_none() { + horizontal = Some(LengthOrPercentage::Percentage(1.0)) + } else { + return Err(()) + } + }, + "top" => { + if vertical.is_none() { + vertical = Some(LengthOrPercentage::Percentage(0.0)) + } else { + return Err(()) + } + }, + "bottom" => { + if vertical.is_none() { + vertical = Some(LengthOrPercentage::Percentage(1.0)) + } else { + return Err(()) + } + } + _ => return Err(()) + } + Ok(()) + }) { + match LengthOrPercentage::parse(input) { + Ok(value) => { + if horizontal.is_none() { + horizontal = Some(value); + } else if vertical.is_none() { + vertical = Some(value); + } else if let LengthOrPercentage::Length(length) = value { + depth = Some(length); + } else { + return Err(()); + } + } + _ => break, + } + } + } + + if horizontal.is_some() || vertical.is_some() { + Ok(SpecifiedValue { + horizontal: horizontal.unwrap_or(LengthOrPercentage::Percentage(0.5)), + vertical: vertical.unwrap_or(LengthOrPercentage::Percentage(0.5)), + depth: depth.unwrap_or(Length::Absolute(Au(0))), + }) + } else { + Err(()) + } + } + + impl ToComputedValue for SpecifiedValue { + type ComputedValue = computed_value::T; + + #[inline] + fn to_computed_value(&self, context: &Context) -> computed_value::T { + computed_value::T { + horizontal: self.horizontal.to_computed_value(context), + vertical: self.vertical.to_computed_value(context), + depth: self.depth.to_computed_value(context), + } + } + } + </%self:longhand> + + ${predefined_type("perspective", + "LengthOrNone", + "computed::LengthOrNone::None")} + + <%self:longhand name="perspective-origin"> + use values::computed::{ToComputedValue, Context}; use values::specified::LengthOrPercentage; use cssparser::ToCss; @@ -5323,6 +5465,34 @@ impl ComputedValues { self.font.clone() } + // http://dev.w3.org/csswg/css-transforms/#grouping-property-values + pub fn get_used_transform_style(&self) -> computed_values::transform_style::T { + use computed_values::mix_blend_mode; + use computed_values::transform_style; + + let effects = self.get_effects(); + + // TODO(gw): Add clip-path, isolation, mask-image, mask-border-source when supported. + if effects.opacity < 1.0 || + !effects.filter.is_empty() || + effects.clip.is_some() { + effects.mix_blend_mode != mix_blend_mode::T::normal || + return transform_style::T::flat; + } + + if effects.transform_style == transform_style::T::auto { + if effects.transform.is_some() { + return transform_style::T::flat; + } + if effects.perspective != computed::LengthOrNone::None { + return transform_style::T::flat; + } + } + + // Return the computed value if not overridden by the above exceptions + effects.transform_style + } + % for style_struct in STYLE_STRUCTS: #[inline] pub fn get_${style_struct.name.lower()} diff --git a/components/style/values.rs b/components/style/values.rs index d6ccb0480be..3fad8588a18 100644 --- a/components/style/values.rs +++ b/components/style/values.rs @@ -480,6 +480,45 @@ pub mod specified { } } + #[derive(Clone, PartialEq, Copy, Debug)] + pub enum LengthOrNone { + Length(Length), + None, + } + + impl ToCss for LengthOrNone { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + match self { + &LengthOrNone::Length(length) => length.to_css(dest), + &LengthOrNone::None => dest.write_str("none"), + } + } + } + impl LengthOrNone { + fn parse_internal(input: &mut Parser, context: &AllowedNumericType) + -> Result<LengthOrNone, ()> + { + match try!(input.next()) { + Token::Dimension(ref value, ref unit) if context.is_ok(value.value) => + Length::parse_dimension(value.value, unit).map(LengthOrNone::Length), + Token::Number(ref value) if value.value == 0. => + Ok(LengthOrNone::Length(Length::Absolute(Au(0)))), + Token::Ident(ref value) if value.eq_ignore_ascii_case("none") => + Ok(LengthOrNone::None), + _ => Err(()) + } + } + #[allow(dead_code)] + #[inline] + pub fn parse(input: &mut Parser) -> Result<LengthOrNone, ()> { + LengthOrNone::parse_internal(input, &AllowedNumericType::All) + } + #[inline] + pub fn parse_non_negative(input: &mut Parser) -> Result<LengthOrNone, ()> { + LengthOrNone::parse_internal(input, &AllowedNumericType::NonNegative) + } + } + /// The sum of a series of lengths and a percentage. This is used in `calc()` and other things /// that effectively work like it (e.g. transforms). #[derive(Clone, Debug, PartialEq)] @@ -1069,6 +1108,36 @@ pub mod computed { } } + #[derive(PartialEq, Clone, Copy)] + pub enum LengthOrNone { + Length(Au), + None, + } + impl fmt::Debug for LengthOrNone { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + &LengthOrNone::Length(length) => write!(f, "{:?}", length), + &LengthOrNone::None => write!(f, "none"), + } + } + } + + impl ToComputedValue for specified::LengthOrNone { + type ComputedValue = LengthOrNone; + + #[inline] + fn to_computed_value(&self, context: &Context) -> LengthOrNone { + match *self { + specified::LengthOrNone::Length(value) => { + LengthOrNone::Length(value.to_computed_value(context)) + } + specified::LengthOrNone::None => { + LengthOrNone::None + } + } + } + } + /// The sum of a series of lengths and a percentage. This is used in `calc()` and other things /// that effectively work like it (e.g. transforms). #[derive(Clone, Copy, Debug, PartialEq)] diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 8a383015502..1e05f384c37 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -10,7 +10,7 @@ dependencies = [ "core-graphics 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-text 0.1.0 (git+https://github.com/servo/core-text-rs)", "devtools 0.0.1", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.0.1", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "glutin_app 0.0.1", @@ -47,7 +47,7 @@ dependencies = [ "core-graphics 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-text 0.1.0 (git+https://github.com/servo/core-text-rs)", "egl 0.1.0 (git+https://github.com/servo/rust-egl)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "freetype 0.1.0 (git+https://github.com/servo/rust-freetype)", "freetype-sys 2.4.11 (git+https://github.com/servo/libfreetype2)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -77,7 +77,7 @@ dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "canvas_traits 0.0.1", "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_traits 0.0.1", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", @@ -93,7 +93,7 @@ version = "0.0.1" dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_traits 0.0.1", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "offscreen_gl_context 0.0.1 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)", @@ -144,7 +144,7 @@ dependencies = [ "core-graphics 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-text 0.1.0 (git+https://github.com/servo/core-text-rs)", "devtools_traits 0.0.1", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.0.1", "gfx_traits 0.0.1", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -320,7 +320,7 @@ dependencies = [ [[package]] name = "euclid" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -402,7 +402,7 @@ dependencies = [ "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-text 0.1.0 (git+https://github.com/servo/core-text-rs)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "fontconfig 0.1.0 (git+https://github.com/servo/rust-fontconfig)", "freetype 0.1.0 (git+https://github.com/servo/rust-freetype)", @@ -496,7 +496,7 @@ dependencies = [ "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "compositing 0.0.1", "egl 0.1.0 (git+https://github.com/servo/rust-egl)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "glutin 0.0.26 (git+https://github.com/servo/glutin?branch=servo)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", @@ -584,7 +584,7 @@ source = "git+https://github.com/servo/io-surface-rs#401cf1d0a90290aa832b6220612 dependencies = [ "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -617,13 +617,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "layers" version = "0.1.0" -source = "git+https://github.com/servo/rust-layers#65001b9e18631172a457c31c04be990639c02c35" +source = "git+https://github.com/servo/rust-layers#d7defb1fbc84e90322d7b1c6f3fde6cf9ffb736d" dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "egl 0.1.0 (git+https://github.com/servo/rust-egl)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "glx 0.0.1 (git+https://github.com/servo/rust-glx)", "io-surface 0.1.0 (git+https://github.com/servo/io-surface-rs)", @@ -645,7 +645,7 @@ dependencies = [ "clock_ticks 0.0.6 (git+https://github.com/tomaka/clock_ticks)", "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.0.1", "gfx_traits 0.0.1", @@ -673,7 +673,7 @@ dependencies = [ name = "layout_traits" version = "0.0.1" dependencies = [ - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.0.1", "msg 0.0.1", "net_traits 0.0.1", @@ -756,7 +756,7 @@ dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "bitflags 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "io-surface 0.1.0 (git+https://github.com/servo/io-surface-rs)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", @@ -773,7 +773,7 @@ version = "0.0.1" dependencies = [ "cookie 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "devtools_traits 0.0.1", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -793,7 +793,7 @@ dependencies = [ name = "net_traits" version = "0.0.1" dependencies = [ - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", @@ -837,7 +837,7 @@ dependencies = [ "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "egl 0.1.0 (git+https://github.com/servo/rust-egl)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "glx 0.0.1 (git+https://github.com/servo/rust-glx)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", @@ -1014,7 +1014,7 @@ dependencies = [ "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "devtools_traits 0.0.1", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.0.1", "html5ever 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1049,7 +1049,7 @@ name = "script_traits" version = "0.0.1" dependencies = [ "devtools_traits 0.0.1", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "net_traits 0.0.1", @@ -1164,7 +1164,7 @@ dependencies = [ "bitflags 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1250,7 +1250,7 @@ dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "bitflags 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "lazy_static 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index 205364aa667..6d248ea394a 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -7,7 +7,7 @@ dependencies = [ "egl 0.1.0 (git+https://github.com/servo/rust-egl)", "env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "errno 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.0.1", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", @@ -34,7 +34,7 @@ dependencies = [ "core-graphics 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-text 0.1.0 (git+https://github.com/servo/core-text-rs)", "egl 0.1.0 (git+https://github.com/servo/rust-egl)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "freetype 0.1.0 (git+https://github.com/servo/rust-freetype)", "freetype-sys 2.4.11 (git+https://github.com/servo/libfreetype2)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -64,7 +64,7 @@ dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "canvas_traits 0.0.1", "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_traits 0.0.1", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", @@ -80,7 +80,7 @@ version = "0.0.1" dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_traits 0.0.1", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "offscreen_gl_context 0.0.1 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)", @@ -121,7 +121,7 @@ dependencies = [ "core-graphics 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-text 0.1.0 (git+https://github.com/servo/core-text-rs)", "devtools_traits 0.0.1", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.0.1", "gfx_traits 0.0.1", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -307,7 +307,7 @@ dependencies = [ [[package]] name = "euclid" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -381,7 +381,7 @@ dependencies = [ "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-text 0.1.0 (git+https://github.com/servo/core-text-rs)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "fontconfig 0.1.0 (git+https://github.com/servo/rust-fontconfig)", "freetype 0.1.0 (git+https://github.com/servo/rust-freetype)", @@ -518,7 +518,7 @@ source = "git+https://github.com/servo/io-surface-rs#401cf1d0a90290aa832b6220612 dependencies = [ "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -551,13 +551,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "layers" version = "0.1.0" -source = "git+https://github.com/servo/rust-layers#65001b9e18631172a457c31c04be990639c02c35" +source = "git+https://github.com/servo/rust-layers#d7defb1fbc84e90322d7b1c6f3fde6cf9ffb736d" dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "egl 0.1.0 (git+https://github.com/servo/rust-egl)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "glx 0.0.1 (git+https://github.com/servo/rust-glx)", "io-surface 0.1.0 (git+https://github.com/servo/io-surface-rs)", @@ -579,7 +579,7 @@ dependencies = [ "clock_ticks 0.0.6 (git+https://github.com/tomaka/clock_ticks)", "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.0.1", "gfx_traits 0.0.1", @@ -607,7 +607,7 @@ dependencies = [ name = "layout_traits" version = "0.0.1" dependencies = [ - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.0.1", "msg 0.0.1", "net_traits 0.0.1", @@ -682,7 +682,7 @@ dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "bitflags 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "io-surface 0.1.0 (git+https://github.com/servo/io-surface-rs)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", @@ -699,7 +699,7 @@ version = "0.0.1" dependencies = [ "cookie 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "devtools_traits 0.0.1", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -719,7 +719,7 @@ dependencies = [ name = "net_traits" version = "0.0.1" dependencies = [ - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", @@ -754,7 +754,7 @@ dependencies = [ "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "egl 0.1.0 (git+https://github.com/servo/rust-egl)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "glx 0.0.1 (git+https://github.com/servo/rust-glx)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", @@ -922,7 +922,7 @@ dependencies = [ "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "devtools_traits 0.0.1", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.0.1", "html5ever 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -957,7 +957,7 @@ name = "script_traits" version = "0.0.1" dependencies = [ "devtools_traits 0.0.1", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "net_traits 0.0.1", @@ -1062,7 +1062,7 @@ dependencies = [ "bitflags 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1139,7 +1139,7 @@ dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "bitflags 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "lazy_static 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/tests/html/test_3d_transform_1.html b/tests/html/test_3d_transform_1.html new file mode 100644 index 00000000000..e35a7777018 --- /dev/null +++ b/tests/html/test_3d_transform_1.html @@ -0,0 +1,131 @@ +<!DOCTYPE html> +<html> + <head> + <style type="text/css"> + /* Shorthand classes for different perspective values */ + .pers250 { + perspective: 250px; + } + .pers350 { + perspective: 350px; + } + .pers500 { + perspective: 500px; + } + + /* Define the container div, the cube div, and a generic face */ + .container { + width: 200px; + height: 200px; + margin: 75px 0 0 75px; + border: none; + } + .cube { + width: 100%; + height: 100%; + backface-visibility: visible; + perspective-origin: 150% 150%; + transform-style: preserve-3d; + } + .face { + display: block; + position: absolute; + width: 100px; + height: 100px; + border: none; + line-height: 100px; + font-family: sans-serif; + font-size: 60px; + color: white; + text-align: center; + } + + /* Define each face based on direction */ + .front { + background: rgba(0, 0, 0, 0.3); + transform: translateZ(50px); + } + .back { + background: rgba(0, 255, 0, 1); + color: black; + transform: rotateY(180deg) translateZ(50px); + } + .right { + background: rgba(196, 0, 0, 0.7); + transform: rotateY(90deg) translateZ(50px); + } + .left { + background: rgba(0, 0, 196, 0.7); + transform: rotateY(-90deg) translateZ(50px); + } + .top { + background: rgba(196, 196, 0, 0.7); + transform: rotateX(90deg) translateZ(50px); + } + .bottom { + background: rgba(196, 0, 196, 0.7); + transform: rotateX(-90deg) translateZ(50px); + } + + /* Make the table a little nicer */ + th, p, td { + background-color: #EEEEEE; + padding: 10px; + font-family: sans-serif; + text-align: left; + } + </style> + </head> + <body> + <table> + <tbody> + <tr> + <th><code>perspective: 250px;</code> + </th> + <th><code>perspective: 350px;</code> + </th> + <th><code>perspective: 500px;</code> + </th> + </tr> + <tr> + <td> + <div class="container"> + <div class="cube pers250"> + <div class="face front"></div> + <div class="face back"></div> + <div class="face right"></div> + <div class="face left"></div> + <div class="face top"></div> + <div class="face bottom"></div> + </div> + </div> + </td> + <td> + <div class="container"> + <div class="cube pers350"> + <div class="face front"></div> + <div class="face back"></div> + <div class="face right"></div> + <div class="face left"></div> + <div class="face top"></div> + <div class="face bottom"></div> + </div> + </div> + </td> + <td> + <div class="container"> + <div class="cube pers500"> + <div class="face front"></div> + <div class="face back"></div> + <div class="face right"></div> + <div class="face left"></div> + <div class="face top"></div> + <div class="face bottom"></div> + </div> + </div> + </td> + </tr> + </tbody> + </table> + </body> +</html> diff --git a/tests/html/test_3d_transform_2.html b/tests/html/test_3d_transform_2.html new file mode 100644 index 00000000000..b585831a52c --- /dev/null +++ b/tests/html/test_3d_transform_2.html @@ -0,0 +1,81 @@ +<!DOCTYPE html> +<html> + <head> + <style type="text/css"> + .pers200 { + perspective: 200px; + } + + .pers500 { + perspective: 500px; + } + + .container { + //background-color: red; + width: 200px; + height: 200px; + margin: 75px 0 0 75px; + //border: 1px solid red; + } + .cube { + //background-color: green; + width: 100%; + height: 100%; + backface-visibility: visible; + perspective-origin: 150% 150%; + transform-style: preserve-3d; + } + .face { + display: block; + position: absolute; + width: 100px; + height: 100px; + border: none; + line-height: 100px; + font-family: sans-serif; + font-size: 60px; + color: white; + text-align: center; + } + + /* Define each face based on direction */ + .front { + background: rgba(1, 1, 1, 0.5); + transform: translateZ(50px); + } + .back { + background: rgba(0, 255, 0, 0.5); + color: black; + transform: rotateY(180deg) translateZ(50px); + } + .right { + background: rgba(196, 0, 0, 0.7); + transform: rotateY(90deg) translateZ(50px); + } + .left { + background: rgba(0, 0, 196, 0.7); + transform: rotateY(-90deg) translateZ(50px); + } + .top { + background: rgba(196, 196, 0, 0.7); + transform: rotateX(90deg) translateZ(50px); + } + .bottom { + background: rgba(196, 0, 196, 0.7); + transform: rotateX(-90deg) translateZ(50px); + } + </style> + </head> + <body> + <div class="container"> + <div class="cube pers500"> + <div class="face front"></div> + <div class="face back"></div> + <div class="face right"></div> + <div class="face left"></div> + <div class="face top"></div> + <div class="face bottom"></div> + </div> + </div> + </body> +</html> diff --git a/tests/html/test_3d_transform_zsort.html b/tests/html/test_3d_transform_zsort.html new file mode 100644 index 00000000000..688d717d659 --- /dev/null +++ b/tests/html/test_3d_transform_zsort.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<html> + <head> + <style type="text/css"> + * { + margin: 0; + padding: 0; + } + .container { + perspective: 100px; + background-color: rgba(0, 0, 0, 0.5); + width: 600px; + height: 600px; + transform-style: preserve-3d; + } + .f1 { + position: absolute; + top: 0px; + left: 0px; + width: 200px; + height: 200px; + background-color: red; + transform: translate3d(0, 0, -5px); + } + .f2 { + position: absolute; + top: 100px; + left: 100px; + width: 200px; + height: 200px; + background-color: green; + transform: translate3d(0, 0, 0); + } + .f3 { + position: absolute; + top: 200px; + left: 200px; + width: 200px; + height: 200px; + background-color: blue; + transform: translate3d(0, 0, 0); + } + </style> + </head> + <body> + <div class="container">AAA + <div class="f1"></div> + <div class="f2"></div> + <div class="f3"></div> + </div> + </body> +</html> |