mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
gfx: Implement box-shadow
per CSS-BACKGROUNDS.
This commit is contained in:
parent
1bc2c8a639
commit
3ba0abd8ff
21 changed files with 766 additions and 31 deletions
|
@ -24,12 +24,14 @@ use util::{OpaqueNodeMethods, ToGfxColor};
|
|||
use geom::approxeq::ApproxEq;
|
||||
use geom::{Point2D, Rect, Size2D, SideOffsets2D};
|
||||
use gfx::color;
|
||||
use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass, DisplayItem};
|
||||
use gfx::display_list::{DisplayList, GradientDisplayItem, GradientDisplayItemClass, GradientStop};
|
||||
use gfx::display_list::{ImageDisplayItem, ImageDisplayItemClass, LineDisplayItem, BorderRadii};
|
||||
use gfx::display_list::{LineDisplayItemClass, SidewaysLeft, SidewaysRight};
|
||||
use gfx::display_list::{SolidColorDisplayItem, SolidColorDisplayItemClass, StackingContext};
|
||||
use gfx::display_list::{TextDisplayItem, TextDisplayItemClass, Upright};
|
||||
use gfx::display_list::{BOX_SHADOW_INFLATION_FACTOR, BaseDisplayItem, BorderDisplayItem};
|
||||
use gfx::display_list::{BorderDisplayItemClass, BorderRadii, BoxShadowDisplayItem};
|
||||
use gfx::display_list::{BoxShadowDisplayItemClass, DisplayItem, DisplayList};
|
||||
use gfx::display_list::{GradientDisplayItem, GradientDisplayItemClass};
|
||||
use gfx::display_list::{GradientStop, ImageDisplayItem, ImageDisplayItemClass, LineDisplayItem};
|
||||
use gfx::display_list::{LineDisplayItemClass, SidewaysLeft};
|
||||
use gfx::display_list::{SidewaysRight, SolidColorDisplayItem, SolidColorDisplayItemClass};
|
||||
use gfx::display_list::{StackingContext, TextDisplayItem, TextDisplayItemClass, Upright};
|
||||
use gfx::paint_task::PaintLayer;
|
||||
use servo_msg::compositor_msg::{FixedPosition, Scrollable};
|
||||
use servo_msg::constellation_msg::{ConstellationChan, FrameRectMsg};
|
||||
|
@ -112,12 +114,24 @@ pub trait FragmentDisplayListBuilding {
|
|||
level: StackingLevel,
|
||||
clip_rect: &Rect<Au>);
|
||||
|
||||
/// Adds the display items necessary to paint the outline of this fragment to the display list
|
||||
/// if necessary.
|
||||
fn build_display_list_for_outline_if_applicable(&self,
|
||||
style: &ComputedValues,
|
||||
display_list: &mut DisplayList,
|
||||
bounds: &Rect<Au>,
|
||||
clip_rect: &Rect<Au>);
|
||||
|
||||
/// Adds the display items necessary to paint the box shadow of this fragment to the display
|
||||
/// list if necessary.
|
||||
fn build_display_list_for_box_shadow_if_applicable(&self,
|
||||
style: &ComputedValues,
|
||||
list: &mut DisplayList,
|
||||
layout_context: &LayoutContext,
|
||||
level: StackingLevel,
|
||||
absolute_bounds: &Rect<Au>,
|
||||
clip_rect: &Rect<Au>);
|
||||
|
||||
fn build_debug_borders_around_text_fragments(&self,
|
||||
display_list: &mut DisplayList,
|
||||
flow_origin: Point2D<Au>,
|
||||
|
@ -413,6 +427,32 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
display_list.push(gradient_display_item, level)
|
||||
}
|
||||
|
||||
fn build_display_list_for_box_shadow_if_applicable(&self,
|
||||
style: &ComputedValues,
|
||||
list: &mut DisplayList,
|
||||
_layout_context: &LayoutContext,
|
||||
level: StackingLevel,
|
||||
absolute_bounds: &Rect<Au>,
|
||||
clip_rect: &Rect<Au>) {
|
||||
// NB: According to CSS-BACKGROUNDS, box shadows render in *reverse* order (front to back).
|
||||
for box_shadow in style.get_effects().box_shadow.iter().rev() {
|
||||
let inflation = box_shadow.spread_radius + box_shadow.blur_radius *
|
||||
BOX_SHADOW_INFLATION_FACTOR;
|
||||
let bounds =
|
||||
absolute_bounds.translate(&Point2D(box_shadow.offset_x, box_shadow.offset_y))
|
||||
.inflate(inflation, inflation);
|
||||
list.push(BoxShadowDisplayItemClass(box BoxShadowDisplayItem {
|
||||
base: BaseDisplayItem::new(bounds, self.node, *clip_rect),
|
||||
box_bounds: *absolute_bounds,
|
||||
color: style.resolve_color(box_shadow.color).to_gfx_color(),
|
||||
offset: Point2D(box_shadow.offset_x, box_shadow.offset_y),
|
||||
blur_radius: box_shadow.blur_radius,
|
||||
spread_radius: box_shadow.spread_radius,
|
||||
inset: box_shadow.inset,
|
||||
}), level);
|
||||
}
|
||||
}
|
||||
|
||||
fn build_display_list_for_borders_if_applicable(&self,
|
||||
style: &ComputedValues,
|
||||
display_list: &mut DisplayList,
|
||||
|
@ -590,6 +630,34 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
let level =
|
||||
StackingLevel::from_background_and_border_level(background_and_border_level);
|
||||
|
||||
// Add a shadow to the list, if applicable.
|
||||
match self.inline_context {
|
||||
Some(ref inline_context) => {
|
||||
for style in inline_context.styles.iter().rev() {
|
||||
self.build_display_list_for_box_shadow_if_applicable(
|
||||
&**style,
|
||||
display_list,
|
||||
layout_context,
|
||||
level,
|
||||
&absolute_fragment_bounds,
|
||||
clip_rect);
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
match self.specific {
|
||||
ScannedTextFragment(_) => {},
|
||||
_ => {
|
||||
self.build_display_list_for_box_shadow_if_applicable(
|
||||
&*self.style,
|
||||
display_list,
|
||||
layout_context,
|
||||
level,
|
||||
&absolute_fragment_bounds,
|
||||
clip_rect);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the background to the list, if applicable.
|
||||
match self.inline_context {
|
||||
Some(ref inline_context) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue