Upload the chosen font to the server
This commit is contained in:
parent
3fcd4d472b
commit
5b84b052a0
|
@ -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",
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue