Upload the chosen font to the server

This commit is contained in:
Patrick Walton 2017-08-10 18:38:54 -07:00
parent 3fcd4d472b
commit 5b84b052a0
3 changed files with 73 additions and 18 deletions

View File

@ -10,6 +10,7 @@
"license": "MIT OR Apache-2.0", "license": "MIT OR Apache-2.0",
"dependencies": { "dependencies": {
"@types/node": "^8.0.19", "@types/node": "^8.0.19",
"base64-js": "^1.2.1",
"bootstrap": "^4.0.0-alpha.6", "bootstrap": "^4.0.0-alpha.6",
"opentype.js": "^0.7.3", "opentype.js": "^0.7.3",
"ts-loader": "^2.3.2", "ts-loader": "^2.3.2",

View File

@ -1,11 +1,30 @@
// pathfinder/demo/src/index.ts // pathfinder/demo/src/index.ts
const base64js = require('base64-js');
const opentype = require('opentype.js'); const opentype = require('opentype.js');
class AppController { const TEXT: string = "A";
constructor() { const FONT_SIZE: number = 16.0;
const PARTITION_FONT_ENDPOINT_URL: string = "/partition-font";
class PathfinderMeshes {
constructor(encodedResponse: string) {
const response = JSON.parse(encodedResponse);
if (!('Ok' in response))
throw new Error("Failed to partition the font!");
const meshes = response.Ok;
this.bQuads = base64js.toByteArray(meshes.bQuads);
this.bVertices = base64js.toByteArray(meshes.bVertices);
} }
bQuads: ArrayBuffer;
bVertices: ArrayBuffer;
}
class AppController {
constructor() {}
start() { start() {
this.view = new PathfinderView(document.getElementById('pf-canvas') as HTMLCanvasElement); this.view = new PathfinderView(document.getElementById('pf-canvas') as HTMLCanvasElement);
@ -15,16 +34,49 @@ class AppController {
loadFont() { loadFont() {
const file = this.loadFontButton.files[0]; const file = this.loadFontButton.files[0];
const fileURL = window.URL.createObjectURL(file); const reader = new FileReader;
opentype.load(fileURL, (err, font) => this.fontLoaded(font)); reader.addEventListener('loadend', () => {
this.fontData = reader.result;
this.fontLoaded();
}, false);
reader.readAsArrayBuffer(file);
} }
fontLoaded(font) { fontLoaded() {
this.font = opentype.parse(this.fontData);
if (!this.font.supported) {
window.alert("The font type is unsupported.");
return;
}
const glyphIDs = this.font.stringToGlyphs(TEXT).map(glyph => glyph.index);
const request = {
otf: base64js.fromByteArray(new Uint8Array(this.fontData)),
fontIndex: 0,
glyphIDs: glyphIDs,
pointSize: FONT_SIZE,
};
const xhr = new XMLHttpRequest();
xhr.addEventListener('load', () => {
this.meshes = new PathfinderMeshes(xhr.responseText);
this.meshesReceived();
}, false);
xhr.open('POST', PARTITION_FONT_ENDPOINT_URL, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(request));
}
meshesReceived() {
// TODO(pcwalton) // TODO(pcwalton)
} }
view: PathfinderView; view: PathfinderView;
loadFontButton: HTMLInputElement; loadFontButton: HTMLInputElement;
fontData: ArrayBuffer;
font: any;
meshes: PathfinderMeshes;
} }
class PathfinderView { class PathfinderView {

View File

@ -52,13 +52,14 @@ impl IndexRange {
} }
} }
#[allow(non_snake_case)]
#[derive(Clone, Serialize, Deserialize)] #[derive(Clone, Serialize, Deserialize)]
struct PartitionFontRequest { struct PartitionFontRequest {
// Base64 encoded. // Base64 encoded.
otf: String, otf: String,
font_index: u32, fontIndex: u32,
glyph_ids: Vec<u32>, glyphIDs: Vec<u32>,
point_size: f64, pointSize: f64,
} }
#[derive(Clone, Copy, Serialize, Deserialize)] #[derive(Clone, Copy, Serialize, Deserialize)]
@ -83,13 +84,14 @@ struct PartitionGlyphInfo {
b_vertex_indices: IndexRange, b_vertex_indices: IndexRange,
} }
#[allow(non_snake_case)]
#[derive(Clone, Serialize, Deserialize)] #[derive(Clone, Serialize, Deserialize)]
struct PartitionFontResponse { struct PartitionFontResponse {
glyph_info: Vec<PartitionGlyphInfo>, glyphInfo: Vec<PartitionGlyphInfo>,
// Base64-encoded `bincode`-encoded `BQuad`s. // Base64-encoded `bincode`-encoded `BQuad`s.
b_quads: String, bQuads: String,
// Base64-encoded `bincode`-encoded `BVertex`es. // Base64-encoded `bincode`-encoded `BVertex`es.
b_vertices: String, bVertices: String,
} }
#[derive(Clone, Copy, Serialize, Deserialize)] #[derive(Clone, Copy, Serialize, Deserialize)]
@ -119,16 +121,16 @@ fn partition_font(request: Json<PartitionFontRequest>)
let font_key = FontKey::new(); let font_key = FontKey::new();
let font_instance_key = FontInstanceKey { let font_instance_key = FontInstanceKey {
font_key: font_key, font_key: font_key,
size: Au::from_f64_px(request.point_size), size: Au::from_f64_px(request.pointSize),
}; };
let mut font_context = FontContext::new(); let mut font_context = FontContext::new();
if font_context.add_font_from_memory(&font_key, otf_data, request.font_index).is_err() { if font_context.add_font_from_memory(&font_key, otf_data, request.fontIndex).is_err() {
return Json(Err(PartitionFontError::FontLoadingFailed)) return Json(Err(PartitionFontError::FontLoadingFailed))
} }
// Read glyph info. // Read glyph info.
let mut outline_buffer = GlyphOutlineBuffer::new(); let mut outline_buffer = GlyphOutlineBuffer::new();
let decoded_outline_indices: Vec<_> = request.glyph_ids.iter().map(|&glyph_id| { let decoded_outline_indices: Vec<_> = request.glyphIDs.iter().map(|&glyph_id| {
let glyph_key = GlyphKey::new(glyph_id); let glyph_key = GlyphKey::new(glyph_id);
let first_endpoint_index = outline_buffer.endpoints.len(); let first_endpoint_index = outline_buffer.endpoints.len();
@ -159,7 +161,7 @@ fn partition_font(request: Json<PartitionFontRequest>)
&outline_buffer.subpaths); &outline_buffer.subpaths);
let mut glyph_info = vec![]; let mut glyph_info = vec![];
for (path_index, (&glyph_id, decoded_outline_indices)) in for (path_index, (&glyph_id, decoded_outline_indices)) in
request.glyph_ids.iter().zip(decoded_outline_indices.iter()).enumerate() { request.glyphIDs.iter().zip(decoded_outline_indices.iter()).enumerate() {
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) {
@ -212,9 +214,9 @@ fn partition_font(request: Json<PartitionFontRequest>)
// Return the response. // Return the response.
Json(Ok(PartitionFontResponse { Json(Ok(PartitionFontResponse {
glyph_info: glyph_info, glyphInfo: glyph_info,
b_quads: base64::encode(&b_quads), bQuads: base64::encode(&b_quads),
b_vertices: base64::encode(&b_vertices), bVertices: base64::encode(&b_vertices),
})) }))
} }