2019-04-30 22:13:28 -04:00
|
|
|
// pathfinder/renderer/src/options.rs
|
|
|
|
//
|
|
|
|
// Copyright © 2019 The Pathfinder Project Developers.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
|
|
|
//! Options that control how rendering is to be performed.
|
|
|
|
|
|
|
|
use crate::gpu_data::RenderCommand;
|
2019-06-21 13:06:19 -04:00
|
|
|
use pathfinder_geometry::rect::RectF;
|
|
|
|
use pathfinder_geometry::transform2d::Transform2DF;
|
|
|
|
use pathfinder_geometry::transform3d::Perspective;
|
|
|
|
use pathfinder_geometry::vector::{Vector2F, Vector4F};
|
|
|
|
use pathfinder_content::clip::PolygonClipper3D;
|
2019-04-30 22:13:28 -04:00
|
|
|
|
|
|
|
pub trait RenderCommandListener: Send + Sync {
|
|
|
|
fn send(&self, command: RenderCommand);
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> RenderCommandListener for F
|
|
|
|
where
|
|
|
|
F: Fn(RenderCommand) + Send + Sync,
|
|
|
|
{
|
|
|
|
#[inline]
|
|
|
|
fn send(&self, command: RenderCommand) {
|
|
|
|
(*self)(command)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-05 17:35:46 -04:00
|
|
|
/// Options that influence scene building.
|
2019-04-30 22:13:28 -04:00
|
|
|
#[derive(Clone, Default)]
|
2019-06-05 17:35:46 -04:00
|
|
|
pub struct BuildOptions {
|
2019-04-30 22:13:28 -04:00
|
|
|
pub transform: RenderTransform,
|
2019-06-03 15:39:29 -04:00
|
|
|
pub dilation: Vector2F,
|
2019-04-30 22:13:28 -04:00
|
|
|
pub subpixel_aa_enabled: bool,
|
|
|
|
}
|
|
|
|
|
2019-06-05 17:35:46 -04:00
|
|
|
impl BuildOptions {
|
|
|
|
pub(crate) fn prepare(self, bounds: RectF) -> PreparedBuildOptions {
|
|
|
|
PreparedBuildOptions {
|
2019-04-30 22:13:28 -04:00
|
|
|
transform: self.transform.prepare(bounds),
|
|
|
|
dilation: self.dilation,
|
|
|
|
subpixel_aa_enabled: self.subpixel_aa_enabled,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub enum RenderTransform {
|
2019-05-29 22:13:42 -04:00
|
|
|
Transform2D(Transform2DF),
|
2019-04-30 22:13:28 -04:00
|
|
|
Perspective(Perspective),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for RenderTransform {
|
|
|
|
#[inline]
|
|
|
|
fn default() -> RenderTransform {
|
2019-05-29 22:13:42 -04:00
|
|
|
RenderTransform::Transform2D(Transform2DF::default())
|
2019-04-30 22:13:28 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl RenderTransform {
|
2019-05-29 22:13:42 -04:00
|
|
|
fn prepare(&self, bounds: RectF) -> PreparedRenderTransform {
|
2019-04-30 22:13:28 -04:00
|
|
|
let perspective = match self {
|
|
|
|
RenderTransform::Transform2D(ref transform) => {
|
|
|
|
if transform.is_identity() {
|
|
|
|
return PreparedRenderTransform::None;
|
|
|
|
}
|
|
|
|
return PreparedRenderTransform::Transform2D(*transform);
|
|
|
|
}
|
|
|
|
RenderTransform::Perspective(ref perspective) => *perspective,
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut points = vec![
|
|
|
|
bounds.origin().to_3d(),
|
|
|
|
bounds.upper_right().to_3d(),
|
|
|
|
bounds.lower_right().to_3d(),
|
|
|
|
bounds.lower_left().to_3d(),
|
|
|
|
];
|
|
|
|
debug!("-----");
|
|
|
|
debug!("bounds={:?} ORIGINAL quad={:?}", bounds, points);
|
|
|
|
for point in &mut points {
|
|
|
|
*point = perspective.transform.transform_point(*point);
|
|
|
|
}
|
|
|
|
debug!("... PERSPECTIVE quad={:?}", points);
|
|
|
|
|
|
|
|
// Compute depth.
|
|
|
|
let quad = [
|
|
|
|
points[0].perspective_divide(),
|
|
|
|
points[1].perspective_divide(),
|
|
|
|
points[2].perspective_divide(),
|
|
|
|
points[3].perspective_divide(),
|
|
|
|
];
|
|
|
|
debug!("... PERSPECTIVE-DIVIDED points = {:?}", quad);
|
|
|
|
|
|
|
|
points = PolygonClipper3D::new(points).clip();
|
|
|
|
debug!("... CLIPPED quad={:?}", points);
|
|
|
|
for point in &mut points {
|
|
|
|
*point = point.perspective_divide()
|
|
|
|
}
|
|
|
|
|
|
|
|
let inverse_transform = perspective.transform.inverse();
|
|
|
|
let clip_polygon = points
|
|
|
|
.into_iter()
|
|
|
|
.map(|point| {
|
|
|
|
inverse_transform
|
|
|
|
.transform_point(point)
|
|
|
|
.perspective_divide()
|
|
|
|
.to_2d()
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
return PreparedRenderTransform::Perspective {
|
|
|
|
perspective,
|
|
|
|
clip_polygon,
|
|
|
|
quad,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-05 17:35:46 -04:00
|
|
|
pub(crate) struct PreparedBuildOptions {
|
2019-05-03 15:35:19 -04:00
|
|
|
pub(crate) transform: PreparedRenderTransform,
|
2019-06-03 15:39:29 -04:00
|
|
|
pub(crate) dilation: Vector2F,
|
2019-05-03 15:35:19 -04:00
|
|
|
pub(crate) subpixel_aa_enabled: bool,
|
2019-04-30 22:13:28 -04:00
|
|
|
}
|
|
|
|
|
2019-06-05 17:35:46 -04:00
|
|
|
impl PreparedBuildOptions {
|
2019-04-30 22:13:28 -04:00
|
|
|
#[inline]
|
2019-05-03 15:35:19 -04:00
|
|
|
pub(crate) fn bounding_quad(&self) -> BoundingQuad {
|
2019-04-30 22:13:28 -04:00
|
|
|
match self.transform {
|
|
|
|
PreparedRenderTransform::Perspective { quad, .. } => quad,
|
2019-06-03 15:39:29 -04:00
|
|
|
_ => [Vector4F::default(); 4],
|
2019-04-30 22:13:28 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-03 15:39:29 -04:00
|
|
|
pub(crate) type BoundingQuad = [Vector4F; 4];
|
2019-04-30 22:13:28 -04:00
|
|
|
|
2019-05-03 15:35:19 -04:00
|
|
|
pub(crate) enum PreparedRenderTransform {
|
2019-04-30 22:13:28 -04:00
|
|
|
None,
|
2019-05-29 22:13:42 -04:00
|
|
|
Transform2D(Transform2DF),
|
2019-04-30 22:13:28 -04:00
|
|
|
Perspective {
|
|
|
|
perspective: Perspective,
|
2019-06-03 15:39:29 -04:00
|
|
|
clip_polygon: Vec<Vector2F>,
|
|
|
|
quad: [Vector4F; 4],
|
2019-04-30 22:13:28 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PreparedRenderTransform {
|
|
|
|
#[inline]
|
2019-05-03 15:35:19 -04:00
|
|
|
pub(crate) fn is_2d(&self) -> bool {
|
2019-04-30 22:13:28 -04:00
|
|
|
match *self {
|
|
|
|
PreparedRenderTransform::Transform2D(_) => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|