Add partial support for Mac `.dfont` suitcases
This commit is contained in:
parent
4418f5b07c
commit
ce383385df
|
@ -12,7 +12,8 @@ memmap = "0.5"
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
|
|
||||||
[dependencies.compute-shader]
|
[dependencies.compute-shader]
|
||||||
git = "https://github.com/pcwalton/compute-shader.git"
|
# git = "https://github.com/pcwalton/compute-shader.git"
|
||||||
|
path = "/Users/pcwalton/Source/rust-packages/compute-shader"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bencher = "0.1"
|
bencher = "0.1"
|
||||||
|
|
|
@ -48,7 +48,7 @@ fn main() {
|
||||||
let (device_pixel_width, _) = window.get_framebuffer_size();
|
let (device_pixel_width, _) = window.get_framebuffer_size();
|
||||||
|
|
||||||
let instance = Instance::new().unwrap();
|
let instance = Instance::new().unwrap();
|
||||||
let device = instance.create_device().unwrap();
|
let device = instance.open_device().unwrap();
|
||||||
let queue = device.create_queue().unwrap();
|
let queue = device.create_queue().unwrap();
|
||||||
|
|
||||||
let rasterizer_options = RasterizerOptions::from_env().unwrap();
|
let rasterizer_options = RasterizerOptions::from_env().unwrap();
|
||||||
|
|
|
@ -43,7 +43,7 @@ fn main() {
|
||||||
let (device_pixel_width, device_pixel_height) = window.get_framebuffer_size();
|
let (device_pixel_width, device_pixel_height) = window.get_framebuffer_size();
|
||||||
|
|
||||||
let instance = Instance::new().unwrap();
|
let instance = Instance::new().unwrap();
|
||||||
let device = instance.create_device().unwrap();
|
let device = instance.open_device().unwrap();
|
||||||
let queue = device.create_queue().unwrap();
|
let queue = device.create_queue().unwrap();
|
||||||
|
|
||||||
let rasterizer_options = RasterizerOptions::from_env().unwrap();
|
let rasterizer_options = RasterizerOptions::from_env().unwrap();
|
||||||
|
@ -80,6 +80,7 @@ fn main() {
|
||||||
&batch,
|
&batch,
|
||||||
&coverage_buffer,
|
&coverage_buffer,
|
||||||
&image).unwrap();
|
&image).unwrap();
|
||||||
|
rasterizer.queue.flush().unwrap();
|
||||||
|
|
||||||
let draw_context = lord_drawquaad::Context::new();
|
let draw_context = lord_drawquaad::Context::new();
|
||||||
|
|
||||||
|
|
|
@ -238,7 +238,7 @@ struct Renderer {
|
||||||
impl Renderer {
|
impl Renderer {
|
||||||
fn new() -> Renderer {
|
fn new() -> Renderer {
|
||||||
let instance = Instance::new().unwrap();
|
let instance = Instance::new().unwrap();
|
||||||
let device = instance.create_device().unwrap();
|
let device = instance.open_device().unwrap();
|
||||||
let queue = device.create_queue().unwrap();
|
let queue = device.create_queue().unwrap();
|
||||||
|
|
||||||
let rasterizer_options = RasterizerOptions::from_env().unwrap();
|
let rasterizer_options = RasterizerOptions::from_env().unwrap();
|
||||||
|
|
|
@ -58,6 +58,11 @@ const TTCF: u32 = ((b't' as u32) << 24) |
|
||||||
((b'c' as u32) << 8) |
|
((b'c' as u32) << 8) |
|
||||||
(b'f' as u32);
|
(b'f' as u32);
|
||||||
|
|
||||||
|
const SFNT: u32 = ((b's' as u32) << 24) |
|
||||||
|
((b'f' as u32) << 16) |
|
||||||
|
((b'n' as u32) << 8) |
|
||||||
|
(b't' as u32);
|
||||||
|
|
||||||
static SFNT_VERSIONS: [u32; 2] = [
|
static SFNT_VERSIONS: [u32; 2] = [
|
||||||
0x10000,
|
0x10000,
|
||||||
((b't' as u32) << 24) | ((b'r' as u32) << 16) | ((b'u' as u32) << 8) | (b'e' as u32),
|
((b't' as u32) << 24) | ((b'r' as u32) << 16) | ((b'u' as u32) << 8) | (b'e' as u32),
|
||||||
|
@ -81,12 +86,12 @@ pub struct FontTable<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Font<'a> {
|
impl<'a> Font<'a> {
|
||||||
#[inline]
|
|
||||||
pub fn new<'b>(bytes: &'b [u8]) -> Result<Font<'b>, ()> {
|
pub fn new<'b>(bytes: &'b [u8]) -> Result<Font<'b>, ()> {
|
||||||
// Check magic number.
|
// Check magic number.
|
||||||
let mut reader = bytes;
|
let mut reader = bytes;
|
||||||
let mut magic_number = try!(reader.read_u32::<BigEndian>().map_err(drop));
|
let mut magic_number = try!(reader.read_u32::<BigEndian>().map_err(drop));
|
||||||
if magic_number == TTCF {
|
match magic_number {
|
||||||
|
TTCF => {
|
||||||
// This is a font collection. Read the first font.
|
// This is a font collection. Read the first font.
|
||||||
//
|
//
|
||||||
// TODO(pcwalton): Provide a mechanism to read others.
|
// TODO(pcwalton): Provide a mechanism to read others.
|
||||||
|
@ -102,11 +107,17 @@ impl<'a> Font<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let table_offset = try!(reader.read_u32::<BigEndian>().map_err(drop));
|
let table_offset = try!(reader.read_u32::<BigEndian>().map_err(drop));
|
||||||
reader = bytes;
|
Font::from_otf(&bytes[table_offset as usize..])
|
||||||
try!(reader.jump(table_offset as usize));
|
|
||||||
|
|
||||||
magic_number = try!(reader.read_u32::<BigEndian>().map_err(drop));
|
|
||||||
}
|
}
|
||||||
|
magic_number if SFNT_VERSIONS.contains(&magic_number) => Font::from_otf(bytes),
|
||||||
|
0x0100 => Font::from_dfont(bytes),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_otf<'b>(bytes: &'b [u8]) -> Result<Font<'b>, ()> {
|
||||||
|
let mut reader = bytes;
|
||||||
|
let mut magic_number = try!(reader.read_u32::<BigEndian>().map_err(drop));
|
||||||
|
|
||||||
// Check version.
|
// Check version.
|
||||||
if !SFNT_VERSIONS.contains(&magic_number) {
|
if !SFNT_VERSIONS.contains(&magic_number) {
|
||||||
|
@ -167,6 +178,70 @@ impl<'a> Font<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://github.com/kreativekorp/ksfl/wiki/Macintosh-Resource-File-Format
|
||||||
|
pub fn from_dfont<'b>(bytes: &'b [u8]) -> Result<Font<'b>, ()> {
|
||||||
|
let mut reader = bytes;
|
||||||
|
|
||||||
|
// Read the Mac resource file header.
|
||||||
|
let resource_data_offset = try!(reader.read_u32::<BigEndian>().map_err(drop));
|
||||||
|
let resource_map_offset = try!(reader.read_u32::<BigEndian>().map_err(drop));
|
||||||
|
let resource_data_size = try!(reader.read_u32::<BigEndian>().map_err(drop));
|
||||||
|
let resource_map_size = try!(reader.read_u32::<BigEndian>().map_err(drop));
|
||||||
|
|
||||||
|
// Move to the fields we care about in the resource map.
|
||||||
|
reader = bytes;
|
||||||
|
try!(reader.jump(resource_map_offset as usize + mem::size_of::<u32>() * 5 +
|
||||||
|
mem::size_of::<u16>() * 2));
|
||||||
|
|
||||||
|
// Read the type list and name list offsets.
|
||||||
|
let type_list_offset = try!(reader.read_u16::<BigEndian>().map_err(drop));
|
||||||
|
let name_list_offset = try!(reader.read_u16::<BigEndian>().map_err(drop));
|
||||||
|
|
||||||
|
// Move to the type list.
|
||||||
|
reader = bytes;
|
||||||
|
try!(reader.jump(resource_map_offset as usize + type_list_offset as usize));
|
||||||
|
|
||||||
|
// Find the 'sfnt' type.
|
||||||
|
let type_count = (try!(reader.read_i16::<BigEndian>().map_err(drop)) + 1) as usize;
|
||||||
|
let mut resource_count_and_list_offset = None;
|
||||||
|
for type_index in 0..type_count {
|
||||||
|
let type_id = try!(reader.read_u32::<BigEndian>().map_err(drop));
|
||||||
|
let resource_count = try!(reader.read_u16::<BigEndian>().map_err(drop));
|
||||||
|
let resource_list_offset = try!(reader.read_u16::<BigEndian>().map_err(drop));
|
||||||
|
if type_id == SFNT {
|
||||||
|
resource_count_and_list_offset = Some((resource_count, resource_list_offset));
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unpack the resource count and list offset.
|
||||||
|
let resource_count;
|
||||||
|
match resource_count_and_list_offset {
|
||||||
|
None => return Err(()),
|
||||||
|
Some((count, resource_list_offset)) => {
|
||||||
|
resource_count = count;
|
||||||
|
reader = bytes;
|
||||||
|
try!(reader.jump(resource_map_offset as usize + type_list_offset as usize +
|
||||||
|
resource_list_offset as usize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the font we're interested in.
|
||||||
|
//
|
||||||
|
// TODO(pcwalton): This only gets the first one. Allow the user of this library to select
|
||||||
|
// others.
|
||||||
|
let sfnt_id = try!(reader.read_u16::<BigEndian>().map_err(drop));
|
||||||
|
let sfnt_name_offset = try!(reader.read_u16::<BigEndian>().map_err(drop));
|
||||||
|
let sfnt_data_offset = try!(reader.read_u32::<BigEndian>().map_err(drop)) & 0x00ffffff;
|
||||||
|
let sfnt_ptr = try!(reader.read_u32::<BigEndian>().map_err(drop));
|
||||||
|
|
||||||
|
// Load the resource.
|
||||||
|
reader = bytes;
|
||||||
|
try!(reader.jump(resource_data_offset as usize + sfnt_data_offset as usize));
|
||||||
|
let sfnt_size = try!(reader.read_u32::<BigEndian>().map_err(drop));
|
||||||
|
Font::from_otf(&reader[0..sfnt_size as usize])
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn glyph_ranges_for_codepoint_ranges(&self, codepoint_ranges: &[CodepointRange])
|
pub fn glyph_ranges_for_codepoint_ranges(&self, codepoint_ranges: &[CodepointRange])
|
||||||
-> Result<GlyphRanges, ()> {
|
-> Result<GlyphRanges, ()> {
|
||||||
|
|
Loading…
Reference in New Issue