Module Otfm
OpenType font decoder.
WARNING. This interface is subject to change in the future.
Otfm is an in-memory decoder for the OpenType font data format. It provides low-level access to OpenType fonts tables and functions to decode some of them.
Consult the limitations and example of use.
Note. Unless otherwise specified the strings returned are UTF-8 encoded.
v0.3.0 - homepage
References
- Microsoft. The OpenType Specification, 2009.
Tags
module Tag : sig ... endTags.
Unicode code points
For some reason OpenType allows the (textually meaningless) surrogate code points to be mapped to glyphs. Hence we deal with Unicode code points not scalar values.
type cp= intThe type for Unicode code points, ranges from
0x0000to0x10_FFFF. Any code point returned byOtfmis guaranteed to be in the range.
type cp_range= cp * cpThe type for Unicode code point ranges. Any range
(u0, u1)returned byOtfmhasu0 <= u1.
val is_cp : int -> boolis_cp iistrueifiis an Unicode code point.
val pp_cp : Stdlib.Format.formatter -> cp -> unitpp_cp ppf cpprints an unspecified representation ofcponppf.
Decode
type error_ctx=[|`Table of tag|`Offset_table|`Table_directory]The type for error contexts.
type error=[|`Unknown_flavour of tag|`Unsupported_TTC|`Unsupported_cmaps of (int * int * int) list|`Unsupported_glyf_matching_points|`Missing_required_table of tag|`Unknown_version of error_ctx * int32|`Unknown_loca_format of error_ctx * int|`Unknown_composite_format of error_ctx * int|`Invalid_offset of error_ctx * int|`Invalid_cp of int|`Invalid_cp_range of int * int|`Invalid_postscript_name of string|`Unexpected_eoi of error_ctx]The type for decoding errors.
Note. In case of
`Invalid_poscript_namea string of bytes is returned.
val pp_error : Stdlib.Format.formatter -> [< error ] -> unitpp_error ppf eprints an uspecified representation ofeonppf.
Table decoding
These functions can be used in any order and are robust: when they return an error the decoder is back to a consistant state and can be used further. However if flavour or table_list returns an error you can safely assume that all other functions will. The fields are in general not documented please refer to the OpenType specification for details.
val flavour : decoder -> (flavour, error) Result.resultdecode_flavour dis the flavour of the font decoded byd.
val table_list : decoder -> (tag list, error) Result.resulttable_list tis the list of tables of the font decoded byd.
val table_mem : decoder -> tag -> (bool, error) Result.resulttable_mem d tistrueif tabletis in the font decoded byd.
val table_raw : decoder -> tag -> (string option, error) Result.resulttable_raw d tis the (unpadded) data of the tabletas a string if the tabletexists.
Convenience decodes
These functions lookup data in the right table.
val glyph_count : decoder -> (int, error) Result.resultglyph_count dis the number of glyphs in the font (bounded by65535).
val postscript_name : decoder -> (string option, error) Result.resultposcript_name dis the PostScript name ofd. Looks up and validates as mandated by the OTF standard, don't rely on name table if you really need this information.
cmap table
type map_kind=[|`Glyph|`Glyph_range]The type for map kinds.
Determines how an unicode range
(u0, u1)and a glyph idgidmust be interpreted in the folding function of cmap table.`Glyphall characters in the range map to togid.`Glyph_range,u0maps togid,u0 + 1togid + 1, ... andu1togid + (u1 - u0)
val cmap : decoder -> ('a -> map_kind -> cp_range -> glyph_id -> 'a) -> 'a -> ((int * int * int) * 'a, error) Result.resultcmap d f accfolds over a mapping from unicode scalar values to glyph ids by reading the cmap table. The returned triple of integer indicates the platform id, encoding id and format of the cmap used.Limitations. Only the format 13 (last resort font), format 12 (UCS-4) and format 4 (UCS-2) cmap table formats are supported.
If multiple tables are present, it favours 13 over 12 over 4. If multiple tables of the same format are present it takes the first one it finds.
If no supported cmap table is found the error
`Unsupported_cmapsis returned with the list of platform id, encoding id, format available in the font.
glyf table
type glyf_locThe type for glyph locations. See loca table table.
type glyph_simple_descr= (bool * int * int) list listThe type for simple glyph descriptions. Lists of contours, contours are list of points with a boolean indicating whether the point is on or off curve.
type glyph_composite_descr= (glyph_id * (int * int) * (float * float * float * float) option) listThe type for glyph composites. A list of components made of a glyph id, a translation and an optional linear transform
a b c d(column major).
type glyph_descr= [ `Simple of glyph_simple_descr | `Composite of glyph_composite_descr ] * (int * int * int * int)The type for glyph descriptions. A simple or composite descriptions with the glyph's
(minx, miny, maxx, maxy)'s bounding box.
val glyf : decoder -> glyf_loc -> (glyph_descr, error) Result.resultglyf d locis the glyph descroption located atlocby reading the glyf table. Glyph locations are obtainted via loca table.
head table
type head={}The type for representing head tables.
val head : decoder -> (head, error) Result.resulthead dis the head table.
hhea table
type hhea={}The type for hhea tables.
val hhea : decoder -> (hhea, error) Result.resulthhea dis the hhea table.
hmtx table
val hmtx : decoder -> ('a -> glyph_id -> int -> int -> 'a) -> 'a -> ('a, error) Result.resulthmtx d f accfolds over the horizontal metrics of the font by reading the hmtx table.fis applied on each entry withf acc' gid adv lsbwithgidthe glyph id (guaranteed to range, in order, from0to glyph count minus one),advthe (unsigned) advance width, andlsbthe (signed) left side bearing.
name table
type lang= stringThe type for BCP 47 language tags.
val name : decoder -> ('a -> int -> lang -> string -> 'a) -> 'a -> ('a, error) Result.resultname d f accfolds over the name records of the font by reading the name table.fis applied on each name id entry withf acc' nid lang namewithnidthe name id, lang the language tag, andnamethe UTF-8 encoded name value.Note. The module normalizes Windows language ids to lowercased BCP 47 ids. Language tags found in language tag records should be BCP 47 language tags but are not checked for conformance.
Tip. If you are looking for the postcript name use
postscript_name.Limitations. Lookups data only in platform ids 0, 2 and 3 (Unicode, ISO and Windows) with UTF-16BE encoding and reports only the data of the first one it finds for a given name id.
OS/2 table
type os2={}The type for OS/2 tables.
val os2 : decoder -> (os2, error) Result.resultos2 dis the OS/2 table.
kern table
type kern_info={kern_dir : [ `H | `V ];kern_kind : [ `Min | `Kern ];kern_cross_stream : bool;}The type for kerning (sub)table information.
val kern : decoder -> ('a -> kern_info -> [ `Skip | `Fold ] * 'a) -> ('a -> glyph_id -> glyph_id -> int -> 'a) -> 'a -> ('a, error) Result.resultkern d t p accfolds over the kerning tables ofdby reading the kern table.tis called on each new (sub)table, the table pairs are skipped if it returns`Skipotherwisep acc' left right valueis called on each kerning pair of the table. The function returnsaccif there is no kern table.Limitations. Only format 0 kerning tables are supported.
loca table
Limitations
As it stands Otfm has the following limitations. Some of these may be lifted in the future and a few of these can be overcome by pre-processing your font (e.g. extract .ttc files to .ttf, or removing hinting information to reduce the font size). See also the individual table decoding functions for other limitations.
- True Type collections (
.ttcfiles) are not supported - The whole font needs to be loaded in memory as a string. This may be a limiting factor on 32 bits platforms (but non
.ttcfont files tend to be smaller than 16 Mo). - Table checksums are not verified.
Examples
The following code prints the postscript name of the font on stdout.
let otf_postscript_name bytes =
let d = Otfm.decoder (`String bytes) in
match Otfm.postscript_name d with
| Error e -> Format.eprintf "@[%a@]@." Otfm.pp_error e
| Ok (Some n) -> Format.printf "%s@." n;
| Ok None -> ()