Always store a transform in PathBuilderRef.

This commit is contained in:
Josh Matthews 2019-02-06 19:17:35 -05:00
parent 53ae73bdec
commit 2c5a6ebc53

View file

@ -62,23 +62,17 @@ impl PathState {
/// applied to any points to ensure they are in the matching device space. /// applied to any points to ensure they are in the matching device space.
struct PathBuilderRef<'a> { struct PathBuilderRef<'a> {
builder: &'a PathBuilder, builder: &'a PathBuilder,
transform: Option<Transform2D<AzFloat>>, transform: Transform2D<AzFloat>,
} }
impl<'a> PathBuilderRef<'a> { impl<'a> PathBuilderRef<'a> {
fn line_to(&self, pt: &Point2D<AzFloat>) { fn line_to(&self, pt: &Point2D<AzFloat>) {
let pt = match self.transform { let pt = self.transform.transform_point(pt);
Some(ref t) => t.transform_point(pt),
None => *pt,
};
self.builder.line_to(pt); self.builder.line_to(pt);
} }
fn move_to(&self, pt: &Point2D<AzFloat>) { fn move_to(&self, pt: &Point2D<AzFloat>) {
let pt = match self.transform { let pt = self.transform.transform_point(pt);
Some(ref t) => t.transform_point(pt),
None => *pt,
};
self.builder.move_to(pt); self.builder.move_to(pt);
} }
@ -88,32 +82,18 @@ impl<'a> PathBuilderRef<'a> {
Point2D::new(rect.origin.x + rect.size.width, rect.origin.y), Point2D::new(rect.origin.x + rect.size.width, rect.origin.y),
Point2D::new(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height), Point2D::new(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height),
Point2D::new(rect.origin.x, rect.origin.y + rect.size.height)); Point2D::new(rect.origin.x, rect.origin.y + rect.size.height));
let (first, second, third, fourth) = match self.transform { self.builder.move_to(self.transform.transform_point(&first));
Some(ref t) => self.builder.line_to(self.transform.transform_point(&second));
(t.transform_point(&first), self.builder.line_to(self.transform.transform_point(&third));
t.transform_point(&second), self.builder.line_to(self.transform.transform_point(&fourth));
t.transform_point(&third),
t.transform_point(&fourth)),
None => (first, second, third, fourth),
};
self.builder.move_to(first);
self.builder.line_to(second);
self.builder.line_to(third);
self.builder.line_to(fourth);
self.builder.close(); self.builder.close();
} }
fn quadratic_curve_to(&self, cp: &Point2D<AzFloat>, endpoint: &Point2D<AzFloat>) { fn quadratic_curve_to(&self, cp: &Point2D<AzFloat>, endpoint: &Point2D<AzFloat>) {
let (cp2, endpoint2); self.builder.quadratic_curve_to(
let (cp, endpoint) = match self.transform { &self.transform.transform_point(cp),
Some(ref t) => { &self.transform.transform_point(endpoint),
cp2 = t.transform_point(cp); )
endpoint2 = t.transform_point(endpoint);
(&cp2, &endpoint2)
}
None => (cp, endpoint),
};
self.builder.quadratic_curve_to(cp, endpoint)
} }
fn bezier_curve_to( fn bezier_curve_to(
@ -122,17 +102,11 @@ impl<'a> PathBuilderRef<'a> {
cp2: &Point2D<AzFloat>, cp2: &Point2D<AzFloat>,
endpoint: &Point2D<AzFloat> endpoint: &Point2D<AzFloat>
) { ) {
let (cp1_t, cp2_t, endpoint_t); self.builder.bezier_curve_to(
let (cp1, cp2, endpoint) = match self.transform { &self.transform.transform_point(cp1),
Some(ref t) => { &self.transform.transform_point(cp2),
cp1_t = t.transform_point(cp1); &self.transform.transform_point(endpoint),
cp2_t = t.transform_point(cp2); )
endpoint_t = t.transform_point(endpoint);
(&cp1_t, &cp2_t, &endpoint_t)
}
None => (cp1, cp2, endpoint),
};
self.builder.bezier_curve_to(cp1, cp2, endpoint)
} }
fn arc( fn arc(
@ -143,10 +117,7 @@ impl<'a> PathBuilderRef<'a> {
end_angle: AzFloat, end_angle: AzFloat,
ccw: bool ccw: bool
) { ) {
let center = match self.transform { let center = self.transform.transform_point(center);
Some(ref t) => t.transform_point(center),
None => *center,
};
self.builder.arc(center, radius, start_angle, end_angle, ccw); self.builder.arc(center, radius, start_angle, end_angle, ccw);
} }
@ -160,28 +131,17 @@ impl<'a> PathBuilderRef<'a> {
end_angle: AzFloat, end_angle: AzFloat,
ccw: bool ccw: bool
) { ) {
let center = match self.transform { let center = self.transform.transform_point(center);
Some(ref t) => t.transform_point(center),
None => *center,
};
self.builder.ellipse(center, radius_x, radius_y, rotation_angle, start_angle, end_angle, ccw); self.builder.ellipse(center, radius_x, radius_y, rotation_angle, start_angle, end_angle, ccw);
} }
fn current_point(&self) -> Option<Point2D<AzFloat>> { fn current_point(&self) -> Option<Point2D<AzFloat>> {
match self.transform { let inverse = match self.transform.inverse() {
Some(ref t) => { Some(i) => i,
let inverse = match t.inverse() { None => return None,
Some(i) => i, };
None => return None, let current_point = self.builder.get_current_point();
}; Some(inverse.transform_point(&Point2D::new(current_point.x, current_point.y)))
let current_point = self.builder.get_current_point();
Some(inverse.transform_point(&Point2D::new(current_point.x, current_point.y)))
}
None => {
let current = self.builder.get_current_point();
Some(Point2D::new(current.x, current.y))
}
}
} }
} }
@ -535,12 +495,12 @@ impl<'a> CanvasData<'a> {
&PathState::UserSpacePathBuilder(ref builder, None) => &PathState::UserSpacePathBuilder(ref builder, None) =>
return PathBuilderRef { return PathBuilderRef {
builder, builder,
transform: None, transform: Transform2D::identity(),
}, },
&PathState::DeviceSpacePathBuilder(ref builder) => &PathState::DeviceSpacePathBuilder(ref builder) =>
return PathBuilderRef { return PathBuilderRef {
builder, builder,
transform: Some(self.drawtarget.get_transform()), transform: self.drawtarget.get_transform(),
}, },
_ => unreachable!(), _ => unreachable!(),
} }
@ -550,12 +510,12 @@ impl<'a> CanvasData<'a> {
&PathState::UserSpacePathBuilder(ref builder, None) => &PathState::UserSpacePathBuilder(ref builder, None) =>
PathBuilderRef { PathBuilderRef {
builder, builder,
transform: None, transform: Transform2D::identity(),
}, },
&PathState::DeviceSpacePathBuilder(ref builder) => &PathState::DeviceSpacePathBuilder(ref builder) =>
PathBuilderRef { PathBuilderRef {
builder, builder,
transform: Some(self.drawtarget.get_transform()), transform: self.drawtarget.get_transform(),
}, },
&PathState::UserSpacePathBuilder(..) | &PathState::UserSpacePathBuilder(..) |
&PathState::UserSpacePath(..) => &PathState::UserSpacePath(..) =>