CffTable.vala
/*
Copyright (C) 2012, 2013 Johan Mattsson
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 3 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
*/
namespace BirdFont {
/** Type2, PostScript outlines */
public class CffTable : OtfTable {
const uint8 HSTEM = 1;
const uint8 VSTEM = 3;
const uint8 VMOVETO = 4;
const uint8 HLINETO = 6;
const uint8 VLINETO = 7;
const uint8 ENDCHAR = 14;
const uint8 HMOVETO = 22;
const uint8 RMOVETO = 21;
const uint8 CHARSET = 15;
const uint8 ENCODING = 16;
const uint8 VERSION = 0;
public int version;
FontData dis;
public CffTable () {
id = "CFF ";
}
uint32 read_offset (uint size) throws GLib.Error {
switch (size) {
case 0:
warning ("offset size is zero");
return dis.read_byte ();
case 1:
return dis.read_byte ();
case 2:
return dis.read_ushort ();
case 4:
return dis.read_ulong ();
default:
warn_if_reached ();
break;
}
warning ("offset size is zero");
return 0;
}
Gee.ArrayList<uint32> read_index () throws Error {
uint32 offset_size, off;
int entries;
Gee.ArrayList<uint32> offsets = new Gee.ArrayList<uint32> ();
entries = dis.read_ushort ();
printd (@"number of entries $(entries)\n");
if (entries == 0) {
printd ("skip index");
return offsets;
}
offset_size = dis.read ();
printd (@"Offset size $(offset_size)\n");
// read the end offset as well
for (int i = 0; i <= entries; i++) {
off = read_offset (offset_size);
printd (@"offset $(off)\n");
offsets.add (off);
}
return offsets;
}
public override void parse (FontData dis) throws Error {
uint v1, v2, offset_size, header_size, len;
string data;
Gee.ArrayList<uint32> offsets, dict_index;
int id, val;
int off; // offset relative to table position
dis.seek (offset);
this.dis = dis;
printd ("Parse CFF.\n");
v1 = dis.read ();
v2 = dis.read ();
printd (@"Version $v1.$v2\n");
header_size = dis.read ();
printd (@"Header size $(header_size)\n");
offset_size = dis.read ();
printd (@"Offset size $(offset_size)\n");
// name index
offsets = read_index ();
// name data
for (int i = 0; i < offsets.size - 1; i++) {
off = (int) offsets.get (i);
len = offsets.get (i + 1) - off;
//dis.seek (offset + off + header_size);
data = dis.read_string (len);
}
// dict index
dict_index = read_index ();
// dict data
id = 0;
val = 0;
for (int i = 0; i < dict_index.size - 1; i++) {
off = (int) offsets.get (i);
len = dict_index.get (i + 1) - dict_index.get (i);
//dis.seek (offset + off + header_size);
//for (int j = 0; j < len; j++) {
if (dis.next_is_operator ()) {
id = dis.read ();
if (id == 12) {
id = dis.read ();
} else {
switch (id) {
case 0:
version = val;
break;
default:
stderr.printf ("unknown operator");
break;
}
}
} else {
val = dis.read_charstring_value ();
}
printd (@"$i: id $(id)\n");
printd (@"val $(val)\n");
//printd (@"B $(dis.read ())\n");
//}
}
// string index
read_index ();
}
public void process () throws GLib.Error {
FontData fd = new FontData ();
string name = "typeface";
// header
fd.add_byte (1); // format version (1.0)
fd.add_byte (0);
fd.add_byte (4); // header size
fd.add_byte (2); // offset field size - ushort
// name index:
fd.add_ushort (1); // number of entries
fd.add_byte (2); // offset field size
fd.add_ushort (1); // offset
fd.add ((uint8) name.length); // length of string
fd.add_str (name);
// top dict index
fd.add_ushort (1); // number of entries
fd.add_byte (2); // offset field size
fd.add_ushort (1); // offset
fd.add_ushort (2); // offset
fd.add_charstring_value (0);
fd.add_byte (CHARSET);
// string index
fd.add_byte (0);
// TODO: glyph gid to cid map
fd.add_byte (0);
fd.pad ();
this.font_data = fd;
}
}
}