This commit is contained in:
Patrick Walton 2019-01-25 17:07:37 -08:00
parent 938bd30a78
commit 80db7155b8
6 changed files with 91 additions and 25 deletions

25
Cargo.lock generated
View File

@ -513,6 +513,7 @@ dependencies = [
"lyon_path 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -880,6 +881,14 @@ name = "slab"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "smallvec"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "strsim"
version = "0.7.0"
@ -993,6 +1002,14 @@ name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unreachable"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "usvg"
version = "0.4.0"
@ -1022,6 +1039,11 @@ name = "version_check"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.6"
@ -1171,6 +1193,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum simplecss 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "135685097a85a64067df36e28a243e94a94f76d829087ce0be34eeb014260c0e"
"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d"
"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15"
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
"checksum svgdom 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a9b53b3ed152fc6b871f7232a8772c640567fd25d056941450637ecba32924d"
"checksum svgtypes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c43c25e6de7264024b5e351eb0c342039eb5acf51f2e9d0099bbd324b661453b"
@ -1183,10 +1206,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1"
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
"checksum usvg 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ebf4d5244ba2e8305caf9de7949377794ecdea5a9e3c84fc5610d78d21f5ee"
"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab"

View File

@ -12,3 +12,4 @@ lyon_geom = "0.12"
lyon_path = "0.12"
serde = "1.0"
serde_derive = "1.0"
smallvec = "0.6"

View File

@ -16,6 +16,7 @@ use crate::simd::F32x4;
use crate::util::lerp;
use euclid::Rect;
use lyon_path::PathEvent;
use smallvec::SmallVec;
use std::mem;
pub struct RectClipper<'a> {
@ -241,26 +242,43 @@ impl Edge {
}
}
pub(crate) struct ContourRectClipper {
clip_rect: Rect<f32>,
pub(crate) struct ContourClipper {
clip_polygon: SmallVec<[Point2DF32; 4]>,
contour: Contour,
}
impl ContourRectClipper {
impl ContourClipper {
#[inline]
pub(crate) fn new(clip_rect: &Rect<f32>, contour: Contour) -> ContourRectClipper {
ContourRectClipper { clip_rect: *clip_rect, contour }
pub(crate) fn new(clip_polygon: &[Point2DF32], contour: Contour) -> ContourClipper {
debug_assert!(!clip_polygon.is_empty());
ContourClipper { clip_polygon: SmallVec::from_slice(clip_polygon), contour }
}
#[inline]
pub(crate) fn from_rect(clip_rect: &Rect<f32>, contour: Contour) -> ContourClipper {
ContourClipper::new(&[
Point2DF32::from_euclid(clip_rect.origin),
Point2DF32::from_euclid(clip_rect.top_right()),
Point2DF32::from_euclid(clip_rect.bottom_right()),
Point2DF32::from_euclid(clip_rect.bottom_left()),
], contour)
}
pub(crate) fn clip(mut self) -> Contour {
if self.clip_rect.contains_rect(&self.contour.bounds()) {
// TODO(pcwalton): Reenable this optimization.
/*if self.clip_rect.contains_rect(&self.contour.bounds()) {
return self.contour
}
}*/
self.clip_against(Edge::left(&self.clip_rect));
self.clip_against(Edge::top(&self.clip_rect));
self.clip_against(Edge::right(&self.clip_rect));
self.clip_against(Edge::bottom(&self.clip_rect));
let clip_polygon = mem::replace(&mut self.clip_polygon, SmallVec::default());
let mut prev = match clip_polygon.last() {
None => return Contour::new(),
Some(prev) => *prev,
};
for &next in &clip_polygon {
self.clip_against(Edge(LineSegmentF32::new(&prev, &next)));
prev = next;
}
/*
let top = Point2DF32::new(lerp(self.clip_rect.origin.x, self.clip_rect.max_x(), 0.5),
@ -399,7 +417,7 @@ impl PolygonClipper3D {
}
}
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug)]
enum Edge3D {
Left,
Right,
@ -413,9 +431,9 @@ impl Edge3D {
#[inline]
fn point_is_inside(self, point: Point3DF32) -> bool {
match self {
Edge3D::Left => point.x() > -1.0, Edge3D::Right => point.x() < 1.0,
Edge3D::Bottom => point.y() > -1.0, Edge3D::Top => point.y() < 1.0,
Edge3D::Near => point.z() > -1.0, Edge3D::Far => point.z() < 1.0,
Edge3D::Left => point.x() >= -1.0, Edge3D::Right => point.x() <= 1.0,
Edge3D::Bottom => point.y() >= -1.0, Edge3D::Top => point.y() <= 1.0,
Edge3D::Near => point.z() >= -1.0, Edge3D::Far => point.z() <= 1.0,
}
}
@ -429,6 +447,6 @@ impl Edge3D {
Edge3D::Left | Edge3D::Bottom | Edge3D::Near => -1.0,
Edge3D::Right | Edge3D::Top | Edge3D::Far => 1.0,
};
prev.lerp(next, (x0 - x) / (x1 - x0))
prev.lerp(next, (x - x0) / (x1 - x0))
}
}

View File

@ -10,7 +10,7 @@
//! A compressed in-memory representation of paths.
use crate::clip::ContourRectClipper;
use crate::clip::ContourClipper;
use crate::line_segment::LineSegmentF32;
use crate::monotonic::MonotonicConversionIter;
use crate::point::Point2DF32;
@ -123,9 +123,18 @@ impl Outline {
self.contours.push(contour);
}
pub fn clip_against_polygon(&mut self, clip_polygon: &[Point2DF32]) {
for contour in mem::replace(&mut self.contours, vec![]) {
let contour = ContourClipper::new(clip_polygon, contour).clip();
if !contour.is_empty() {
self.push_contour(contour);
}
}
}
pub fn clip_against_rect(&mut self, clip_rect: &Rect<f32>) {
for contour in mem::replace(&mut self.contours, vec![]) {
let contour = ContourRectClipper::new(clip_rect, contour).clip();
let contour = ContourClipper::from_rect(clip_rect, contour).clip();
if !contour.is_empty() {
self.push_contour(contour);
}

View File

@ -179,6 +179,11 @@ impl Transform3DF32 {
Point4DF32(term0 + term1 + term2 + term3)
}
#[inline]
pub fn transform_point_3d(&self, point: Point3DF32) -> Point3DF32 {
self.transform_point(point.to_4d()).perspective_divide()
}
#[inline]
pub fn upper_left(&self) -> Matrix2x2F32 {
Matrix2x2F32(self.c0.combine_axaybxby(self.c1))
@ -200,6 +205,9 @@ impl Transform3DF32 {
}
// https://en.wikipedia.org/wiki/Invertible_matrix#Blockwise_inversion
//
// If A is the upper left submatrix of this matrix, this method assumes that A and the Schur
// complement of A are invertible.
pub fn inverse(&self) -> Transform3DF32 {
// Extract submatrices.
let (a, b) = (self.upper_left(), self.upper_right());
@ -263,11 +271,6 @@ impl Perspective {
(point + Point2DF32::splat(1.0)) * size_scale
}
#[inline]
pub fn transform_point_3d(&self, point: &Point3DF32) -> Point3DF32 {
self.transform.transform_point(point.to_4d()).perspective_divide()
}
// TODO(pcwalton): SIMD?
#[inline]
pub fn transform_rect(&self, rect: &Rect<f32>) -> Rect<f32> {

View File

@ -120,10 +120,16 @@ impl Scene {
pub fn apply_perspective(&mut self, perspective: &Perspective) {
let quad = self.clip_bounding_quad_with_perspective(perspective);
println!("bounds={:?} quad={:?}", self.bounds, quad);
println!("bounds={:?} PRE-transform quad={:?}", self.bounds, quad);
let inverse_transform = perspective.transform.inverse();
let quad: Vec<_> = quad.into_iter().map(|point| {
inverse_transform.transform_point_3d(point).to_2d()
}).collect();
println!("bounds={:?} POST-transform quad={:?}", self.bounds, quad);
let mut bounds = Rect::zero();
for (object_index, object) in self.objects.iter_mut().enumerate() {
object.outline.clip_against_polygon(&quad);
object.outline.apply_perspective(perspective);
object.outline.clip_against_rect(&self.view_box);
@ -145,9 +151,13 @@ impl Scene {
Point3DF32::from_euclid_2d(&self.bounds.bottom_right()),
Point3DF32::from_euclid_2d(&self.bounds.bottom_left()),
];
println!("-----");
println!("bounds={:?} ORIGINAL quad={:?}", self.bounds, points);
for point in &mut points {
*point = perspective.transform_point_3d(point);
*point = perspective.transform.transform_point_3d(*point);
}
println!("PERSPECTIVE quad={:?}", points);
//points
PolygonClipper3D::new(points).clip()
}
}