diff options
author | pylbrecht <palbrecht@mailbox.org> | 2019-09-12 21:30:29 +0200 |
---|---|---|
committer | pylbrecht <palbrecht@mailbox.org> | 2019-09-17 16:58:13 +0200 |
commit | 308908ed407909ced9db413388ef0920a13e1475 (patch) | |
tree | 11c923f1f7332a358df2fc3fe951fa3d9ec8ad0d /components/canvas/raqote_backend.rs | |
parent | b8f92937b32dbbec0f749ec5f2220745dcd1dfdd (diff) | |
download | servo-308908ed407909ced9db413388ef0920a13e1475.tar.gz servo-308908ed407909ced9db413388ef0920a13e1475.zip |
Implement LinearGradient and RadialGradient
Diffstat (limited to 'components/canvas/raqote_backend.rs')
-rw-r--r-- | components/canvas/raqote_backend.rs | 106 |
1 files changed, 42 insertions, 64 deletions
diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 3cd19bfd4e9..b8fcd592de0 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -491,68 +491,6 @@ impl GenericPathBuilder for PathBuilder { mut end_angle: f32, anticlockwise: bool, ) { - /* - * Point startPoint(aOrigin.x + cosf(aStartAngle) * aRadius.width, - * aOrigin.y + sinf(aStartAngle) * aRadius.height); - * aSink->LineTo(startPoint); - * // Clockwise we always sweep from the smaller to the larger angle, ccw - * // it's vice versa. - * if (!aAntiClockwise && (aEndAngle < aStartAngle)) { - * Float correction = Float(ceil((aStartAngle - aEndAngle) / (2.0f * M_PI))); - * aEndAngle += float(correction * 2.0f * M_PI); - * } else if (aAntiClockwise && (aStartAngle < aEndAngle)) { - * Float correction = (Float)ceil((aEndAngle - aStartAngle) / (2.0f * M_PI)); - * aStartAngle += float(correction * 2.0f * M_PI); - * } - * // Sweeping more than 2 * pi is a full circle. - * if (!aAntiClockwise && (aEndAngle - aStartAngle > 2 * M_PI)) { - * aEndAngle = float(aStartAngle + 2.0f * M_PI); - * } else if (aAntiClockwise && (aStartAngle - aEndAngle > 2.0f * M_PI)) { - * aEndAngle = float(aStartAngle - 2.0f * M_PI); - * } - * - * // Calculate the total arc we're going to sweep. - * Float arcSweepLeft = fabs(aEndAngle - aStartAngle); - * - * Float sweepDirection = aAntiClockwise ? -1.0f : 1.0f; - * - * Float currentStartAngle = aStartAngle; - * - * while (arcSweepLeft > 0) { - * // We guarantee here the current point is the start point of the next - * // curve segment. - * Float currentEndAngle; - * - * if (arcSweepLeft > M_PI / 2.0f) { - * currentEndAngle = Float(currentStartAngle + M_PI / 2.0f * sweepDirection); - * } else { - * currentEndAngle = currentStartAngle + arcSweepLeft * sweepDirection; - * } - * Point currentStartPoint(aOrigin.x + cosf(currentStartAngle) * aRadius.width, - * aOrigin.y + sinf(currentStartAngle) * aRadius.height); - * Point currentEndPoint(aOrigin.x + cosf(currentEndAngle) * aRadius.width, - * aOrigin.y + sinf(currentEndAngle) * aRadius.height); - * - * // Calculate kappa constant for partial curve. The sign of angle in the - * // tangent will actually ensure this is negative for a counter clockwise - * // sweep, so changing signs later isn't needed. - * Float kappaFactor = (4.0f / 3.0f) * tan((currentEndAngle - currentStartAngle) / 4.0f); - * Float kappaX = kappaFactor * aRadius.width; - * Float kappaY = kappaFactor * aRadius.height; - * - * Point tangentStart(-sin(currentStartAngle), cos(currentStartAngle)); - * Point cp1 = currentStartPoint; - * cp1 += Point(tangentStart.x * kappaX, tangentStart.y * kappaY); - * - * Point revTangentEnd(sin(currentEndAngle), -cos(currentEndAngle)); - * Point cp2 = currentEndPoint; - * cp2 += Point(revTangentEnd.x * kappaX, revTangentEnd.y * kappaY); - * - * aSink->BezierTo(cp1, cp2, currentEndPoint); - * - * arcSweepLeft -= Float(M_PI / 2.0f); - * currentStartAngle = currentEndAngle; - */ let start_point = Point2D::new( origin.x + start_angle.cos() * radius_x, origin.y + end_angle.sin() * radius_y, @@ -689,6 +627,22 @@ pub trait ToRaqoteSource<'a> { fn to_raqote_source(self) -> Option<raqote::Source<'a>>; } +pub trait ToRaqoteGradientStop { + fn to_raqote(&self) -> raqote::GradientStop; +} + +impl ToRaqoteGradientStop for CanvasGradientStop { + fn to_raqote(&self) -> raqote::GradientStop { + let color: u32 = ((self.color.alpha as u32) << 8 * 3 | + (self.color.red as u32) << 8 * 2 | + (self.color.green as u32) << 8 * 1 | + (self.color.blue as u32) << 8 * 0) + .into(); + let position = self.offset as f32; + raqote::GradientStop { position, color } + } +} + impl<'a> ToRaqoteSource<'a> for FillOrStrokeStyle { #[allow(unsafe_code)] fn to_raqote_source(self) -> Option<raqote::Source<'a>> { @@ -701,8 +655,32 @@ impl<'a> ToRaqoteSource<'a> for FillOrStrokeStyle { b: rgba.blue, a: rgba.alpha, })), - LinearGradient(_) => unimplemented!(), - RadialGradient(_) => unimplemented!(), + LinearGradient(style) => { + let stops = style.stops.into_iter().map(|s| s.to_raqote()).collect(); + let gradient = raqote::Gradient { stops }; + let start = Point2D::new(style.x0 as f32, style.y0 as f32); + let end = Point2D::new(style.x1 as f32, style.y1 as f32); + Some(raqote::Source::new_linear_gradient( + gradient, + start, + end, + raqote::Spread::Pad, + )) + }, + RadialGradient(style) => { + let stops = style.stops.into_iter().map(|s| s.to_raqote()).collect(); + let gradient = raqote::Gradient { stops }; + let center1 = Point2D::new(style.x0 as f32, style.y0 as f32); + let center2 = Point2D::new(style.x1 as f32, style.y1 as f32); + Some(raqote::Source::new_two_circle_radial_gradient( + gradient, + center1, + style.r0 as f32, + center2, + style.r1 as f32, + raqote::Spread::Pad, + )) + }, Surface(ref surface) => { let data = &surface.surface_data[..]; Some(raqote::Source::Image( |