Benchmark the server-side partitioning
This commit is contained in:
parent
7f84e98e6e
commit
b6c6c70ef0
|
@ -102,6 +102,12 @@ button > svg path {
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
max-height: 75vh;
|
max-height: 75vh;
|
||||||
}
|
}
|
||||||
|
.pf-benchmark-results-global {
|
||||||
|
padding: 0.75rem;
|
||||||
|
}
|
||||||
|
.pf-benchmark-results-label {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Arrow
|
* Arrow
|
||||||
|
|
|
@ -45,6 +45,11 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
<div class="pf-benchmark-results-global">
|
||||||
|
<span class="pf-benchmark-results-label">Partitioning:</span>
|
||||||
|
|
||||||
|
<span id="pf-benchmark-results-partitioning-time">0</span> µs/glyph
|
||||||
|
</div>
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead class="thead-default">
|
<thead class="thead-default">
|
||||||
<tr><th>Font size (px)</th><th>GPU time per glyph (µs)</th></tr>
|
<tr><th>Font size (px)</th><th>GPU time per glyph (µs)</th></tr>
|
||||||
|
|
|
@ -166,9 +166,9 @@ class ThreeDController extends DemoAppController<ThreeDView> {
|
||||||
this.glyphStorage = new TextFrameGlyphStorage(fileData, textFrames, font);
|
this.glyphStorage = new TextFrameGlyphStorage(fileData, textFrames, font);
|
||||||
this.glyphStorage.layoutRuns();
|
this.glyphStorage.layoutRuns();
|
||||||
|
|
||||||
this.glyphStorage.partition().then((baseMeshes: PathfinderMeshData) => {
|
this.glyphStorage.partition().then(result => {
|
||||||
this.baseMeshes = baseMeshes;
|
this.baseMeshes = result.meshes;
|
||||||
this.expandedMeshes = this.glyphStorage.expandMeshes(baseMeshes);
|
this.expandedMeshes = this.glyphStorage.expandMeshes(this.baseMeshes);
|
||||||
this.view.then(view => {
|
this.view.then(view => {
|
||||||
view.uploadPathColors(this.expandedMeshes.length);
|
view.uploadPathColors(this.expandedMeshes.length);
|
||||||
view.uploadPathTransforms(this.expandedMeshes.length);
|
view.uploadPathTransforms(this.expandedMeshes.length);
|
||||||
|
|
|
@ -58,6 +58,9 @@ class BenchmarkAppController extends DemoAppController<BenchmarkTestView> {
|
||||||
this.resultsTableBody =
|
this.resultsTableBody =
|
||||||
unwrapNull(document.getElementById('pf-benchmark-results-table-body')) as
|
unwrapNull(document.getElementById('pf-benchmark-results-table-body')) as
|
||||||
HTMLTableSectionElement;
|
HTMLTableSectionElement;
|
||||||
|
this.resultsPartitioningTimeLabel =
|
||||||
|
unwrapNull(document.getElementById('pf-benchmark-results-partitioning-time')) as
|
||||||
|
HTMLSpanElement;
|
||||||
|
|
||||||
const resultsCloseButton =
|
const resultsCloseButton =
|
||||||
unwrapNull(document.getElementById('pf-benchmark-results-close-button'));
|
unwrapNull(document.getElementById('pf-benchmark-results-close-button'));
|
||||||
|
@ -82,10 +85,18 @@ class BenchmarkAppController extends DemoAppController<BenchmarkTestView> {
|
||||||
const textFrame = new TextFrame([textRun], font);
|
const textFrame = new TextFrame([textRun], font);
|
||||||
this.glyphStorage = new TextFrameGlyphStorage(fileData, [textFrame], font);
|
this.glyphStorage = new TextFrameGlyphStorage(fileData, [textFrame], font);
|
||||||
|
|
||||||
this.glyphStorage.partition().then(baseMeshes => {
|
this.glyphStorage.partition().then(result => {
|
||||||
this.baseMeshes = baseMeshes;
|
this.baseMeshes = result.meshes;
|
||||||
const expandedMeshes = this.glyphStorage.expandMeshes(baseMeshes)[0];
|
|
||||||
|
const partitionTime = result.time / this.glyphStorage.uniqueGlyphs.length * 1e6;
|
||||||
|
const timeLabel = this.resultsPartitioningTimeLabel;
|
||||||
|
while (timeLabel.firstChild != null)
|
||||||
|
timeLabel.removeChild(timeLabel.firstChild);
|
||||||
|
timeLabel.appendChild(document.createTextNode("" + partitionTime));
|
||||||
|
|
||||||
|
const expandedMeshes = this.glyphStorage.expandMeshes(this.baseMeshes)[0];
|
||||||
this.expandedMeshes = expandedMeshes;
|
this.expandedMeshes = expandedMeshes;
|
||||||
|
|
||||||
this.view.then(view => {
|
this.view.then(view => {
|
||||||
view.uploadPathColors(1);
|
view.uploadPathColors(1);
|
||||||
view.uploadPathTransforms(1);
|
view.uploadPathTransforms(1);
|
||||||
|
@ -149,6 +160,7 @@ class BenchmarkAppController extends DemoAppController<BenchmarkTestView> {
|
||||||
|
|
||||||
private resultsModal: HTMLDivElement;
|
private resultsModal: HTMLDivElement;
|
||||||
private resultsTableBody: HTMLTableSectionElement;
|
private resultsTableBody: HTMLTableSectionElement;
|
||||||
|
private resultsPartitioningTimeLabel: HTMLSpanElement;
|
||||||
|
|
||||||
private glyphStorage: TextFrameGlyphStorage<BenchmarkGlyph>;
|
private glyphStorage: TextFrameGlyphStorage<BenchmarkGlyph>;
|
||||||
private baseMeshes: PathfinderMeshData;
|
private baseMeshes: PathfinderMeshData;
|
||||||
|
@ -156,6 +168,7 @@ class BenchmarkAppController extends DemoAppController<BenchmarkTestView> {
|
||||||
|
|
||||||
private pixelsPerEm: number;
|
private pixelsPerEm: number;
|
||||||
private elapsedTimes: ElapsedTime[];
|
private elapsedTimes: ElapsedTime[];
|
||||||
|
private partitionTime: number;
|
||||||
|
|
||||||
font: opentype.Font | null;
|
font: opentype.Font | null;
|
||||||
textRun: TextRun<BenchmarkGlyph> | null;
|
textRun: TextRun<BenchmarkGlyph> | null;
|
||||||
|
|
|
@ -156,7 +156,7 @@ class MeshDebuggerAppController extends AppController {
|
||||||
|
|
||||||
const glyph = new MeshDebuggerGlyph(opentypeGlyph);
|
const glyph = new MeshDebuggerGlyph(opentypeGlyph);
|
||||||
const glyphStorage = new GlyphStorage(this.fileData, [glyph], this.file);
|
const glyphStorage = new GlyphStorage(this.fileData, [glyph], this.file);
|
||||||
promise = glyphStorage.partition();
|
promise = glyphStorage.partition().then(result => result.meshes);
|
||||||
} else if (this.file instanceof SVGLoader) {
|
} else if (this.file instanceof SVGLoader) {
|
||||||
promise = this.file.partition(this.fontPathSelect.selectedIndex);
|
promise = this.file.partition(this.fontPathSelect.selectedIndex);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -176,10 +176,10 @@ class TextDemoController extends DemoAppController<TextDemoView> {
|
||||||
const newLayout = new SimpleTextLayout(fileData,
|
const newLayout = new SimpleTextLayout(fileData,
|
||||||
this.text,
|
this.text,
|
||||||
glyph => new GlyphInstance(glyph));
|
glyph => new GlyphInstance(glyph));
|
||||||
newLayout.glyphStorage.partition().then((meshes: PathfinderMeshData) => {
|
newLayout.glyphStorage.partition().then(result => {
|
||||||
this.view.then(view => {
|
this.view.then(view => {
|
||||||
this.layout = newLayout;
|
this.layout = newLayout;
|
||||||
this.meshes = meshes;
|
this.meshes = result.meshes;
|
||||||
|
|
||||||
view.attachText();
|
view.attachText();
|
||||||
view.uploadPathColors(1);
|
view.uploadPathColors(1);
|
||||||
|
|
|
@ -25,6 +25,11 @@ export interface ExpandedMeshData {
|
||||||
meshes: PathfinderMeshData;
|
meshes: PathfinderMeshData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PartitionResult {
|
||||||
|
meshes: PathfinderMeshData,
|
||||||
|
time: number,
|
||||||
|
}
|
||||||
|
|
||||||
type CreateGlyphFn<Glyph> = (glyph: opentype.Glyph) => Glyph;
|
type CreateGlyphFn<Glyph> = (glyph: opentype.Glyph) => Glyph;
|
||||||
|
|
||||||
export interface PixelMetrics {
|
export interface PixelMetrics {
|
||||||
|
@ -250,7 +255,7 @@ export class GlyphStorage<Glyph extends PathfinderGlyph> {
|
||||||
this.uniqueGlyphs = _.sortedUniqBy(this.uniqueGlyphs, glyph => glyph.index);
|
this.uniqueGlyphs = _.sortedUniqBy(this.uniqueGlyphs, glyph => glyph.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
partition(): Promise<PathfinderMeshData> {
|
partition(): Promise<PartitionResult> {
|
||||||
// Build the partitioning request to the server.
|
// Build the partitioning request to the server.
|
||||||
//
|
//
|
||||||
// FIXME(pcwalton): If this is a builtin font, don't resend it to the server!
|
// FIXME(pcwalton): If this is a builtin font, don't resend it to the server!
|
||||||
|
@ -278,7 +283,10 @@ export class GlyphStorage<Glyph extends PathfinderGlyph> {
|
||||||
const response = JSON.parse(responseText);
|
const response = JSON.parse(responseText);
|
||||||
if (!('Ok' in response))
|
if (!('Ok' in response))
|
||||||
panic("Failed to partition the font!");
|
panic("Failed to partition the font!");
|
||||||
return new PathfinderMeshData(response.Ok.pathData);
|
return {
|
||||||
|
meshes: new PathfinderMeshData(response.Ok.pathData),
|
||||||
|
time: response.Ok.time,
|
||||||
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ use std::fs::File;
|
||||||
use std::io::{self, Read};
|
use std::io::{self, Read};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
use std::u32;
|
use std::u32;
|
||||||
|
|
||||||
static STATIC_INDEX_PATH: &'static str = "../client/index.html";
|
static STATIC_INDEX_PATH: &'static str = "../client/index.html";
|
||||||
|
@ -152,6 +153,7 @@ struct PartitionFontResponse {
|
||||||
glyph_info: Vec<PartitionGlyphInfo>,
|
glyph_info: Vec<PartitionGlyphInfo>,
|
||||||
#[serde(rename = "pathData")]
|
#[serde(rename = "pathData")]
|
||||||
path_data: PartitionEncodedPathData,
|
path_data: PartitionEncodedPathData,
|
||||||
|
time: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Serialize, Deserialize)]
|
||||||
|
@ -255,108 +257,126 @@ struct PartitionSvgPathsResponse {
|
||||||
path_data: PartitionEncodedPathData,
|
path_data: PartitionEncodedPathData,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn partition_paths(partitioner: &mut Partitioner, subpath_indices: &[SubpathRange])
|
struct PathPartitioningResult {
|
||||||
-> (PartitionEncodedPathData, Vec<PartitionPathIndices>) {
|
encoded_data: PartitionEncodedPathData,
|
||||||
let (mut b_quads, mut b_vertex_positions) = (vec![], vec![]);
|
indices: Vec<PartitionPathIndices>,
|
||||||
let (mut b_vertex_path_ids, mut b_vertex_loop_blinn_data) = (vec![], vec![]);
|
time: Duration,
|
||||||
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![]);
|
|
||||||
|
|
||||||
let mut path_indices = vec![];
|
impl PathPartitioningResult {
|
||||||
|
fn compute(partitioner: &mut Partitioner, subpath_indices: &[SubpathRange])
|
||||||
|
-> PathPartitioningResult {
|
||||||
|
let timestamp_before = Instant::now();
|
||||||
|
|
||||||
for (path_index, subpath_range) in subpath_indices.iter().enumerate() {
|
let (mut b_quads, mut b_vertex_positions) = (vec![], vec![]);
|
||||||
partitioner.partition((path_index + 1) as u16, subpath_range.start, subpath_range.end);
|
let (mut b_vertex_path_ids, mut b_vertex_loop_blinn_data) = (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![]);
|
||||||
|
|
||||||
let path_b_vertex_positions = partitioner.b_vertex_positions();
|
let mut path_indices = vec![];
|
||||||
let path_b_vertex_path_ids = partitioner.b_vertex_path_ids();
|
|
||||||
let path_b_vertex_loop_blinn_data = partitioner.b_vertex_loop_blinn_data();
|
|
||||||
let cover_indices = partitioner.cover_indices();
|
|
||||||
let edge_indices = partitioner.edge_indices();
|
|
||||||
|
|
||||||
let positions_start = IndexRange::from_data(&mut b_vertex_positions,
|
for (path_index, subpath_range) in subpath_indices.iter().enumerate() {
|
||||||
path_b_vertex_positions).unwrap().start as u32;
|
partitioner.partition((path_index + 1) as u16, subpath_range.start, subpath_range.end);
|
||||||
IndexRange::from_data(&mut b_vertex_path_ids, path_b_vertex_path_ids).unwrap();
|
|
||||||
|
|
||||||
let mut path_b_quads = partitioner.b_quads().to_vec();
|
let path_b_vertex_positions = partitioner.b_vertex_positions();
|
||||||
let mut path_cover_interior_indices = cover_indices.interior_indices.to_vec();
|
let path_b_vertex_path_ids = partitioner.b_vertex_path_ids();
|
||||||
let mut path_cover_curve_indices = cover_indices.curve_indices.to_vec();
|
let path_b_vertex_loop_blinn_data = partitioner.b_vertex_loop_blinn_data();
|
||||||
let mut path_edge_upper_line_indices = edge_indices.upper_line_indices.to_vec();
|
let cover_indices = partitioner.cover_indices();
|
||||||
let mut path_edge_upper_curve_indices = edge_indices.upper_curve_indices.to_vec();
|
let edge_indices = partitioner.edge_indices();
|
||||||
let mut path_edge_lower_line_indices = edge_indices.lower_line_indices.to_vec();
|
|
||||||
let mut path_edge_lower_curve_indices = edge_indices.lower_curve_indices.to_vec();
|
|
||||||
|
|
||||||
for path_b_quad in &mut path_b_quads {
|
let positions_start =
|
||||||
path_b_quad.offset(positions_start);
|
IndexRange::from_data(&mut b_vertex_positions,
|
||||||
}
|
path_b_vertex_positions).unwrap().start as u32;
|
||||||
for path_cover_interior_index in &mut path_cover_interior_indices {
|
IndexRange::from_data(&mut b_vertex_path_ids, path_b_vertex_path_ids).unwrap();
|
||||||
*path_cover_interior_index += positions_start
|
|
||||||
}
|
let mut path_b_quads = partitioner.b_quads().to_vec();
|
||||||
for path_cover_curve_index in &mut path_cover_curve_indices {
|
let mut path_cover_interior_indices = cover_indices.interior_indices.to_vec();
|
||||||
*path_cover_curve_index += positions_start
|
let mut path_cover_curve_indices = cover_indices.curve_indices.to_vec();
|
||||||
}
|
let mut path_edge_upper_line_indices = edge_indices.upper_line_indices.to_vec();
|
||||||
for path_edge_upper_line_indices in &mut path_edge_upper_line_indices {
|
let mut path_edge_upper_curve_indices = edge_indices.upper_curve_indices.to_vec();
|
||||||
path_edge_upper_line_indices.offset(positions_start);
|
let mut path_edge_lower_line_indices = edge_indices.lower_line_indices.to_vec();
|
||||||
}
|
let mut path_edge_lower_curve_indices = edge_indices.lower_curve_indices.to_vec();
|
||||||
for path_edge_upper_curve_indices in &mut path_edge_upper_curve_indices {
|
|
||||||
path_edge_upper_curve_indices.offset(positions_start);
|
for path_b_quad in &mut path_b_quads {
|
||||||
}
|
path_b_quad.offset(positions_start);
|
||||||
for path_edge_lower_line_indices in &mut path_edge_lower_line_indices {
|
}
|
||||||
path_edge_lower_line_indices.offset(positions_start);
|
for path_cover_interior_index in &mut path_cover_interior_indices {
|
||||||
}
|
*path_cover_interior_index += positions_start
|
||||||
for path_edge_lower_curve_indices in &mut path_edge_lower_curve_indices {
|
}
|
||||||
path_edge_lower_curve_indices.offset(positions_start);
|
for path_cover_curve_index in &mut path_cover_curve_indices {
|
||||||
|
*path_cover_curve_index += positions_start
|
||||||
|
}
|
||||||
|
for path_edge_upper_line_indices in &mut path_edge_upper_line_indices {
|
||||||
|
path_edge_upper_line_indices.offset(positions_start);
|
||||||
|
}
|
||||||
|
for path_edge_upper_curve_indices in &mut path_edge_upper_curve_indices {
|
||||||
|
path_edge_upper_curve_indices.offset(positions_start);
|
||||||
|
}
|
||||||
|
for path_edge_lower_line_indices in &mut path_edge_lower_line_indices {
|
||||||
|
path_edge_lower_line_indices.offset(positions_start);
|
||||||
|
}
|
||||||
|
for path_edge_lower_curve_indices in &mut path_edge_lower_curve_indices {
|
||||||
|
path_edge_lower_curve_indices.offset(positions_start);
|
||||||
|
}
|
||||||
|
|
||||||
|
path_indices.push(PartitionPathIndices {
|
||||||
|
b_quad_indices: IndexRange::from_data(&mut b_quads, &path_b_quads).unwrap(),
|
||||||
|
b_vertex_indices: IndexRange::from_data(&mut b_vertex_loop_blinn_data,
|
||||||
|
path_b_vertex_loop_blinn_data).unwrap(),
|
||||||
|
cover_interior_indices: IndexRange::from_data(&mut cover_interior_indices,
|
||||||
|
&path_cover_interior_indices).unwrap(),
|
||||||
|
cover_curve_indices: IndexRange::from_data(&mut cover_curve_indices,
|
||||||
|
&path_cover_curve_indices).unwrap(),
|
||||||
|
edge_upper_line_indices:
|
||||||
|
IndexRange::from_data(&mut edge_upper_line_indices,
|
||||||
|
&path_edge_upper_line_indices).unwrap(),
|
||||||
|
edge_upper_curve_indices:
|
||||||
|
IndexRange::from_data(&mut edge_upper_curve_indices,
|
||||||
|
&path_edge_upper_curve_indices).unwrap(),
|
||||||
|
edge_lower_line_indices: IndexRange::from_data(&mut edge_lower_line_indices,
|
||||||
|
&path_edge_lower_line_indices).unwrap(),
|
||||||
|
edge_lower_curve_indices:
|
||||||
|
IndexRange::from_data(&mut edge_lower_curve_indices,
|
||||||
|
&path_edge_lower_curve_indices).unwrap(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
path_indices.push(PartitionPathIndices {
|
// Reverse interior indices for early Z optimizations.
|
||||||
b_quad_indices: IndexRange::from_data(&mut b_quads, &path_b_quads).unwrap(),
|
let mut new_cover_interior_indices = Vec::with_capacity(cover_interior_indices.len());
|
||||||
b_vertex_indices: IndexRange::from_data(&mut b_vertex_loop_blinn_data,
|
for path_indices in path_indices.iter_mut().rev() {
|
||||||
path_b_vertex_loop_blinn_data).unwrap(),
|
let old_byte_start = path_indices.cover_interior_indices.start * mem::size_of::<u32>();
|
||||||
cover_interior_indices: IndexRange::from_data(&mut cover_interior_indices,
|
let old_byte_end = path_indices.cover_interior_indices.end * mem::size_of::<u32>();
|
||||||
&path_cover_interior_indices).unwrap(),
|
let new_start_index = new_cover_interior_indices.len() / mem::size_of::<u32>();
|
||||||
cover_curve_indices: IndexRange::from_data(&mut cover_curve_indices,
|
new_cover_interior_indices.extend(
|
||||||
&path_cover_curve_indices).unwrap(),
|
cover_interior_indices[old_byte_start..old_byte_end].into_iter());
|
||||||
edge_upper_line_indices: IndexRange::from_data(&mut edge_upper_line_indices,
|
let new_end_index = new_cover_interior_indices.len() / mem::size_of::<u32>();
|
||||||
&path_edge_upper_line_indices).unwrap(),
|
path_indices.cover_interior_indices.start = new_start_index;
|
||||||
edge_upper_curve_indices:
|
path_indices.cover_interior_indices.end = new_end_index;
|
||||||
IndexRange::from_data(&mut edge_upper_curve_indices,
|
}
|
||||||
&path_edge_upper_curve_indices).unwrap(),
|
cover_interior_indices = new_cover_interior_indices;
|
||||||
edge_lower_line_indices: IndexRange::from_data(&mut edge_lower_line_indices,
|
|
||||||
&path_edge_lower_line_indices).unwrap(),
|
let time_elapsed = timestamp_before.elapsed();
|
||||||
edge_lower_curve_indices:
|
|
||||||
IndexRange::from_data(&mut edge_lower_curve_indices,
|
let encoded_path_data = PartitionEncodedPathData {
|
||||||
&path_edge_lower_curve_indices).unwrap(),
|
b_quads: base64::encode(&b_quads),
|
||||||
})
|
b_vertex_positions: base64::encode(&b_vertex_positions),
|
||||||
|
b_vertex_path_ids: base64::encode(&b_vertex_path_ids),
|
||||||
|
b_vertex_loop_blinn_data: base64::encode(&b_vertex_loop_blinn_data),
|
||||||
|
cover_interior_indices: base64::encode(&cover_interior_indices),
|
||||||
|
cover_curve_indices: base64::encode(&cover_curve_indices),
|
||||||
|
edge_upper_line_indices: base64::encode(&edge_upper_line_indices),
|
||||||
|
edge_upper_curve_indices: base64::encode(&edge_upper_curve_indices),
|
||||||
|
edge_lower_line_indices: base64::encode(&edge_lower_line_indices),
|
||||||
|
edge_lower_curve_indices: base64::encode(&edge_lower_curve_indices),
|
||||||
|
};
|
||||||
|
|
||||||
|
PathPartitioningResult {
|
||||||
|
encoded_data: encoded_path_data,
|
||||||
|
indices: path_indices,
|
||||||
|
time: time_elapsed,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse interior indices for early Z optimizations.
|
|
||||||
let mut new_cover_interior_indices = Vec::with_capacity(cover_interior_indices.len());
|
|
||||||
for path_indices in path_indices.iter_mut().rev() {
|
|
||||||
let old_byte_start = path_indices.cover_interior_indices.start * mem::size_of::<u32>();
|
|
||||||
let old_byte_end = path_indices.cover_interior_indices.end * mem::size_of::<u32>();
|
|
||||||
let new_start_index = new_cover_interior_indices.len() / mem::size_of::<u32>();
|
|
||||||
new_cover_interior_indices.extend(
|
|
||||||
cover_interior_indices[old_byte_start..old_byte_end].into_iter());
|
|
||||||
let new_end_index = new_cover_interior_indices.len() / mem::size_of::<u32>();
|
|
||||||
path_indices.cover_interior_indices.start = new_start_index;
|
|
||||||
path_indices.cover_interior_indices.end = new_end_index;
|
|
||||||
}
|
|
||||||
cover_interior_indices = new_cover_interior_indices;
|
|
||||||
|
|
||||||
let encoded_path_data = PartitionEncodedPathData {
|
|
||||||
b_quads: base64::encode(&b_quads),
|
|
||||||
b_vertex_positions: base64::encode(&b_vertex_positions),
|
|
||||||
b_vertex_path_ids: base64::encode(&b_vertex_path_ids),
|
|
||||||
b_vertex_loop_blinn_data: base64::encode(&b_vertex_loop_blinn_data),
|
|
||||||
cover_interior_indices: base64::encode(&cover_interior_indices),
|
|
||||||
cover_curve_indices: base64::encode(&cover_curve_indices),
|
|
||||||
edge_upper_line_indices: base64::encode(&edge_upper_line_indices),
|
|
||||||
edge_upper_curve_indices: base64::encode(&edge_upper_curve_indices),
|
|
||||||
edge_lower_line_indices: base64::encode(&edge_lower_line_indices),
|
|
||||||
edge_lower_curve_indices: base64::encode(&edge_lower_curve_indices),
|
|
||||||
};
|
|
||||||
|
|
||||||
(encoded_path_data, path_indices)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/partition-font", format = "application/json", data = "<request>")]
|
#[post("/partition-font", format = "application/json", data = "<request>")]
|
||||||
|
@ -428,11 +448,14 @@ fn partition_font(request: Json<PartitionFontRequest>)
|
||||||
// Partition the decoded glyph outlines.
|
// Partition the decoded glyph outlines.
|
||||||
let mut partitioner = Partitioner::new();
|
let mut partitioner = Partitioner::new();
|
||||||
partitioner.init_with_path_buffer(&path_buffer);
|
partitioner.init_with_path_buffer(&path_buffer);
|
||||||
let (encoded_path_data, path_indices) = partition_paths(&mut partitioner, &subpath_indices);
|
let path_partitioning_result = PathPartitioningResult::compute(&mut partitioner,
|
||||||
|
&subpath_indices);
|
||||||
|
|
||||||
// Package up other miscellaneous glyph info.
|
// Package up other miscellaneous glyph info.
|
||||||
let mut glyph_info = vec![];
|
let mut glyph_info = vec![];
|
||||||
for (glyph, glyph_path_indices) in request.glyphs.iter().zip(path_indices.iter()) {
|
for (glyph, glyph_path_indices) in request.glyphs
|
||||||
|
.iter()
|
||||||
|
.zip(path_partitioning_result.indices.iter()) {
|
||||||
let glyph_key = GlyphKey::new(glyph.id);
|
let glyph_key = GlyphKey::new(glyph.id);
|
||||||
|
|
||||||
let dimensions = match font_context.glyph_dimensions(&font_instance_key, &glyph_key) {
|
let dimensions = match font_context.glyph_dimensions(&font_instance_key, &glyph_key) {
|
||||||
|
@ -453,10 +476,14 @@ fn partition_font(request: Json<PartitionFontRequest>)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let time = path_partitioning_result.time.as_secs() as f64 +
|
||||||
|
path_partitioning_result.time.subsec_nanos() as f64 * 1e-9;
|
||||||
|
|
||||||
// Return the response.
|
// Return the response.
|
||||||
Json(Ok(PartitionFontResponse {
|
Json(Ok(PartitionFontResponse {
|
||||||
glyph_info: glyph_info,
|
glyph_info: glyph_info,
|
||||||
path_data: encoded_path_data,
|
path_data: path_partitioning_result.encoded_data,
|
||||||
|
time: time,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,12 +558,12 @@ fn partition_svg_paths(request: Json<PartitionSvgPathsRequest>)
|
||||||
// Partition the paths.
|
// Partition the paths.
|
||||||
let mut partitioner = Partitioner::new();
|
let mut partitioner = Partitioner::new();
|
||||||
partitioner.init_with_path_buffer(&path_buffer);
|
partitioner.init_with_path_buffer(&path_buffer);
|
||||||
let (encoded_path_data, path_indices) = partition_paths(&mut partitioner, &paths);
|
let path_partitioning_result = PathPartitioningResult::compute(&mut partitioner, &paths);
|
||||||
|
|
||||||
// Return the response.
|
// Return the response.
|
||||||
Json(Ok(PartitionSvgPathsResponse {
|
Json(Ok(PartitionSvgPathsResponse {
|
||||||
path_indices: path_indices,
|
path_indices: path_partitioning_result.indices,
|
||||||
path_data: encoded_path_data,
|
path_data: path_partitioning_result.encoded_data,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue