8 ttffindchar(TTFont *fx, Rune r)
17 if(r < f->cmap[0].start || r > f->cmap[j].end) return 0;
20 if(f->cmap[k].end < r)
22 else if(f->cmap[k].start > r)
29 if(r < p->start || r > p->end) return 0;
30 if((p->flags & TTCINVALID) != 0) return 0;
32 return p->tab[r - p->start];
34 if((p->flags & TTCDELTA16) != 0)
40 ttfenumchar(TTFont *fx, Rune r, Rune *rp)
49 if(r > f->cmap[j].end) return 0;
52 if(f->cmap[k].end < r)
54 else if(f->cmap[k].start > r)
60 for(p = &f->cmap[j]; p < &f->cmap[f->ncmap]; p++){
61 if((p->flags & TTCINVALID) != 0)
67 while(r <= p->end && (rv = p->tab[r - p->start], rv == 0))
77 if((p->flags & TTCDELTA16) != 0)
90 ttfgotosub(TTFontU *f)
93 u16int nsub, id, sid, off;
96 #define SUBID(a,b) ((a)<<16|(b))
98 if(ttfgototable(f, "cmap") < 0)
100 ttfunpack(f, ".. w", &nsub);
103 for(i = 0; i < nsub; i++){
104 ttfunpack(f, "wwl", &id, &sid, &off);
105 switch(id << 16 | sid){
106 case SUBID(0, 4): /* Unicode 2.0 or later (BMP and non-BMP) */
109 case SUBID(0, 0): /* Unicode default */
110 case SUBID(0, 1): /* Unicode 1.1 */
111 case SUBID(0, 2): /* ISO 10646 */
112 case SUBID(0, 3): /* Unicode 2.0 (BMP) */
115 case SUBID(3, 10): /* Windows, UCS-4 */
118 case SUBID(3, 1): /* Windows, UCS-2 */
121 case SUBID(3, 0): /* Windows, Symbol */
134 werrstr("no suitable character table");
137 if(ttfgototable(f, "cmap") < 0)
139 Bseek(f->bin, maxoff, 1);
152 ttfunpack(f, "w2", &len);
154 werrstr("character table too short");
157 f->cmap = mallocz(sizeof(TTChMap), 1);
163 f->cmap->tab = mallocz(256 * sizeof(int), 1);
164 if(f->cmap->tab == nil)
166 Bread(f->bin, f->cmap->tab, 256 * sizeof(int));
167 p = (u8int*)f->cmap->tab + 256;
168 q = f->cmap->tab + 256;
169 for(i = 255; i >= 0; i--)
178 int i, j, n, n0, off;
182 ttfunpack(f, "w2", &len);
184 werrstr("character table too short");
187 ttfunpack(f, "w6", &ncmap);
189 if(len < 16 + 8 * ncmap){
190 werrstr("character table too short");
193 f->cmap = mallocz(sizeof(TTChMap) * ncmap, 1);
194 if(f->cmap == nil) return -1;
196 for(i = 0; i < ncmap; i++)
197 f->cmap[i].flags = TTCDELTA16;
198 for(i = 0; i < ncmap; i++)
199 ttfunpack(f, "W", &f->cmap[i].end);
201 for(i = 0; i < ncmap; i++)
202 ttfunpack(f, "W", &f->cmap[i].start);
203 for(i = 0; i < ncmap; i++)
204 ttfunpack(f, "W", &f->cmap[i].delta);
205 for(i = 0; i < ncmap; i++)
206 ttfunpack(f, "W", &f->cmap[i].temp);
207 len -= 10 + 8 * ncmap;
211 Bread(f->bin, buf, len);
212 for(i = 0; i < ncmap; i++){
213 if(f->cmap[i].temp == 0) continue;
214 n0 = f->cmap[i].end - f->cmap[i].start + 1;
216 off = f->cmap[i].temp - (ncmap - i) * 2;
217 if(off + 2 * n > len) n = (len - off) / 2;
218 if(off < 0 || n <= 0){
219 f->cmap[i].flags |= TTCINVALID;
222 f->cmap[i].tab = mallocz(n0 * sizeof(int), 1);
223 if(f->cmap[i].tab == nil)
225 for(j = 0; j < n; j++){
226 v = buf[off + 2*j] << 8 | buf[off + 2*j + 1];
227 if(v != 0) v += f->cmap[i].delta;
228 f->cmap[i].tab[j] = v;
238 u16int len, first, cnt, v;
242 ttfunpack(f, "w2", &len);
244 werrstr("character table too short");
247 ttfunpack(f, "ww", &first, &cnt);
248 f->cmap = mallocz(sizeof(TTChMap), 1);
252 f->cmap->start = first;
253 f->cmap->end = first + len - 1;
254 f->cmap->tab = mallocz(cnt * sizeof(int), 1);
255 if(f->cmap->tab == nil)
257 if(len < 10 + 2 * cnt){
258 werrstr("character table too short");
261 Bread(f->bin, f->cmap->tab, 2 * cnt);
262 p = f->cmap->tab + cnt;
263 q = (u8int*) f->cmap->tab + 2 * cnt;
264 while(p > f->cmap->tab){
279 ttfunpack(f, "2l4", &len);
281 werrstr("character table too short");
284 ttfunpack(f, "l", &ncmap);
285 if(len < 16 + 12 * ncmap){
286 werrstr("character table too short");
289 f->cmap = mallocz(sizeof(TTChMap) * ncmap, 1);
293 for(i = 0; i < ncmap; i++){
294 ttfunpack(f, "lll", &f->cmap[i].start, &f->cmap[i].end, &f->cmap[i].delta);
295 f->cmap[i].delta -= f->cmap[i].start;
300 int (*cmaphand[])(TTFontU *) = {
308 ttfparsecmap(TTFontU *f)
312 if(ttfgotosub(f) < 0)
314 ttfunpack(f, "w", &format);
315 if(format >= nelem(cmaphand) || cmaphand[format] == nil){
316 werrstr("character table in unknown format %d", format);
319 if(cmaphand[format](f) < 0)