mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
Handle clip-path in stylo
This commit is contained in:
parent
1d32422fe8
commit
3895b7118e
12 changed files with 432 additions and 49 deletions
|
@ -79,3 +79,182 @@ impl From<nsStyleCoord_CalcValue> for LengthOrPercentage {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod basic_shape {
|
||||
use euclid::size::Size2D;
|
||||
use gecko_bindings::structs::StyleClipPathGeometryBox;
|
||||
use gecko_bindings::structs::{StyleBasicShape, StyleBasicShapeType, StyleFillRule};
|
||||
use gecko_bindings::structs::{nsStyleCoord, nsStyleCorners, nsStyleImageLayers_Position};
|
||||
use gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue};
|
||||
use gecko_values::GeckoStyleCoordConvertible;
|
||||
use std::borrow::Borrow;
|
||||
use values::computed::basic_shape::*;
|
||||
use values::computed::position::Position;
|
||||
use values::computed::{BorderRadiusSize, LengthOrPercentage};
|
||||
|
||||
// using Borrow so that we can have a non-moving .into()
|
||||
impl<T: Borrow<StyleBasicShape>> From<T> for BasicShape {
|
||||
fn from(other: T) -> Self {
|
||||
let other = other.borrow();
|
||||
match other.mType {
|
||||
StyleBasicShapeType::Inset => {
|
||||
let t = LengthOrPercentage::from_gecko_style_coord(&other.mCoordinates[0]);
|
||||
let r = LengthOrPercentage::from_gecko_style_coord(&other.mCoordinates[1]);
|
||||
let b = LengthOrPercentage::from_gecko_style_coord(&other.mCoordinates[2]);
|
||||
let l = LengthOrPercentage::from_gecko_style_coord(&other.mCoordinates[3]);
|
||||
let round = (&other.mRadius).into();
|
||||
BasicShape::Inset(InsetRect {
|
||||
top: t.expect("inset() offset should be a length, percentage, or calc value"),
|
||||
right: r.expect("inset() offset should be a length, percentage, or calc value"),
|
||||
bottom: b.expect("inset() offset should be a length, percentage, or calc value"),
|
||||
left: l.expect("inset() offset should be a length, percentage, or calc value"),
|
||||
round: Some(round),
|
||||
})
|
||||
}
|
||||
StyleBasicShapeType::Circle => {
|
||||
BasicShape::Circle(Circle {
|
||||
radius: (&other.mCoordinates[0]).into(),
|
||||
position: (&other.mPosition).into()
|
||||
})
|
||||
}
|
||||
StyleBasicShapeType::Ellipse => {
|
||||
BasicShape::Ellipse(Ellipse {
|
||||
semiaxis_x: (&other.mCoordinates[0]).into(),
|
||||
semiaxis_y: (&other.mCoordinates[1]).into(),
|
||||
position: (&other.mPosition).into()
|
||||
})
|
||||
}
|
||||
StyleBasicShapeType::Polygon => {
|
||||
let fill_rule = if other.mFillRule == StyleFillRule::Evenodd {
|
||||
FillRule::EvenOdd
|
||||
} else {
|
||||
FillRule::NonZero
|
||||
};
|
||||
let mut coords = Vec::with_capacity(other.mCoordinates.len() / 2);
|
||||
for i in 0..(other.mCoordinates.len() / 2) {
|
||||
let x = 2 * i;
|
||||
let y = x + 1;
|
||||
coords.push((LengthOrPercentage::from_gecko_style_coord(&other.mCoordinates[x])
|
||||
.expect("polygon() coordinate should be a length, percentage, or calc value"),
|
||||
LengthOrPercentage::from_gecko_style_coord(&other.mCoordinates[y])
|
||||
.expect("polygon() coordinate should be a length, percentage, or calc value")
|
||||
))
|
||||
}
|
||||
BasicShape::Polygon(Polygon {
|
||||
fill: fill_rule,
|
||||
coordinates: coords,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Borrow<nsStyleCorners>> From<T> for BorderRadius {
|
||||
fn from(other: T) -> Self {
|
||||
let other = other.borrow();
|
||||
let get_corner = |index| {
|
||||
BorderRadiusSize(Size2D::new(
|
||||
LengthOrPercentage::from_gecko_style_coord(&other.data_at(index))
|
||||
.expect("<border-radius> should be a length, percentage, or calc value"),
|
||||
LengthOrPercentage::from_gecko_style_coord(&other.data_at(index + 1))
|
||||
.expect("<border-radius> should be a length, percentage, or calc value")))
|
||||
};
|
||||
|
||||
BorderRadius {
|
||||
top_left: get_corner(0),
|
||||
top_right: get_corner(2),
|
||||
bottom_right: get_corner(4),
|
||||
bottom_left: get_corner(6),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Can't be a From impl since we need to set an existing
|
||||
// nsStyleCorners, not create a new one
|
||||
impl BorderRadius {
|
||||
pub fn set_corners(&self, other: &mut nsStyleCorners) {
|
||||
let mut set_corner = |field: &BorderRadiusSize, index| {
|
||||
field.0.width.to_gecko_style_coord(&mut other.data_at_mut(index));
|
||||
field.0.height.to_gecko_style_coord(&mut other.data_at_mut(index + 1));
|
||||
};
|
||||
set_corner(&self.top_left, 0);
|
||||
set_corner(&self.top_right, 2);
|
||||
set_corner(&self.bottom_right, 4);
|
||||
set_corner(&self.bottom_left, 6);
|
||||
}
|
||||
}
|
||||
|
||||
/// We use None for a nonexistant radius, but Gecko uses (0 0 0 0 / 0 0 0 0)
|
||||
pub fn set_corners_from_radius(radius: Option<BorderRadius>, other: &mut nsStyleCorners) {
|
||||
if let Some(radius) = radius {
|
||||
radius.set_corners(other);
|
||||
} else {
|
||||
for i in 0..8 {
|
||||
other.data_at_mut(i).set_value(CoordDataValue::Coord(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Can't be a From impl since we need to set an existing
|
||||
// nsStyleImageLayers_Position, not create a new one
|
||||
impl From<Position> for nsStyleImageLayers_Position {
|
||||
fn from(other: Position) -> Self {
|
||||
nsStyleImageLayers_Position {
|
||||
mXPosition: other.horizontal.into(),
|
||||
mYPosition: other.vertical.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Borrow<nsStyleCoord>> From<T> for ShapeRadius {
|
||||
fn from(other: T) -> Self {
|
||||
let other = other.borrow();
|
||||
ShapeRadius::from_gecko_style_coord(other)
|
||||
.expect("<shape-radius> should be a length, percentage, calc, or keyword value")
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Borrow<nsStyleImageLayers_Position>> From<T> for Position {
|
||||
fn from(other: T) -> Self {
|
||||
let other = other.borrow();
|
||||
Position {
|
||||
horizontal: other.mXPosition.into(),
|
||||
vertical: other.mYPosition.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GeometryBox> for StyleClipPathGeometryBox {
|
||||
fn from(reference: GeometryBox) -> Self {
|
||||
use gecko_bindings::structs::StyleClipPathGeometryBox::*;
|
||||
match reference {
|
||||
GeometryBox::ShapeBox(ShapeBox::Content) => Content,
|
||||
GeometryBox::ShapeBox(ShapeBox::Padding) => Padding,
|
||||
GeometryBox::ShapeBox(ShapeBox::Border) => Border,
|
||||
GeometryBox::ShapeBox(ShapeBox::Margin) => Margin,
|
||||
GeometryBox::Fill => Fill,
|
||||
GeometryBox::Stroke => Stroke,
|
||||
GeometryBox::View => View,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Will panic on NoBox
|
||||
// Ideally these would be implemented on Option<T>,
|
||||
// but coherence doesn't like that and TryFrom isn't stable
|
||||
impl From<StyleClipPathGeometryBox> for GeometryBox {
|
||||
fn from(reference: StyleClipPathGeometryBox) -> Self {
|
||||
use gecko_bindings::structs::StyleClipPathGeometryBox::*;
|
||||
match reference {
|
||||
NoBox => panic!("Shouldn't convert NoBox to GeometryBox"),
|
||||
Content => GeometryBox::ShapeBox(ShapeBox::Content),
|
||||
Padding => GeometryBox::ShapeBox(ShapeBox::Padding),
|
||||
Border => GeometryBox::ShapeBox(ShapeBox::Border),
|
||||
Margin => GeometryBox::ShapeBox(ShapeBox::Margin),
|
||||
Fill => GeometryBox::Fill,
|
||||
Stroke => GeometryBox::Stroke,
|
||||
View => GeometryBox::View,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue