Add skeleton code for TrueType hinting, not functional yet

This commit is contained in:
Patrick Walton 2017-02-23 17:41:27 -08:00
parent b86133a4ef
commit d29775c345
7 changed files with 534 additions and 18 deletions

View File

@ -17,7 +17,9 @@ use error::FontError;
use font::{Font, FontTable};
use std::mem;
use tables::cff::{self, CffTable};
use tables::cvt;
use tables::cmap::{self, CmapTable};
use tables::fpgm;
use tables::glyf::{self, GlyfTable};
use tables::head::{self, HeadTable};
use tables::hhea::{self, HheaTable};
@ -25,6 +27,7 @@ use tables::hmtx::{self, HmtxTable};
use tables::kern::{self, KernTable};
use tables::loca::{self, LocaTable};
use tables::os_2::{self, Os2Table};
use tables::prep;
use util::Jump;
const OTTO: u32 = ((b'O' as u32) << 24) |
@ -32,30 +35,36 @@ const OTTO: u32 = ((b'O' as u32) << 24) |
((b'T' as u32) << 8) |
(b'O' as u32);
pub const KNOWN_TABLE_COUNT: usize = 9;
pub const KNOWN_TABLE_COUNT: usize = 12;
pub static KNOWN_TABLES: [u32; KNOWN_TABLE_COUNT] = [
cff::TAG,
os_2::TAG,
cmap::TAG,
cvt::TAG,
fpgm::TAG,
glyf::TAG,
head::TAG,
hhea::TAG,
hmtx::TAG,
kern::TAG,
loca::TAG,
prep::TAG,
];
// This must agree with the above.
const TABLE_INDEX_CFF: usize = 0;
const TABLE_INDEX_OS_2: usize = 1;
const TABLE_INDEX_CMAP: usize = 2;
const TABLE_INDEX_GLYF: usize = 3;
const TABLE_INDEX_HEAD: usize = 4;
const TABLE_INDEX_HHEA: usize = 5;
const TABLE_INDEX_HMTX: usize = 6;
const TABLE_INDEX_KERN: usize = 7;
const TABLE_INDEX_LOCA: usize = 8;
const TABLE_INDEX_CVT: usize = 3;
const TABLE_INDEX_FPGM: usize = 4;
const TABLE_INDEX_GLYF: usize = 5;
const TABLE_INDEX_HEAD: usize = 6;
const TABLE_INDEX_HHEA: usize = 7;
const TABLE_INDEX_HMTX: usize = 8;
const TABLE_INDEX_KERN: usize = 9;
const TABLE_INDEX_LOCA: usize = 10;
const TABLE_INDEX_PREP: usize = 11;
pub static SFNT_VERSIONS: [u32; 3] = [
0x10000,
@ -65,16 +74,23 @@ pub static SFNT_VERSIONS: [u32; 3] = [
#[doc(hidden)]
pub struct FontTables<'a> {
// Required tables.
pub cmap: CmapTable<'a>,
pub head: HeadTable,
pub hhea: HheaTable,
pub hmtx: HmtxTable<'a>,
pub os_2: Os2Table,
// Optional tables.
pub cff: Option<CffTable<'a>>,
pub glyf: Option<GlyfTable<'a>>,
pub loca: Option<LocaTable<'a>>,
pub kern: Option<KernTable<'a>>,
// Optional tables that need no parsing.
pub cvt: Option<FontTable<'a>>,
pub fpgm: Option<FontTable<'a>>,
pub prep: Option<FontTable<'a>>,
}
impl<'a> Font<'a> {
@ -145,6 +161,10 @@ impl<'a> Font<'a> {
glyf: tables[TABLE_INDEX_GLYF].map(GlyfTable::new),
loca: loca_table,
kern: tables[TABLE_INDEX_KERN].and_then(|table| KernTable::new(table).ok()),
cvt: tables[TABLE_INDEX_CVT],
fpgm: tables[TABLE_INDEX_FPGM],
prep: tables[TABLE_INDEX_PREP],
};
Ok(Font::from_tables(bytes, tables))

View File

@ -124,3 +124,10 @@ pub enum GlyphStoreCreationError {
GlError(GlError),
}
/// An error in hinting instruction evaluation.
#[derive(Debug)]
pub enum HintingError {
/// A miscellaneous error occurred.
Failed,
}

View File

@ -200,6 +200,24 @@ impl<'a> Font<'a> {
pub fn line_gap(&self) -> i16 {
self.tables.os_2.typo_line_gap
}
/// Returns the Control Value Table of the font.
#[inline]
pub fn control_value_table(&self) -> &[u8] {
match self.tables.cvt {
None => &[],
Some(cvt) => cvt.bytes,
}
}
/// Returns the font program, which is run whenever the font is loaded.
#[inline]
pub fn font_program(&self) -> &[u8] {
match self.tables.fpgm {
None => &[],
Some(fpgm) => fpgm.bytes,
}
}
}
#[derive(Clone, Copy, PartialEq, Debug)]

438
src/hinting.rs Normal file
View File

@ -0,0 +1,438 @@
// Copyright 2017 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(dead_code)]
//! The TrueType hinting VM.
//!
//! See: https://www.microsoft.com/typography/otspec/ttinst.htm
use byteorder::{BigEndian, ByteOrder};
use error::HintingError;
use euclid::Point2D;
use font::Font;
/// A TrueType hinting virtual machine.
pub struct Hinter {
// The Control Value Table: the VM's initialized memory.
control_value_table: Vec<i16>,
// The Storage Area: the VM's uninitialized memory.
storage_area: Vec<u32>,
// The projection vector, in 2.14 fixed point.
projection_vector: Point2D<i16>,
// The dual projection vector, in 2.14 fixed point.
dual_projection_vector: Point2D<i16>,
// The freedom vector, in 2.14 fixed point.
freedom_vector: Point2D<i16>,
// The reference point indices.
reference_points: [u32; 3],
// The zone numbers.
zone_points: [u32; 3],
// The round state.
round_state: RoundState,
// The loop variable count.
loop_count: u32,
// The minimum distance value.
minimum_distance: u32,
// Instruction control flags.
instruction_control: InstructionControl,
// Threshold value for ppem. See `SCANCTRL` (ttinst1.doc, 244-245).
dropout_threshold: u8,
// Special dropout control.
dropout_control: DropoutControl,
// The scan type. See `SCANTYPE` (ttinst1.doc, 246-247).
scan_type: ScanType,
// The control value cut in. See `SCVTSI` (ttinst1.doc, 249).
control_value_cut_in: u32,
// The single width cut in. See `SSWCI` (ttinst1.doc, 250).
single_width_cut_in: u32,
// The single width value. See `SSW` (ttinst1.doc, 251).
single_width_value: i32,
// The angle weight. Per spec, does nothing. See `SANGW` (ttinst1.doc, 254).
angle_weight: u32,
// The delta base. See `SDB` (ttinst1.doc, 255).
delta_base: u32,
// The delta shift. See `SDS` (ttinst1.doc, 256).
delta_shift: u32,
// Various graphics state flags.
graphics_state_flags: GraphicsStateFlags,
}
impl Hinter {
pub fn new(font: &Font) -> Result<Hinter, HintingError> {
let cvt = font.control_value_table().chunks(2).map(BigEndian::read_i16).collect();
let hinter = Hinter {
control_value_table: cvt,
storage_area: vec![],
projection_vector: Point2D::zero(),
dual_projection_vector: Point2D::zero(),
freedom_vector: Point2D::zero(),
reference_points: [0; 3],
zone_points: [0; 3],
round_state: RoundState::RoundToHalfGrid,
loop_count: 0,
minimum_distance: 0,
instruction_control: InstructionControl::empty(),
dropout_threshold: 0,
dropout_control: DropoutControl::empty(),
scan_type: ScanType::SimpleDropoutControlIncludingStubs,
control_value_cut_in: 0,
single_width_cut_in: 0,
single_width_value: 0,
angle_weight: 0,
delta_base: 0,
delta_shift: 0,
graphics_state_flags: AUTO_FLIP,
};
Ok(hinter)
}
}
// All TrueType instructions.
#[derive(Clone, Copy, Debug)]
enum Instruction<'a> {
// Push N Bytes (0x40) (ttinst1.doc, p. 189)
Npushb(&'a [u8]),
// Push N Words (0x41) (ttinst1.doc, p. 190)
Npushw(&'a [u8]),
// Push Bytes (0xb0-0xb7) (ttinst1.doc, p. 191)
Pushb(u8, &'a [u8]),
// Push Words (0xb8-0xbf) (ttinst1.doc, p. 192)
Pushw(u8, &'a [u8]),
// Read Store (0x43) (ttinst1.doc, p. 194)
Rs,
// Write Store (0x42) (ttinst1.doc, p. 195)
Ws,
// Write Control Value Table in Pixel Units (0x44) (ttinst1.doc, 197)
Wcvtp,
// Write Control Value Table in FUints (0x70) (ttinst1.doc, 198)
Wcvtf,
// Read Control Value Table (0x45) (ttinst1.doc, 199)
Rcvt,
// Set Freedom and Projection Vectors to Coordinate Axis (0x00-0x01) (ttinst1.doc, 202)
Svtca(Axis),
// Set Projection Vector to Coordinate Axis (0x02-0x03) (ttinst1.doc, 203)
Spvtca(Axis),
// Set Freedom Vector to Coordinate Axis (0x04-0x05) (ttinst1.doc, 204)
Sfvtca(Axis),
// Set Projection Vector to Line (0x06-0x07) (ttinst1.doc, 205-207)
Spvtl(LineOrientation),
// Set Freedom Vector to Line (0x08-0x09) (ttinst1.doc, 208-209)
Sfvtl(LineOrientation),
// Set Freedom Vector to Projection Vector (0x0e) (ttinst1.doc, 210)
Sfvtpv,
// Set Dual Projection Vector to Line (0x86-0x87) (ttinst1.doc, 211)
Sdpvtl(LineOrientation),
// Set Projection Vector From Stack (0x0a) (ttinst1.doc, 212-213)
Spvfs,
// Set Freedom Vector From Stack (0x0b) (ttinst1.doc, 214-215)
Sfvfs,
// Get Projection Vector (0x0c) (ttinst1.doc, 216-217)
Gpv,
// Get Freedom Vector (0x0d) (ttinst1.doc, 218-219)
Gfv,
// Set Reference Point 0 (0x10) (ttinst1.doc, 220)
Srp0,
// Set Reference Point 1 (0x11) (ttinst1.doc, 221)
Srp1,
// Set Reference Point 2 (0x12) (ttinst1.doc, 222)
Srp2,
// Set Zone Pointer 0 (0x13) (ttinst1.doc, 223)
Szp0,
// Set Zone Pointer 1 (0x14) (ttinst1.doc, 224)
Szp1,
// Set Zone Pointer 2 (0x15) (ttinst1.doc, 225)
Szp2,
// Set Zone Pointers (0x16) (ttinst1.doc, 226)
Szps,
// Round to Half Grid (0x19) (ttinst1.doc, 227)
Rthg,
// Round to Grid (0x18) (ttinst1.doc, 228)
Rtg,
// Round to Double Grid (0x3d) (ttinst1.doc, 229)
Rtdg,
// Round Down to Grid (0x7d) (ttinst1.doc, 230)
Rdtg,
// Round Up to Grid (0x7c) (ttinst1.doc, 231)
Rutg,
// Round Off (0x7a) (ttinst1.doc, 232)
Roff,
// Super Round (0x76) (ttinst1.doc, 233-238)
Sround,
// Super Round 45 Degrees (0x77) (ttinst1.doc, 239)
S45round,
// Set Loop Variable (0x17) (ttinst1.doc, 240)
Sloop,
// Set Minimum Distance (0x1a) (ttinst1.doc, 241)
Smd,
// Instruction Execution Control (0x8e) (ttinst1.doc, 242-243)
Instctrl,
// Scan Conversion Control (0x85) (ttinst1.doc, 244-245)
Scanctrl,
// Set Control Value Table Cut In (0x1d) (ttinst1.doc, 249)
Scvtci,
// Set Single Width Cut In (0x1e) (ttinst1.doc, 250)
Sswci,
// Set Single Width (0x1f) (ttinst1.doc, 251)
Ssw,
// Set Auto Flip Boolean to On (0x4d) (ttinst1.doc, 252)
Flipon,
// Set Auto Flip Boolean to Off (0x4e) (ttinst1.doc, 253)
Flipoff,
// Set Angle Weight (0x7e) (ttinst1.doc, 254)
Sangw,
// Set Delta Base (0x5e) (ttinst1.doc, 255)
Sdb,
// Set Delta Shift (0x5f) (ttinst1.doc, 256)
Sds,
// Get Coordinate (0x46-0x47) (ttinst1.doc, 258-259)
Gc(WhichPosition),
// Set Coordinate From Stack (0x48) (ttinst1.doc, 260)
Scfs,
// Measure Distance (0x49-0x4a) (ttinst1.doc, 261-262)
Md(WhichPosition),
// Measure Pixels Per Em (0x4b) (ttinst1.doc, 263)
Mppem,
// Measure Point Size (0x4c) (ttinst1.doc, 264)
Mps,
// Flip Point (0x80) (ttinst2.doc, 263)
Flippt,
// Flip Range On (0x81) (ttinst2.doc, 264)
Fliprgon,
// Flip Range Off (0x82) (ttinst2.doc, 265)
Fliprgoff,
// Shift Point by Last Point (0x32-0x33) (ttinst2.doc, 266)
Shp(ZonePoint),
// Shift Contour by Last Point (0x34-0x35) (ttinst2.doc, 267)
Shc(ZonePoint),
// Shift Zone by Last Point (0x36-0x37) (ttinst2.doc, 268)
Shz(ZonePoint),
// Shift Point by Pixel Amount (0x38) (ttinst2.doc, 269)
Shpix,
// Move Stack Indirect Relative Point (0x3a-0x3b) (ttinst2.doc, 270)
Msirp(SetRP0),
// Move Direct Absolute Point (0x2e-0x2f) (ttinst2.doc, 271)
Mdap(ShouldRound),
// Move Indirect Absolute Point (0x3e-0x3f) (ttinst2.doc, 272-275)
Miap(ShouldRound),
// Move Direct Relative Point (0xc0-0xdf) (ttinst2.doc, 276-283)
Mdrp(SetRP0, ApplyMinimumDistance, ShouldRound, DistanceType),
// Align Relative Point (0x3c) (ttinst2.doc, 284)
Alignrp,
// Move Point to Intersection of Two Lines (0x0f) (ttinst2.doc, 286-288)
Isect,
// Align Points (0x27) (ttinst2.doc, 289)
Alignpts,
// Interpolate Point by Last Relative Stretch (0x39) (ttinst2.doc, 290)
Ip,
// Untouch Point (0x29) (ttinst2.doc, 291)
Utp,
// Interpolate Untouched Points Through Outline (0x30-0x31) (ttinst2.doc, 292)
Iup(Axis),
// Delta Exception P1 (0x5d) (ttinst2.doc, 296)
Deltap1,
// Delta Exception P2 (0x71) (ttinst2.doc, 297)
Deltap2,
// Delta Exception P3 (0x72) (ttinst2.doc, 298)
Deltap3,
// Delta Exception C1 (0x73) (ttinst2.doc, 299)
Deltac1,
// Delta Exception C2 (0x74) (ttinst2.doc, 300)
Deltac2,
// Delta Exception C3 (0x75) (ttinst2.doc, 301)
Deltac3,
// Duplicate Top Stack Element (0x20) (ttinst2.doc, 304)
Dup,
// Pop Top Stack Element (0x21) (ttinst2.doc, 305)
Pop,
// Clear the Entire Stack (0x22) (ttinst2.doc, 306)
Clear,
// Swap the Top Two Elements on the Stack (0x23) (ttinst2.doc, 307)
Swap,
// Return the Depth of the Stack (0x24) (ttinst2.doc, 308)
Depth,
// Copy an Indexed Element to the Top of the Stack (0x25) (ttinst2.doc, 309)
Cindex,
// Move an Indexed Element to the Top of the Stack (0x26) (ttinst2.doc, 310)
Mindex,
// Roll the Top Three Stack Elements (0x8a) (ttinst2.doc, 311)
Roll,
// If Test (0x58) (ttinst2.doc, 313-314)
If,
// Else (0x1b) (ttinst2.doc, 315)
Else,
// End If (0x59) (ttinst2.doc, 316)
EIf,
// Jump Relative on True (0x78) (ttinst2.doc, 317-318)
Jrot,
// Jump (0x1c) (ttinst2.doc, 319)
Jmpr,
// Jump Relative on False (0x79) (ttinst2.doc, 320-321)
Jrof,
// Less Than (0x50) (ttinst2.doc, 323)
Lt,
// Less Than or Equal (0x51) (ttinst2.doc, 324)
Lteq,
// Greater Than (0x52) (ttinst2.doc, 325)
Gt,
// Greater Than or Equal (0x53) (ttinst2.doc, 326)
Gteq,
// Equal (0x54) (ttinst2.doc, 327)
Eq,
// Not Equal (0x55) (ttinst2.doc, 328)
Neq,
// Odd (0x56) (ttinst2.doc, 329)
Odd,
// Even (0x57) (ttinst2.doc, 330)
Even,
// Logical And (0x5a) (ttinst2.doc, 331-332)
And,
// Logical Or (0x5b) (ttinst2.doc, 333)
Or,
// Logical Not (0x5c) (ttinst2.doc, 334)
Not,
// Add (0x60) (ttinst2.doc, 336)
Add,
// Subtract (0x61) (ttinst2.doc, 337)
Sub,
// Divide (0x62) (ttinst2.doc, 338)
Div,
// Multiply (0x63) (ttinst2.doc, 339)
Mul,
// Absolute Value (0x64) (ttinst2.doc, 340)
Abs,
// Negate (0x65) (ttinst2.doc, 341)
Neg,
// Floor (0x66) (ttinst2.doc, 342)
Floor,
// Ceiling (0x67) (ttinst2.doc, 343)
Ceiling,
// Maximum of Top Two Stack Elements (0x8b) (ttinst2.doc, 344)
Max,
// Minimum of Top Two Stack Elements (0x8c) (ttinst2.doc, 345)
Min,
// Round Value (0x68-0x6b) (ttinst2.doc, 347)
Round(DistanceType),
// No Rounding of Value (0x6c-0x6f) (ttinst2.doc, 349)
Nround(DistanceType),
// Function Definition (0x2c) (ttinst2.doc, 351)
Fdef,
// End Function Definition (0x2d) (ttinst2.doc, 352)
Endf,
// Call Function (0x2b) (ttinst2.doc, 353)
Call,
// Loop and Call Function (0x2a) (ttinst2.doc, 354)
Loopcall,
// Instruction Definition (0x89) (ttinst2.doc, 355)
Idef,
// Debug Call (0x4f) (ttinst2.doc, 356)
Debug,
// Get Information (0x88) (ttinst2.doc, 357-360)
Getinfo,
// Get Variation (0x91) (ttinst2.doc, 361)
Getvariation,
}
#[derive(Copy, Clone, Debug)]
#[repr(u8)]
enum Axis {
Y = 0,
X = 1,
}
#[derive(Copy, Clone, Debug)]
#[repr(u8)]
enum LineOrientation {
Parallel = 0,
Perpendicular = 1,
}
#[derive(Copy, Clone, Debug)]
#[repr(u8)]
enum RoundState {
RoundToHalfGrid = 0,
RoundToGrid = 1,
RoundToDoubleGrid = 2,
RoundDownToGrid = 3,
RoundUpToGrid = 4,
RoundOff = 5,
}
#[derive(Copy, Clone, Debug)]
#[repr(u8)]
enum WhichPosition {
// Use the current position.
Current = 0,
// Use the position in the original outline.
Original = 1,
}
bitflags! {
flags InstructionControl: u8 {
const INHIBIT_GRID_FITTING = 1 << 0,
const IGNORE_CVT_PARAMETERS = 1 << 1,
const NATIVE_SUBPIXEL_AA = 1 << 2,
}
}
bitflags! {
flags DropoutControl: u8 {
const DROPOUT_IF_PPEM_LESS_THAN_THRESHOLD = 1 << 0,
const DROPOUT_IF_ROTATED = 1 << 1,
const DROPOUT_IF_STRETCHED = 1 << 2,
const NO_DROPOUT_IF_PPEM_GREATER_THAN_THRESHOLD = 1 << 3,
const NO_DROPOUT_IF_UNROTATED = 1 << 4,
const NO_DROPOUT_IF_UNSTRETCHED = 1 << 5,
}
}
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
enum ScanType {
SimpleDropoutControlIncludingStubs = 0,
SimpleDropoutControlExcludingStubs = 1,
NoDropoutControl = 2,
SmartDropoutControlIncludingStubs = 3,
SmartDropoutControlExcludingStubs = 4,
}
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
enum ZonePoint {
Zone1Point2 = 0,
Zone0Point1 = 1,
}
#[derive(Copy, Clone, PartialEq, Debug)]
struct SetRP0(pub bool);
#[derive(Copy, Clone, PartialEq, Debug)]
struct ApplyMinimumDistance(pub bool);
#[derive(Copy, Clone, PartialEq, Debug)]
struct ShouldRound(pub bool);
// See `MDRP` (ttinst2.doc, 277)
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
enum DistanceType {
Gray = 0,
Black = 1,
White = 2,
}
bitflags! {
flags GraphicsStateFlags: u8 {
// See `FLIPON` (default true) (ttinst1.doc, 252).
const AUTO_FLIP = 1 << 1,
}
}

View File

@ -93,6 +93,7 @@ pub mod charmap;
pub mod coverage;
pub mod error;
pub mod font;
pub mod hinting;
pub mod outline;
pub mod rasterizer;
pub mod shaper;

View File

@ -124,8 +124,9 @@ impl<'a> GlyfTable<'a> {
// Now parse the contours.
let (mut position, mut point_index) = (Point2D::new(0, 0), 0);
for _ in 0..number_of_contours {
let contour_point_count = try!(endpoints_reader.read_u16::<BigEndian>()
.map_err(FontError::eof)) - point_index + 1;
let contour_point_count =
try!(endpoints_reader.read_u16::<BigEndian>().map_err(FontError::eof)) -
point_index + 1;
let mut first_on_curve_point = None;
let mut initial_off_curve_point = None;
@ -143,7 +144,8 @@ impl<'a> GlyfTable<'a> {
delta.x = -delta.x
}
} else if !flags.contains(THIS_X_IS_SAME) {
delta.x = try!(x_coordinate_reader.read_i16::<BigEndian>().map_err(FontError::eof))
delta.x = try!(x_coordinate_reader.read_i16::<BigEndian>()
.map_err(FontError::eof))
}
if flags.contains(Y_SHORT_VECTOR) {
delta.y = try!(y_coordinate_reader.read_u8().map_err(FontError::eof)) as i16;
@ -151,7 +153,8 @@ impl<'a> GlyfTable<'a> {
delta.y = -delta.y
}
} else if !flags.contains(THIS_Y_IS_SAME) {
delta.y = try!(y_coordinate_reader.read_i16::<BigEndian>().map_err(FontError::eof))
delta.y = try!(y_coordinate_reader.read_i16::<BigEndian>()
.map_err(FontError::eof))
}
if last_point_was_off_curve && !flags.contains(ON_CURVE) {
@ -267,13 +270,19 @@ impl<'a> GlyfTable<'a> {
transform.m00 = scale;
transform.m11 = scale;
} else if flags.contains(WE_HAVE_AN_X_AND_Y_SCALE) {
transform.m00 = F2Dot14(try!(reader.read_i16::<BigEndian>().map_err(FontError::eof)));
transform.m11 = F2Dot14(try!(reader.read_i16::<BigEndian>().map_err(FontError::eof)));
transform.m00 = F2Dot14(try!(reader.read_i16::<BigEndian>()
.map_err(FontError::eof)));
transform.m11 = F2Dot14(try!(reader.read_i16::<BigEndian>()
.map_err(FontError::eof)));
} else if flags.contains(WE_HAVE_A_TWO_BY_TWO) {
transform.m00 = F2Dot14(try!(reader.read_i16::<BigEndian>().map_err(FontError::eof)));
transform.m01 = F2Dot14(try!(reader.read_i16::<BigEndian>().map_err(FontError::eof)));
transform.m10 = F2Dot14(try!(reader.read_i16::<BigEndian>().map_err(FontError::eof)));
transform.m11 = F2Dot14(try!(reader.read_i16::<BigEndian>().map_err(FontError::eof)));
transform.m00 = F2Dot14(try!(reader.read_i16::<BigEndian>()
.map_err(FontError::eof)));
transform.m01 = F2Dot14(try!(reader.read_i16::<BigEndian>()
.map_err(FontError::eof)));
transform.m10 = F2Dot14(try!(reader.read_i16::<BigEndian>()
.map_err(FontError::eof)));
transform.m11 = F2Dot14(try!(reader.read_i16::<BigEndian>()
.map_err(FontError::eof)));
}
if let Some(offset) = try!(loca_table.location_of(head_table, glyph_index)) {
@ -332,7 +341,8 @@ fn calculate_size_of_x_coordinates<'a, 'b>(reader: &'a mut &'b [u8], number_of_p
-> Result<u16, FontError> {
let (mut x_coordinate_length, mut points_left) = (0, number_of_points);
while points_left > 0 {
let flags = SimpleFlags::from_bits_truncate(try!(reader.read_u8().map_err(FontError::eof)));
let flags = SimpleFlags::from_bits_truncate(try!(reader.read_u8()
.map_err(FontError::eof)));
let repeat_count = if !flags.contains(REPEAT) {
1
} else {

View File

@ -10,6 +10,28 @@
//! OpenType fonts.
// These tables need no parsing and so don't need separate files.
pub mod cvt {
pub const TAG: u32 = ((b'c' as u32) << 24) |
((b'v' as u32) << 16) |
((b't' as u32) << 8) |
(b' ' as u32);
}
pub mod fpgm {
pub const TAG: u32 = ((b'f' as u32) << 24) |
((b'p' as u32) << 16) |
((b'g' as u32) << 8) |
(b'm' as u32);
}
pub mod prep {
pub const TAG: u32 = ((b'p' as u32) << 24) |
((b'r' as u32) << 16) |
((b'e' as u32) << 8) |
(b'p' as u32);
}
pub mod cff;
pub mod cmap;
pub mod glyf;