From a927294790fb8b1f3c57dcc93f0cb67d0cd9b68f Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 27 Jan 2017 13:01:21 -0800 Subject: [PATCH] Add rudimentary support for TTC --- examples/lorem-ipsum.rs | 3 +++ src/otf/cmap.rs | 32 ++++++++++++++++++++------------ src/otf/mod.rs | 38 +++++++++++++++++++++++++++++++++++--- 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/examples/lorem-ipsum.rs b/examples/lorem-ipsum.rs index 5d6d850e..03b866d6 100644 --- a/examples/lorem-ipsum.rs +++ b/examples/lorem-ipsum.rs @@ -1,6 +1,9 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ +#![feature(alloc_system)] + +extern crate alloc_system; extern crate compute_shader; extern crate euclid; extern crate gl; diff --git a/src/otf/cmap.rs b/src/otf/cmap.rs index 9ed484c2..8ee8c1d3 100644 --- a/src/otf/cmap.rs +++ b/src/otf/cmap.rs @@ -52,20 +52,28 @@ impl<'a> CmapTable<'a> { // Check platform ID and encoding. // TODO(pcwalton): Handle more. - // TODO(pcwalton): Search for one that we can handle. - let platform_id = try!(cmap_reader.read_u16::().map_err(drop)); - let encoding_id = try!(cmap_reader.read_u16::().map_err(drop)); - match (platform_id, encoding_id) { - (PLATFORM_ID_UNICODE, _) | - (PLATFORM_ID_MICROSOFT, MICROSOFT_ENCODING_ID_UNICODE_BMP) | - (PLATFORM_ID_MICROSOFT, MICROSOFT_ENCODING_ID_UNICODE_UCS4) => {} - _ => return Err(()) + let mut table_found = false; + for _ in 0..num_tables { + let platform_id = try!(cmap_reader.read_u16::().map_err(drop)); + let encoding_id = try!(cmap_reader.read_u16::().map_err(drop)); + let offset = try!(cmap_reader.read_u32::().map_err(drop)); + match (platform_id, encoding_id) { + (PLATFORM_ID_UNICODE, _) | + (PLATFORM_ID_MICROSOFT, MICROSOFT_ENCODING_ID_UNICODE_BMP) | + (PLATFORM_ID_MICROSOFT, MICROSOFT_ENCODING_ID_UNICODE_UCS4) => { + // Move to the mapping table. + cmap_reader = self.table.bytes; + try!(cmap_reader.jump(offset as usize)); + table_found = true; + break + } + _ => {} + } } - // Move to the mapping table. - let offset = try!(cmap_reader.read_u32::().map_err(drop)); - cmap_reader = self.table.bytes; - try!(cmap_reader.jump(offset as usize)); + if !table_found { + return Err(()) + } // Check the mapping table format. let format = try!(cmap_reader.read_u16::().map_err(drop)); diff --git a/src/otf/mod.rs b/src/otf/mod.rs index 73a7834c..8d8198cb 100644 --- a/src/otf/mod.rs +++ b/src/otf/mod.rs @@ -50,6 +50,15 @@ const LOCA: u32 = ((b'l' as u32) << 24) | ((b'o' as u32) << 16) | ((b'c' as u32) << 8) | (b'a' as u32); +const TTCF: u32 = ((b't' as u32) << 24) | + ((b't' as u32) << 16) | + ((b'c' as u32) << 8) | + (b'f' as u32); + +static SFNT_VERSIONS: [u32; 2] = [ + 0x10000, + ((b't' as u32) << 24) | ((b'r' as u32) << 16) | ((b'u' as u32) << 8) | (b'e' as u32), +]; pub struct Font<'a> { pub bytes: &'a [u8], @@ -71,10 +80,33 @@ pub struct FontTable<'a> { impl<'a> Font<'a> { #[inline] pub fn new<'b>(bytes: &'b [u8]) -> Result, ()> { - // Read the tables we care about. + // Check magic number. let mut reader = bytes; - let sfnt_version = try!(reader.read_u32::().map_err(drop)); - if sfnt_version != 0x10000 { + let mut magic_number = try!(reader.read_u32::().map_err(drop)); + if magic_number == TTCF { + // This is a font collection. Read the first font. + // + // TODO(pcwalton): Provide a mechanism to read others. + let major_version = try!(reader.read_u16::().map_err(drop)); + let minor_version = try!(reader.read_u16::().map_err(drop)); + if (major_version != 1 && major_version != 2) || minor_version != 0 { + return Err(()) + } + + let num_fonts = try!(reader.read_u32::().map_err(drop)); + if num_fonts == 0 { + return Err(()) + } + + let table_offset = try!(reader.read_u32::().map_err(drop)); + reader = bytes; + try!(reader.jump(table_offset as usize)); + + magic_number = try!(reader.read_u32::().map_err(drop)); + } + + // Check version. + if !SFNT_VERSIONS.contains(&magic_number) { return Err(()) }