1 /*
2 Copyright (C) 2012, 2013 Johan Mattsson
3
4 This library is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 3 of the
7 License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13 */
14
15 namespace BirdFont {
16
17 /** Type2, PostScript outlines */
18 public class CffTable : OtfTable {
19
20 const uint8 HSTEM = 1;
21 const uint8 VSTEM = 3;
22 const uint8 VMOVETO = 4;
23 const uint8 HLINETO = 6;
24 const uint8 VLINETO = 7;
25 const uint8 ENDCHAR = 14;
26 const uint8 HMOVETO = 22;
27 const uint8 RMOVETO = 21;
28
29 const uint8 CHARSET = 15;
30 const uint8 ENCODING = 16;
31
32 const uint8 VERSION = 0;
33
34 public int version;
35
36 FontData dis;
37
38 public CffTable () {
39 id = "CFF ";
40 }
41
42 uint32 read_offset (uint size) throws GLib.Error {
43 switch (size) {
44 case 0:
45 warning ("offset size is zero");
46 return dis.read_byte ();
47 case 1:
48 return dis.read_byte ();
49 case 2:
50 return dis.read_ushort ();
51 case 4:
52 return dis.read_ulong ();
53 default:
54 warn_if_reached ();
55 break;
56 }
57
58 warning ("offset size is zero");
59 return 0;
60 }
61
62 Gee.ArrayList<uint32> read_index () throws Error {
63 uint32 offset_size, off;
64 int entries;
65 Gee.ArrayList<uint32> offsets = new Gee.ArrayList<uint32> ();
66
67 entries = dis.read_ushort ();
68 printd (@"number of entries $(entries)\n");
69
70 if (entries == 0) {
71 printd ("skip index");
72 return offsets;
73 }
74
75 offset_size = dis.read ();
76 printd (@"Offset size $(offset_size)\n");
77
78 // read the end offset as well
79 for (int i = 0; i <= entries; i++) {
80 off = read_offset (offset_size);
81 printd (@"offset $(off)\n");
82 offsets.add (off);
83 }
84
85 return offsets;
86 }
87
88 public override void parse (FontData dis) throws Error {
89 uint v1, v2, offset_size, header_size, len;
90 string data;
91 Gee.ArrayList<uint32> offsets, dict_index;
92 int id, val;
93 int off; // offset relative to table position
94
95 dis.seek (offset);
96 this.dis = dis;
97
98 printd ("Parse CFF.\n");
99 v1 = dis.read ();
100 v2 = dis.read ();
101 printd (@"Version $v1.$v2\n");
102 header_size = dis.read ();
103 printd (@"Header size $(header_size)\n");
104 offset_size = dis.read ();
105 printd (@"Offset size $(offset_size)\n");
106
107 // name index
108 offsets = read_index ();
109
110 // name data
111 for (int i = 0; i < offsets.size - 1; i++) {
112 off = (int) offsets.get (i);
113 len = offsets.get (i + 1) - off;
114 //dis.seek (offset + off + header_size);
115 data = dis.read_string (len);
116 }
117
118 // dict index
119 dict_index = read_index ();
120
121 // dict data
122 id = 0;
123 val = 0;
124 for (int i = 0; i < dict_index.size - 1; i++) {
125 off = (int) offsets.get (i);
126 len = dict_index.get (i + 1) - dict_index.get (i);
127 //dis.seek (offset + off + header_size);
128
129 //for (int j = 0; j < len; j++) {
130
131 if (dis.next_is_operator ()) {
132 id = dis.read ();
133
134 if (id == 12) {
135 id = dis.read ();
136 } else {
137 switch (id) {
138 case 0:
139 version = val;
140 break;
141 default:
142 stderr.printf ("unknown operator");
143 break;
144 }
145 }
146 } else {
147 val = dis.read_charstring_value ();
148 }
149
150 printd (@"$i: id $(id)\n");
151 printd (@"val $(val)\n");
152 //printd (@"B $(dis.read ())\n");
153 //}
154 }
155
156 // string index
157 read_index ();
158 }
159
160 public void process () throws GLib.Error {
161 FontData fd = new FontData ();
162 string name = "typeface";
163
164 // header
165 fd.add_byte (1); // format version (1.0)
166 fd.add_byte (0);
167
168 fd.add_byte (4); // header size
169 fd.add_byte (2); // offset field size - ushort
170
171 // name index:
172 fd.add_ushort (1); // number of entries
173 fd.add_byte (2); // offset field size
174 fd.add_ushort (1); // offset
175 fd.add ((uint8) name.length); // length of string
176 fd.add_str (name);
177
178 // top dict index
179 fd.add_ushort (1); // number of entries
180 fd.add_byte (2); // offset field size
181 fd.add_ushort (1); // offset
182 fd.add_ushort (2); // offset
183
184 fd.add_charstring_value (0);
185 fd.add_byte (CHARSET);
186
187 // string index
188 fd.add_byte (0);
189
190 // TODO: glyph gid to cid map
191 fd.add_byte (0);
192
193 fd.pad ();
194
195 this.font_data = fd;
196 }
197 }
198
199 }
200