Split out B-vertex positions and info so that they're easier to pack into textures

This commit is contained in:
Patrick Walton 2017-08-11 15:56:07 -07:00
parent fa1b2390c7
commit 57ebbf8281
6 changed files with 141 additions and 111 deletions

View File

@ -14,11 +14,13 @@ class PathfinderMeshes {
if (!('Ok' in response))
throw new Error("Failed to partition the font!");
const meshes = response.Ok;
this.bQuads = base64js.toByteArray(meshes.bQuads);
this.bQuadPositions = base64js.toByteArray(meshes.bQuadPositions);
this.bQuadInfo = base64js.toByteArray(meshes.bQuadInfo);
this.bVertices = base64js.toByteArray(meshes.bVertices);
}
bQuads: ArrayBuffer;
bQuadPositions: ArrayBuffer;
bQuadInfo: ArrayBuffer;
bVertices: ArrayBuffer;
}

View File

@ -121,8 +121,10 @@ struct PartitionFontResponse {
glyphInfo: Vec<PartitionGlyphInfo>,
// Base64-encoded `bincode`-encoded `BQuad`s.
bQuads: String,
// Base64-encoded `bincode`-encoded `BVertex`es.
bVertices: String,
// Base64-encoded `bincode`-encoded `Point2D<f32>`s.
bVertexPositions: String,
// Base64-encoded `bincode`-encoded `BVertexInfo`s.
bVertexInfo: String,
coverInteriorIndices: Vec<u32>,
coverCurveIndices: Vec<u32>,
// Base64-encoded `bincode`-encoded `LineIndices` instances.
@ -195,7 +197,7 @@ fn partition_font(request: Json<PartitionFontRequest>)
// Partition the decoded glyph outlines.
let mut partitioner = Partitioner::new();
let (mut b_quads, mut b_vertices) = (vec![], vec![]);
let (mut b_quads, mut b_vertex_positions, mut b_vertex_info) = (vec![], vec![], vec![]);
let (mut cover_interior_indices, mut cover_curve_indices) = (vec![], vec![]);
let (mut edge_upper_line_indices, mut edge_upper_curve_indices) = (vec![], vec![]);
let (mut edge_lower_line_indices, mut edge_lower_curve_indices) = (vec![], vec![]);
@ -228,18 +230,23 @@ fn partition_font(request: Json<PartitionFontRequest>)
decoded_outline_indices.subpath_indices.start as u32,
decoded_outline_indices.subpath_indices.end as u32);
let (path_b_quads, path_b_vertices) = (partitioner.b_quads(), partitioner.b_vertices());
let path_b_quads = partitioner.b_quads();
let path_b_vertex_positions = partitioner.b_vertex_positions();
let path_b_vertex_info = partitioner.b_vertex_info();
let cover_indices = partitioner.cover_indices();
let edge_indices = partitioner.edge_indices();
IndexRange::from_vector_append_and_serialization(&mut b_vertex_positions,
path_b_vertex_positions).unwrap();
glyph_info.push(PartitionGlyphInfo {
id: glyph_id,
dimensions: dimensions,
bQuadIndices: IndexRange::from_vector_append_and_serialization(&mut b_quads,
path_b_quads).unwrap(),
bVertexIndices:
IndexRange::from_vector_append_and_serialization(&mut b_vertices,
path_b_vertices).unwrap(),
IndexRange::from_vector_append_and_serialization(&mut b_vertex_info,
path_b_vertex_info).unwrap(),
coverInteriorIndices:
IndexRange::from_vector_append_operation(&mut cover_interior_indices,
cover_indices.interior_indices),
@ -265,7 +272,8 @@ fn partition_font(request: Json<PartitionFontRequest>)
Json(Ok(PartitionFontResponse {
glyphInfo: glyph_info,
bQuads: base64::encode(&b_quads),
bVertices: base64::encode(&b_vertices),
bVertexPositions: base64::encode(&b_vertex_positions),
bVertexInfo: base64::encode(&b_vertex_info),
coverInteriorIndices: cover_interior_indices,
coverCurveIndices: cover_curve_indices,
edgeUpperLineIndices: base64::encode(&edge_upper_line_indices),

View File

@ -6,7 +6,7 @@ use legalizer::Legalizer;
use partitioner::Partitioner;
use std::mem;
use std::slice;
use {BQuad, BVertex, CurveIndices, Endpoint, LineIndices, Subpath};
use {BQuad, BVertexInfo, CurveIndices, Endpoint, LineIndices, Subpath};
#[derive(Clone, Copy)]
#[repr(C)]
@ -184,15 +184,25 @@ pub unsafe extern fn pf_partitioner_b_quads<'a>(partitioner: *const Partitioner<
}
#[no_mangle]
pub unsafe extern fn pf_partitioner_b_vertices<'a>(partitioner: *const Partitioner<'a>,
out_b_vertex_count: *mut u32)
-> *const BVertex {
// FIXME(pcwalton): This is unsafe! `Point2D<f32>` and `Point2DF32` may have different layouts!
let b_vertices = (*partitioner).b_vertices();
pub unsafe extern fn pf_partitioner_b_vertex_positions<'a>(partitioner: *const Partitioner<'a>,
out_b_vertex_count: *mut u32)
-> *const Point2D<f32> {
let b_vertex_positions = (*partitioner).b_vertex_positions();
if !out_b_vertex_count.is_null() {
*out_b_vertex_count = b_vertices.len() as u32
*out_b_vertex_count = b_vertex_positions.len() as u32
}
b_vertices.as_ptr() as *const BVertex
b_vertex_positions.as_ptr() as *const Point2D<f32>
}
#[no_mangle]
pub unsafe extern fn pf_partitioner_b_vertex_info<'a>(partitioner: *const Partitioner<'a>,
out_b_vertex_count: *mut u32)
-> *const BVertexInfo {
let b_vertex_info = (*partitioner).b_vertex_info();
if !out_b_vertex_count.is_null() {
*out_b_vertex_count = b_vertex_info.len() as u32
}
b_vertex_info.as_ptr() as *const BVertexInfo
}
#[no_mangle]

View File

@ -91,24 +91,22 @@ pub enum BVertexKind {
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
#[repr(C)]
pub struct BVertex {
pub position: Point2D<f32>,
pub struct BVertexInfo {
pub path_id: u32,
pub tex_coord: [u8; 2],
pub kind: BVertexKind,
pad: u8,
}
impl BVertex {
impl BVertexInfo {
#[inline]
pub fn new(position: &Point2D<f32>, kind: BVertexKind, path_id: u32) -> BVertex {
pub fn new(kind: BVertexKind, path_id: u32) -> BVertexInfo {
let tex_coord = match kind {
BVertexKind::Endpoint0 => [0, 0],
BVertexKind::Endpoint1 => [2, 2],
BVertexKind::ConcaveControlPoint | BVertexKind::ConvexControlPoint => [1, 0],
};
BVertex {
position: *position,
BVertexInfo {
path_id: path_id,
tex_coord: tex_coord,
kind: kind,
@ -121,7 +119,7 @@ impl BVertex {
right_endpoint_position: &Point2D<f32>,
path_id: u32,
bottom: bool)
-> BVertex {
-> BVertexInfo {
let control_point_vector = *control_point_position - *left_endpoint_position;
let right_vector = *right_endpoint_position - *left_endpoint_position;
let determinant = right_vector.cross(control_point_vector);
@ -130,7 +128,7 @@ impl BVertex {
} else {
BVertexKind::ConcaveControlPoint
};
BVertex::new(control_point_position, endpoint_kind, path_id)
BVertexInfo::new(endpoint_kind, path_id)
}
}

View File

@ -37,15 +37,14 @@ struct pf_matrix2d_f32 {
typedef struct pf_matrix2d_f32 pf_matrix2d_f32_t;
struct pf_b_vertex {
pf_point2d_f32_t position;
struct pf_b_vertex_info {
uint32_t path_id;
uint8_t tex_coord[2];
pf_b_vertex_kind_t kind;
uint8_t pad;
};
typedef struct pf_b_vertex pf_b_vertex_t;
typedef struct pf_b_vertex_info pf_b_vertex_info_t;
struct pf_cover_indices {
const uint32_t *interior_indices;
@ -169,8 +168,11 @@ void pf_partitioner_partition(pf_partitioner_t *partitioner,
const pf_b_quad_t *pf_partitioner_b_quads(const pf_partitioner_t *partitioner,
uint32_t *out_b_quad_count);
const pf_b_vertex_t *pf_partitioner_b_vertices(const pf_partitioner_t *partitioner,
uint32_t *out_b_vertex_count);
const pf_point2d_f32_t *pf_partitioner_b_vertex_positions(const pf_partitioner_t *partitioner,
uint32_t *out_b_vertex_count);
const pf_b_vertex_info_t *pf_partitioner_b_vertex_info(const pf_partitioner_t *partitioner,
uint32_t *out_b_vertex_count);
const void pf_partitioner_cover_indices(const pf_partitioner_t *partitioner,
pf_cover_indices_t *out_cover_indices);

View File

@ -8,7 +8,7 @@ use std::collections::BinaryHeap;
use std::cmp::Ordering;
use std::f32;
use std::u32;
use {BQuad, BVertex, BVertexKind, CurveIndices, Endpoint, LineIndices, Subpath};
use {BQuad, BVertexInfo, BVertexKind, CurveIndices, Endpoint, LineIndices, Subpath};
pub struct Partitioner<'a> {
endpoints: &'a [Endpoint],
@ -16,7 +16,8 @@ pub struct Partitioner<'a> {
subpaths: &'a [Subpath],
b_quads: Vec<BQuad>,
b_vertices: Vec<BVertex>,
b_vertex_positions: Vec<Point2D<f32>>,
b_vertex_info: Vec<BVertexInfo>,
cover_indices: CoverIndicesBuffer,
edge_indices: EdgeIndicesBuffer,
@ -35,7 +36,8 @@ impl<'a> Partitioner<'a> {
subpaths: &[],
b_quads: vec![],
b_vertices: vec![],
b_vertex_positions: vec![],
b_vertex_info: vec![],
cover_indices: CoverIndicesBuffer::new(),
edge_indices: EdgeIndicesBuffer::new(),
@ -61,7 +63,8 @@ impl<'a> Partitioner<'a> {
pub fn partition(&mut self, path_id: u32, first_subpath_index: u32, last_subpath_index: u32) {
self.b_quads.clear();
self.b_vertices.clear();
self.b_vertex_info.clear();
self.b_vertex_positions.clear();
self.cover_indices.clear();
self.edge_indices.clear();
self.heap.clear();
@ -80,8 +83,13 @@ impl<'a> Partitioner<'a> {
}
#[inline]
pub fn b_vertices(&self) -> &[BVertex] {
&self.b_vertices
pub fn b_vertex_positions(&self) -> &[Point2D<f32>] {
&self.b_vertex_positions
}
#[inline]
pub fn b_vertex_info(&self) -> &[BVertexInfo] {
&self.b_vertex_info
}
#[inline]
@ -172,13 +180,13 @@ impl<'a> Partitioner<'a> {
{
let active_edge = &mut self.active_edges[active_edge_index as usize];
active_edge.left_vertex_index = self.b_vertices.len() as u32;
active_edge.left_vertex_index = self.b_vertex_info.len() as u32;
active_edge.control_point_vertex_index = active_edge.left_vertex_index + 1;
let endpoint_position = self.endpoints[active_edge.right_endpoint_index as usize]
.position;
self.b_vertices
.push(BVertex::new(&endpoint_position, active_edge.endpoint_kind(), self.path_id));
self.b_vertex_positions.push(endpoint_position);
self.b_vertex_info.push(BVertexInfo::new(active_edge.endpoint_kind(), self.path_id));
active_edge.toggle_parity();
@ -206,18 +214,19 @@ impl<'a> Partitioner<'a> {
}
control_point_index => {
self.active_edges[active_edge_index as usize].control_point_vertex_index =
self.b_vertices.len() as u32;
self.b_vertex_info.len() as u32;
let left_vertex_index = self.active_edges[active_edge_index as usize]
.left_vertex_index;
let control_point_position = &self.control_points[control_point_index as usize];
let control_point_b_vertex =
BVertex::control_point(&self.b_vertices[left_vertex_index as usize].position,
&control_point_position,
&new_point.position,
self.path_id,
bottom);
self.b_vertices.push(control_point_b_vertex)
let control_point_b_vertex_info = BVertexInfo::control_point(
&self.b_vertex_positions[left_vertex_index as usize],
&control_point_position,
&new_point.position,
self.path_id,
bottom);
self.b_vertex_positions.push(*control_point_position);
self.b_vertex_info.push(control_point_b_vertex_info);
}
}
}
@ -271,12 +280,13 @@ impl<'a> Partitioner<'a> {
let new_active_edges = &mut self.active_edges[next_active_edge_index as usize..
next_active_edge_index as usize + 2];
let left_vertex_index = self.b_vertices.len() as u32;
let left_vertex_index = self.b_vertex_info.len() as u32;
new_active_edges[0].left_vertex_index = left_vertex_index;
new_active_edges[1].left_vertex_index = left_vertex_index;
let position = self.endpoints[endpoint_index as usize].position;
self.b_vertices.push(BVertex::new(&position, BVertexKind::Endpoint0, self.path_id));
self.b_vertex_positions.push(position);
self.b_vertex_info.push(BVertexInfo::new(BVertexKind::Endpoint0, self.path_id));
new_active_edges[0].toggle_parity();
new_active_edges[1].toggle_parity();
@ -312,36 +322,40 @@ impl<'a> Partitioner<'a> {
match upper_control_point_index {
u32::MAX => new_active_edges[0].control_point_vertex_index = u32::MAX,
upper_control_point_index => {
new_active_edges[0].control_point_vertex_index = self.b_vertices.len() as u32;
new_active_edges[0].control_point_vertex_index = self.b_vertex_info.len() as u32;
let control_point_position =
self.control_points[upper_control_point_index as usize];
let right_vertex_position =
self.endpoints[new_active_edges[0].right_endpoint_index as usize].position;
let control_point_b_vertex = BVertex::control_point(&position,
&control_point_position,
&right_vertex_position,
self.path_id,
false);
self.b_vertices.push(control_point_b_vertex)
let control_point_b_vertex_info =
BVertexInfo::control_point(&position,
&control_point_position,
&right_vertex_position,
self.path_id,
false);
self.b_vertex_positions.push(control_point_position);
self.b_vertex_info.push(control_point_b_vertex_info);
}
}
match lower_control_point_index {
u32::MAX => new_active_edges[1].control_point_vertex_index = u32::MAX,
lower_control_point_index => {
new_active_edges[1].control_point_vertex_index = self.b_vertices.len() as u32;
new_active_edges[1].control_point_vertex_index = self.b_vertex_info.len() as u32;
let control_point_position =
self.control_points[lower_control_point_index as usize];
let right_vertex_position =
self.endpoints[new_active_edges[1].right_endpoint_index as usize].position;
let control_point_b_vertex = BVertex::control_point(&position,
&control_point_position,
&right_vertex_position,
self.path_id,
true);
self.b_vertices.push(control_point_b_vertex)
let control_point_b_vertex_info =
BVertexInfo::control_point(&position,
&control_point_position,
&right_vertex_position,
self.path_id,
true);
self.b_vertex_positions.push(control_point_position);
self.b_vertex_info.push(control_point_b_vertex_info);
}
}
}
@ -419,8 +433,8 @@ impl<'a> Partitioner<'a> {
// NB: Order is important here—we depend on the provoking vertex!
let upper_shape = upper_curve.shape(&self.b_vertices);
let lower_shape = lower_curve.shape(&self.b_vertices);
let upper_shape = upper_curve.shape(&self.b_vertex_info);
let lower_shape = lower_curve.shape(&self.b_vertex_info);
match upper_shape {
Shape::Flat => {
@ -627,8 +641,8 @@ impl<'a> Partitioner<'a> {
}
fn solve_active_edge_t_for_x(&self, x: f32, active_edge: &ActiveEdge) -> f32 {
let left_vertex_position = &self.b_vertices[active_edge.left_vertex_index as usize]
.position;
let left_vertex_position = &self.b_vertex_positions[active_edge.left_vertex_index as
usize];
let right_endpoint_position = &self.endpoints[active_edge.right_endpoint_index as usize]
.position;
match active_edge.control_point_vertex_index {
@ -636,7 +650,7 @@ impl<'a> Partitioner<'a> {
geometry::solve_line_t_for_x(x, left_vertex_position, right_endpoint_position)
}
control_point_vertex_index => {
let control_point = &self.b_vertices[control_point_vertex_index as usize].position;
let control_point = &self.b_vertex_positions[control_point_vertex_index as usize];
geometry::solve_quadratic_bezier_t_for_x(x,
left_vertex_position,
control_point,
@ -650,8 +664,8 @@ impl<'a> Partitioner<'a> {
}
fn sample_active_edge(&self, t: f32, active_edge: &ActiveEdge) -> Point2D<f32> {
let left_vertex_position = &self.b_vertices[active_edge.left_vertex_index as usize]
.position;
let left_vertex_position = &self.b_vertex_positions[active_edge.left_vertex_index as
usize];
let right_endpoint_position = &self.endpoints[active_edge.right_endpoint_index as usize]
.position;
match active_edge.control_point_vertex_index {
@ -661,7 +675,7 @@ impl<'a> Partitioner<'a> {
.to_point()
}
control_point_vertex_index => {
let control_point = &self.b_vertices[control_point_vertex_index as usize].position;
let control_point = &self.b_vertex_positions[control_point_vertex_index as usize];
geometry::sample_quadratic_bezier(t,
left_vertex_position,
control_point,
@ -682,11 +696,11 @@ impl<'a> Partitioner<'a> {
}
let upper_left_vertex_position =
&self.b_vertices[upper_active_edge.left_vertex_index as usize].position;
&self.b_vertex_positions[upper_active_edge.left_vertex_index as usize];
let upper_right_endpoint_position =
&self.endpoints[upper_active_edge.right_endpoint_index as usize].position;
let lower_left_vertex_position =
&self.b_vertices[lower_active_edge.left_vertex_index as usize].position;
&self.b_vertex_positions[lower_active_edge.left_vertex_index as usize];
let lower_right_endpoint_position =
&self.endpoints[lower_active_edge.right_endpoint_index as usize].position;
@ -700,7 +714,7 @@ impl<'a> Partitioner<'a> {
}
(upper_control_point_vertex_index, u32::MAX) => {
let upper_control_point =
&self.b_vertices[upper_control_point_vertex_index as usize].position;
&self.b_vertex_positions[upper_control_point_vertex_index as usize];
geometry::line_quadratic_bezier_crossing_point(lower_left_vertex_position,
lower_right_endpoint_position,
upper_left_vertex_position,
@ -709,7 +723,7 @@ impl<'a> Partitioner<'a> {
}
(u32::MAX, lower_control_point_vertex_index) => {
let lower_control_point =
&self.b_vertices[lower_control_point_vertex_index as usize].position;
&self.b_vertex_positions[lower_control_point_vertex_index as usize];
geometry::line_quadratic_bezier_crossing_point(upper_left_vertex_position,
upper_right_endpoint_position,
lower_left_vertex_position,
@ -718,9 +732,9 @@ impl<'a> Partitioner<'a> {
}
(upper_control_point_vertex_index, lower_control_point_vertex_index) => {
let upper_control_point =
&self.b_vertices[upper_control_point_vertex_index as usize].position;
&self.b_vertex_positions[upper_control_point_vertex_index as usize];
let lower_control_point =
&self.b_vertices[lower_control_point_vertex_index as usize].position;
&self.b_vertex_positions[lower_control_point_vertex_index as usize];
geometry::quadratic_bezier_quadratic_bezier_crossing_point(
upper_left_vertex_position,
upper_control_point,
@ -743,57 +757,53 @@ impl<'a> Partitioner<'a> {
let left_curve_control_point_vertex_index;
match active_edge.control_point_vertex_index {
u32::MAX => {
let left_point = self.b_vertices[left_curve_left as usize];
let path_id = self.b_vertex_info[left_curve_left as usize].path_id;
let left_point_position = self.b_vertex_positions[left_curve_left as usize];
let right_point = self.endpoints[active_edge.right_endpoint_index as usize]
.position;
let middle_point = left_point.position.to_vector().lerp(right_point.to_vector(), t);
let middle_point = left_point_position.to_vector().lerp(right_point.to_vector(), t);
active_edge.left_vertex_index = self.b_vertices.len() as u32;
self.b_vertices.push(BVertex::new(&middle_point.to_point(),
active_edge.endpoint_kind(),
left_point.path_id));
active_edge.left_vertex_index = self.b_vertex_info.len() as u32;
self.b_vertex_positions.push(middle_point.to_point());
self.b_vertex_info.push(BVertexInfo::new(active_edge.endpoint_kind(), path_id));
active_edge.toggle_parity();
left_curve_control_point_vertex_index = u32::MAX;
}
_ => {
let left_endpoint_position = self.b_vertices[active_edge.left_vertex_index as usize]
.position;
let left_endpoint_position =
self.b_vertex_positions[active_edge.left_vertex_index as usize];
let right_endpoint_position =
self.endpoints[active_edge.right_endpoint_index as usize].position;
let subdivided_quadratic_bezier = SubdividedQuadraticBezier::new(
t,
&left_endpoint_position,
&self.b_vertices[active_edge.control_point_vertex_index as usize].position,
&self.b_vertex_positions[active_edge.control_point_vertex_index as usize],
&right_endpoint_position);
let control_point_b_vertex_a =
BVertex::control_point(&left_endpoint_position,
&subdivided_quadratic_bezier.ap1,
&subdivided_quadratic_bezier.ap2bp0,
self.path_id,
bottom);
left_curve_control_point_vertex_index = self.b_vertices.len() as u32;
left_curve_control_point_vertex_index = self.b_vertex_info.len() as u32;
active_edge.left_vertex_index = left_curve_control_point_vertex_index + 1;
active_edge.control_point_vertex_index = left_curve_control_point_vertex_index + 2;
self.b_vertices.extend([
control_point_b_vertex_a,
BVertex::new(&subdivided_quadratic_bezier.ap2bp0,
active_edge.endpoint_kind(),
self.path_id)
self.b_vertex_positions.extend([
subdivided_quadratic_bezier.ap1,
subdivided_quadratic_bezier.ap2bp0,
subdivided_quadratic_bezier.bp1,
].into_iter());
self.b_vertex_info.extend([
BVertexInfo::control_point(&left_endpoint_position,
&subdivided_quadratic_bezier.ap1,
&subdivided_quadratic_bezier.ap2bp0,
self.path_id,
bottom),
BVertexInfo::new(active_edge.endpoint_kind(), self.path_id),
BVertexInfo::control_point(&subdivided_quadratic_bezier.ap2bp0,
&subdivided_quadratic_bezier.bp1,
&right_endpoint_position,
self.path_id,
bottom),
].into_iter());
let control_point_b_vertex_b =
BVertex::control_point(&subdivided_quadratic_bezier.ap2bp0,
&subdivided_quadratic_bezier.bp1,
&right_endpoint_position,
self.path_id,
bottom);
active_edge.control_point_vertex_index = self.b_vertices.len() as u32;
self.b_vertices.push(control_point_b_vertex_b);
active_edge.toggle_parity();
}
@ -1005,11 +1015,11 @@ struct SubdividedActiveEdge {
}
impl SubdividedActiveEdge {
fn shape(&self, b_vertices: &[BVertex]) -> Shape {
fn shape(&self, b_vertex_info: &[BVertexInfo]) -> Shape {
if self.left_curve_control_point == u32::MAX {
return Shape::Flat
}
match b_vertices[self.left_curve_control_point as usize].kind {
match b_vertex_info[self.left_curve_control_point as usize].kind {
BVertexKind::ConvexControlPoint => Shape::Convex,
_ => Shape::Concave,
}