9 #define NGLYPHS (1 << 14)
10 #define NLOOKUPS (1 << 12)
12 #define BUFLEN (1 << 23)
14 #define MAX(a, b) ((a) < (b) ? (b) : (a))
16 #define U32(buf, off) (htonl(*(u32 *) ((buf) + (off))))
17 #define U16(buf, off) (htons(*(u16 *) ((buf) + (off))))
18 #define U8(buf, off) (*(u8 *) ((buf) + (off)))
19 #define S16(buf, off) ((s16) htons(*(u16 *) ((buf) + (off))))
20 #define S32(buf, off) ((s32) htonl(*(u32 *) ((buf) + (off))))
22 #define GCTXLEN 16 /* number of context backtrack coverage arrays */
24 typedef unsigned int u32
;
25 typedef unsigned short u16
;
26 typedef unsigned char u8
;
30 static char glyph_name
[NGLYPHS
][GNLEN
];
31 static int glyph_code
[NGLYPHS
];
32 static int glyph_bbox
[NGLYPHS
][4];
33 static int glyph_wid
[NGLYPHS
];
35 static int upm
; /* units per em */
36 static int res
; /* device resolution */
37 static int kmin
; /* minimum kerning value */
38 static int warn
; /* report unsupported tables */
40 static char *macset
[];
42 static int owid(int w
)
44 return (w
< 0 ? w
* 1000 - upm
/ 2 : w
* 1000 + upm
/ 2) / upm
;
47 static int uwid(int w
)
50 return (w
< 0 ? owid(w
) - d
/ 2 : owid(w
) + d
/ 2) / d
;
53 /* weather the script is right-to-left */
54 static int otf_r2l(char *feat
)
56 char *scrp
= strchr(feat
, ':') + 1;
57 return !strcmp("arab", scrp
) || !strcmp("hebr", scrp
);
60 /* report unsupported otf tables */
61 static void otf_unsupported(char *sub
, int type
, int fmt
)
64 fprintf(stderr
, "neatmkfn: unsupported %s lookup %d", sub
, type
);
66 fprintf(stderr
, " format %d", fmt
);
67 fprintf(stderr
, "\n");
71 /* find the otf table with the given name */
72 static void *otf_table(void *otf
, char *name
)
74 int nrecs
= U16(otf
, 4);
76 for (i
= 0; i
< nrecs
; i
++) {
77 void *rec
= otf
+ 12 + i
* 16; /* an otf table record */
78 if (!strncmp(rec
, name
, 4))
79 return otf
+ U32(rec
, 8);
84 /* obtain postscript font name from name table */
85 static void otf_name(void *otf
, void *tab
)
88 void *str
= tab
+ U16(tab
, 4); /* storage area */
89 int n
= U16(tab
, 2); /* number of name records */
91 for (i
= 0; i
< n
; i
++) {
92 void *rec
= tab
+ 6 + 12 * i
;
93 int pid
= U16(rec
, 0); /* platform id */
94 int eid
= U16(rec
, 2); /* encoding id */
95 int lid
= U16(rec
, 4); /* language id */
96 int nid
= U16(rec
, 6); /* name id */
97 int len
= U16(rec
, 8); /* string length */
98 int off
= U16(rec
, 10); /* string offset */
99 if (pid
== 1 && eid
== 0 && lid
== 0 && nid
== 6) {
100 memcpy(name
, str
+ off
, len
);
107 /* parse otf cmap format 4 subtable */
108 static void otf_cmap4(void *otf
, void *cmap4
)
111 void *ends
, *begs
, *deltas
, *offsets
;
112 int beg
, end
, delta
, offset
;
114 nsegs
= U16(cmap4
, 6) / 2;
116 begs
= ends
+ 2 * nsegs
+ 2;
117 deltas
= begs
+ 2 * nsegs
;
118 offsets
= deltas
+ 2 * nsegs
;
119 for (i
= 0; i
< nsegs
; i
++) {
120 beg
= U16(begs
, 2 * i
);
121 end
= U16(ends
, 2 * i
);
122 delta
= U16(deltas
, 2 * i
);
123 offset
= U16(offsets
, 2 * i
);
125 for (j
= beg
; j
<= end
; j
++)
126 glyph_code
[(U16(offsets
+ 2 * i
,
127 offset
+ (j
- beg
) * 2) + delta
) & 0xffff] = j
;
129 for (j
= beg
; j
<= end
; j
++)
130 glyph_code
[(j
+ delta
) & 0xffff] = j
;
135 /* parse otf cmap header */
136 static void otf_cmap(void *otf
, void *cmap
)
138 int nrecs
= U16(cmap
, 2);
140 for (i
= 0; i
< nrecs
; i
++) {
141 void *rec
= cmap
+ 4 + i
* 8; /* a cmap record */
142 int plat
= U16(rec
, 0);
143 int enc
= U16(rec
, 2);
144 void *tab
= cmap
+ U32(rec
, 4); /* a cmap subtable */
145 int fmt
= U16(tab
, 0);
146 if (plat
== 3 && enc
== 1 && fmt
== 4)
151 static void otf_post(void *otf
, void *post
)
153 void *post2
; /* version 2.0 header */
154 void *index
; /* glyph name indices */
155 void *names
; /* glyph names */
158 if (U32(post
, 0) != 0x00020000)
161 glyph_n
= U16(post2
, 0);
163 names
= index
+ 2 * glyph_n
;
164 for (i
= 0; i
< glyph_n
; i
++) {
165 int idx
= U16(index
, 2 * i
);
167 strcpy(glyph_name
[i
], macset
[idx
]);
169 memcpy(glyph_name
[i
], names
+ cname
+ 1,
171 glyph_name
[i
][U8(names
, cname
)] = '\0';
172 cname
+= U8(names
, cname
) + 1;
177 static void otf_glyf(void *otf
, void *glyf
)
179 void *maxp
= otf_table(otf
, "maxp");
180 void *head
= otf_table(otf
, "head");
181 void *loca
= otf_table(otf
, "loca");
184 int n
= U16(maxp
, 4);
185 int fmt
= U16(head
, 50);
187 for (i
= 0; i
< n
; i
++) {
189 gdat
= glyf
+ U32(loca
, 4 * i
);
190 gdat_next
= glyf
+ U32(loca
, 4 * (i
+ 1));
192 gdat
= glyf
+ U16(loca
, 2 * i
) * 2;
193 gdat_next
= glyf
+ U16(loca
, 2 * (i
+ 1)) * 2;
195 if (gdat
< gdat_next
)
196 for (j
= 0; j
< 4; j
++)
197 glyph_bbox
[i
][j
] = S16(gdat
, 2 + 2 * j
);
201 static void otf_hmtx(void *otf
, void *hmtx
)
203 void *hhea
= otf_table(otf
, "hhea");
207 for (i
= 0; i
< n
; i
++)
208 glyph_wid
[i
] = U16(hmtx
, i
* 4);
209 for (i
= n
; i
< glyph_n
; i
++)
210 glyph_wid
[i
] = glyph_wid
[n
- 1];
213 static void otf_kern(void *otf
, void *kern
)
217 int n
= U16(kern
, 2); /* number of kern subtables */
218 for (i
= 0; i
< n
; i
++) {
219 void *tab
= kern
+ off
; /* a kern subtable */
220 int cov
= U16(tab
, 4);
222 if ((cov
>> 8) == 0 && (cov
& 1)) { /* format 0 */
223 int npairs
= U16(tab
, 6);
224 for (j
= 0; j
< npairs
; j
++) {
225 int c1
= U16(tab
, 14 + 6 * j
);
226 int c2
= U16(tab
, 14 + 6 * j
+ 2);
227 int val
= S16(tab
, 14 + 6 * j
+ 4);
228 trfn_kern(glyph_name
[c1
], glyph_name
[c2
],
235 static int coverage(void *cov
, int *out
)
237 int fmt
= U16(cov
, 0);
243 for (i
= 0; i
< n
; i
++)
244 out
[ncov
++] = U16(cov
, 4 + 2 * i
);
247 for (i
= 0; i
< n
; i
++) {
248 beg
= U16(cov
, 4 + 6 * i
);
249 end
= U16(cov
, 4 + 6 * i
+ 2);
250 for (j
= beg
; j
<= end
; j
++)
257 static int classdef(void *tab
, int *gl
, int *cls
)
259 int fmt
= U16(tab
, 0);
263 int beg
= U16(tab
, 2);
265 for (i
= 0; i
< ngl
; i
++) {
267 cls
[i
] = U16(tab
, 6 + 2 * i
);
272 for (i
= 0; i
< n
; i
++) {
273 int beg
= U16(tab
, 4 + 6 * i
);
274 int end
= U16(tab
, 4 + 6 * i
+ 2);
275 for (j
= beg
; j
<= end
; j
++) {
277 cls
[ngl
] = U16(tab
, 4 + 6 * i
+ 4);
285 static int intcmp(void *v1
, void *v2
)
287 return *(int *) v1
- *(int *) v2
;
290 int ggrp_make(int *src
, int n
);
292 static int ggrp_class(int *src
, int *cls
, int nsrc
, int id
)
297 for (i
= 0; i
< nsrc
; i
++)
300 qsort(g
, n
, sizeof(g
[0]), (void *) intcmp
);
301 return ggrp_make(g
, n
);
304 static int ggrp_coverage(int *g
, int n
)
306 qsort(g
, n
, sizeof(g
[0]), (void *) intcmp
);
307 return ggrp_make(g
, n
);
310 static int valuerecord_len(int fmt
)
314 for (i
= 0; i
< 8; i
++)
320 static void valuerecord_print(int fmt
, void *rec
)
325 for (i
= 0; i
< 8; i
++) {
326 if (fmt
& (1 << i
)) {
327 vals
[i
] = uwid(S16(rec
, off
));
332 printf(":%+d%+d%+d%+d", vals
[0], vals
[1], vals
[2], vals
[3]);
335 static int valuerecord_small(int fmt
, void *rec
)
339 for (i
= 0; i
< 8; i
++) {
340 if (fmt
& (1 << i
)) {
341 if (abs(uwid(S16(rec
, off
))) >= MAX(1, kmin
))
349 /* single adjustment positioning */
350 static void otf_gpostype1(void *otf
, void *sub
, char *feat
)
352 int fmt
= U16(sub
, 0);
353 int vfmt
= U16(sub
, 4);
356 int vlen
= valuerecord_len(vfmt
);
358 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
360 for (i
= 0; i
< ncov
; i
++) {
361 if (valuerecord_small(vfmt
, sub
+ 6))
363 printf("gpos %s 1 %s", feat
, glyph_name
[cov
[i
]]);
364 valuerecord_print(vfmt
, sub
+ 6);
370 for (i
= 0; i
< nvals
; i
++) {
371 if (valuerecord_small(vfmt
, sub
+ 6))
373 printf("gpos %s 1 %s", feat
, glyph_name
[cov
[i
]]);
374 valuerecord_print(vfmt
, sub
+ 8 + i
* vlen
);
380 /* pair adjustment positioning */
381 static void otf_gpostype2(void *otf
, void *sub
, char *feat
)
383 int fmt
= U16(sub
, 0);
384 int vfmt1
= U16(sub
, 4); /* valuerecord 1 */
385 int vfmt2
= U16(sub
, 6); /* valuerecord 2 */
386 int fmtoff1
, fmtoff2
;
387 int vrlen
; /* the length of vfmt1 and vfmt2 */
389 vrlen
= valuerecord_len(vfmt1
) + valuerecord_len(vfmt2
);
392 int nc1
= U16(sub
, 8);
393 coverage(sub
+ U16(sub
, 2), cov
);
394 for (i
= 0; i
< nc1
; i
++) {
395 void *c2
= sub
+ U16(sub
, 10 + 2 * i
);
396 int nc2
= U16(c2
, 0);
397 for (j
= 0; j
< nc2
; j
++) {
398 int second
= U16(c2
+ 2 + (2 + vrlen
) * j
, 0);
399 fmtoff1
= 2 + (2 + vrlen
) * j
+ 2;
400 fmtoff2
= fmtoff1
+ valuerecord_len(vfmt1
);
401 if (valuerecord_small(vfmt1
, c2
+ fmtoff1
) &&
402 valuerecord_small(vfmt2
, c2
+ fmtoff2
))
404 printf("gpos %s 2", feat
);
405 printf(" %s", glyph_name
[cov
[i
]]);
406 valuerecord_print(vfmt1
, c2
+ fmtoff1
);
407 printf(" %s", glyph_name
[second
]);
408 valuerecord_print(vfmt2
, c2
+ fmtoff2
);
414 int gl1
[NGLYPHS
], gl2
[NGLYPHS
];
415 int cls1
[NGLYPHS
], cls2
[NGLYPHS
];
416 int grp1
[NGLYPHS
], grp2
[NGLYPHS
];
417 int ngl1
= classdef(sub
+ U16(sub
, 8), gl1
, cls1
);
418 int ngl2
= classdef(sub
+ U16(sub
, 10), gl2
, cls2
);
419 int ncls1
= U16(sub
, 12);
420 int ncls2
= U16(sub
, 14);
421 for (i
= 0; i
< ncls1
; i
++)
422 grp1
[i
] = ggrp_class(gl1
, cls1
, ngl1
, i
);
423 for (i
= 0; i
< ncls2
; i
++)
424 grp2
[i
] = ggrp_class(gl2
, cls2
, ngl2
, i
);
425 for (i
= 0; i
< ncls1
; i
++) {
426 for (j
= 0; j
< ncls2
; j
++) {
427 fmtoff1
= 16 + (i
* ncls2
+ j
) * vrlen
;
428 fmtoff2
= fmtoff1
+ valuerecord_len(vfmt1
);
429 if (valuerecord_small(vfmt1
, sub
+ fmtoff1
) &&
430 valuerecord_small(vfmt2
, sub
+ fmtoff2
))
432 printf("gpos %s %d", feat
, 2);
433 printf(" @%d", grp1
[i
]);
434 valuerecord_print(vfmt1
, sub
+ fmtoff1
);
435 printf(" @%d", grp2
[j
]);
436 valuerecord_print(vfmt2
, sub
+ fmtoff2
);
443 /* cursive attachment positioning */
444 static void otf_gpostype3(void *otf
, void *sub
, char *feat
)
446 int fmt
= U16(sub
, 0);
449 coverage(sub
+ U16(sub
, 2), cov
);
453 for (i
= 0; i
< n
; i
++) {
454 int prev
= U16(sub
, 6 + 4 * i
);
455 int next
= U16(sub
, 6 + 4 * i
+ 2);
456 printf("gcur %s %s", feat
, glyph_name
[cov
[i
]]);
458 printf(" %d %d", uwid(S16(sub
, prev
+ 2)),
459 uwid(S16(sub
, prev
+ 4)));
463 printf(" %d %d", uwid(S16(sub
, next
+ 2)),
464 uwid(S16(sub
, next
+ 4)));
471 /* mark-to-base attachment positioning */
472 static void otf_gpostype4(void *otf
, void *sub
, char *feat
)
474 int fmt
= U16(sub
, 0);
475 int mcov
[NGLYPHS
]; /* mark coverage */
476 int bcov
[NGLYPHS
]; /* base coverage */
477 int cgrp
[1024]; /* glyph groups assigned to classes */
478 int bgrp
; /* the group assigned to base glyphs */
479 int mcnt
; /* mark coverage size */
480 int bcnt
; /* base coverage size */
481 int ccnt
; /* class count */
482 void *marks
; /* mark array table */
483 void *bases
; /* base array table */
487 mcnt
= coverage(sub
+ U16(sub
, 2), mcov
);
488 bcnt
= coverage(sub
+ U16(sub
, 4), bcov
);
490 marks
= sub
+ U16(sub
, 8);
491 bases
= sub
+ U16(sub
, 10);
492 bgrp
= ggrp_coverage(bcov
, bcnt
);
493 for (i
= 0; i
< ccnt
; i
++) {
496 for (j
= 0; j
< mcnt
; j
++)
497 if (U16(marks
, 2 + 4 * j
) == i
)
498 grp
[cnt
++] = mcov
[j
];
499 cgrp
[i
] = ggrp_coverage(grp
, cnt
);
501 for (i
= 0; i
< mcnt
; i
++) {
502 void *mark
= marks
+ U16(marks
, 2 + 4 * i
+ 2); /* mark anchor */
503 int dx
= -uwid(S16(mark
, 2));
504 int dy
= -uwid(S16(mark
, 4));
506 dx
+= uwid(glyph_wid
[mcov
[i
]]);
509 printf("gpos %s 2 @%d %s:%+d%+d%+d%+d\n",
510 feat
, bgrp
, glyph_name
[mcov
[i
]], dx
, dy
, 0, 0);
512 for (i
= 0; i
< bcnt
; i
++) {
513 for (j
= 0; j
< ccnt
; j
++) {
514 void *base
= bases
+ U16(bases
, 2 + ccnt
* 2 * i
+ 2 * j
);
515 int dx
= uwid(S16(base
, 2)) - uwid(glyph_wid
[bcov
[i
]]);
516 int dy
= uwid(S16(base
, 4));
518 dx
+= uwid(glyph_wid
[bcov
[i
]]);
521 printf("gpos %s 2 %s @%d:%+d%+d%+d%+d\n",
522 feat
, glyph_name
[bcov
[i
]], cgrp
[j
], dx
, dy
, 0, 0);
529 int bgrp
[GCTXLEN
]; /* backtrack coverage arrays */
530 int igrp
[GCTXLEN
]; /* input coverage arrays */
531 int lgrp
[GCTXLEN
]; /* lookahead coverage arrays*/
532 int bn
, in
, ln
; /* size of b[], i[], l[] */
533 int seqidx
; /* sequence index */
536 static int gctx_len(struct gctx
*ctx
, int patlen
)
538 return ctx
? ctx
->bn
+ ctx
->in
+ ctx
->ln
- patlen
: 0;
541 static void gctx_backtrack(struct gctx
*ctx
)
546 for (i
= 0; i
< ctx
->bn
; i
++)
547 printf(" =@%d", ctx
->bgrp
[i
]);
548 for (i
= 0; i
< ctx
->seqidx
; i
++)
549 printf(" =@%d", ctx
->igrp
[i
]);
552 static void gctx_lookahead(struct gctx
*ctx
, int patlen
)
557 for (i
= ctx
->seqidx
+ patlen
; i
< ctx
->in
; i
++)
558 printf(" =@%d", ctx
->igrp
[i
]);
559 for (i
= 0; i
< ctx
->ln
; i
++)
560 printf(" =@%d", ctx
->lgrp
[i
]);
563 /* single substitution */
564 static void otf_gsubtype1(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
567 int fmt
= U16(sub
, 0);
570 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
572 for (i
= 0; i
< ncov
; i
++) {
573 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
575 printf(" -%s +%s", glyph_name
[cov
[i
]],
576 glyph_name
[cov
[i
] + S16(sub
, 4)]);
577 gctx_lookahead(ctx
, 1);
583 for (i
= 0; i
< n
; i
++) {
584 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
586 printf(" -%s +%s", glyph_name
[cov
[i
]],
587 glyph_name
[U16(sub
, 6 + 2 * i
)]);
588 gctx_lookahead(ctx
, 1);
594 /* alternate substitution */
595 static void otf_gsubtype3(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
598 int fmt
= U16(sub
, 0);
602 coverage(sub
+ U16(sub
, 2), cov
);
604 for (i
= 0; i
< n
; i
++) {
605 void *alt
= sub
+ U16(sub
, 6 + 2 * i
);
606 int nalt
= U16(alt
, 0);
607 for (j
= 0; j
< nalt
; j
++) {
608 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
610 printf(" -%s +%s", glyph_name
[cov
[i
]],
611 glyph_name
[U16(alt
, 2 + 2 * j
)]);
612 gctx_lookahead(ctx
, 1);
618 /* ligature substitution */
619 static void otf_gsubtype4(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
621 int fmt
= U16(sub
, 0);
626 coverage(sub
+ U16(sub
, 2), cov
);
628 for (i
= 0; i
< n
; i
++) {
629 void *set
= sub
+ U16(sub
, 6 + 2 * i
);
630 int nset
= U16(set
, 0);
631 for (j
= 0; j
< nset
; j
++) {
632 void *lig
= set
+ U16(set
, 2 + 2 * j
);
633 int nlig
= U16(lig
, 2);
634 printf("gsub %s %d", feat
, nlig
+ 1 + gctx_len(ctx
, nlig
));
636 printf(" -%s", glyph_name
[cov
[i
]]);
637 for (k
= 0; k
< nlig
- 1; k
++)
638 printf(" -%s", glyph_name
[U16(lig
, 4 + 2 * k
)]);
639 printf(" +%s", glyph_name
[U16(lig
, 0)]);
640 gctx_lookahead(ctx
, nlig
);
646 /* chaining contextual substitution */
647 static void otf_gsubtype6(void *otf
, void *sub
, char *feat
, void *gsub
)
649 struct gctx ctx
= {{0}};
650 void *lookups
= gsub
+ U16(gsub
, 8);
651 int fmt
= U16(sub
, 0);
653 int i
, j
, nsub
, ncov
;
656 otf_unsupported("GSUB", 6, fmt
);
659 ctx
.bn
= U16(sub
, off
);
660 for (i
= 0; i
< ctx
.bn
; i
++) {
661 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
662 ctx
.bgrp
[i
] = ggrp_coverage(cov
, ncov
);
664 off
+= 2 + 2 * ctx
.bn
;
665 ctx
.in
= U16(sub
, off
);
666 for (i
= 0; i
< ctx
.in
; i
++) {
667 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
668 ctx
.igrp
[i
] = ggrp_coverage(cov
, ncov
);
670 off
+= 2 + 2 * ctx
.in
;
671 ctx
.ln
= U16(sub
, off
);
672 for (i
= 0; i
< ctx
.ln
; i
++) {
673 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
674 ctx
.lgrp
[i
] = ggrp_coverage(cov
, ncov
);
676 off
+= 2 + 2 * ctx
.ln
;
677 nsub
= U16(sub
, off
); /* nsub > 1 is not supported */
678 for (i
= 0; i
< nsub
&& i
< 1; i
++) {
679 int lidx
= U16(sub
, off
+ 2 + 4 * i
+ 2);
680 void *lookup
= lookups
+ U16(lookups
, 2 + 2 * lidx
);
681 int ltype
= U16(lookup
, 0);
682 int ntabs
= U16(lookup
, 4);
683 ctx
.seqidx
= U16(sub
, off
+ 2 + 4 * i
);
684 for (j
= 0; j
< ntabs
; j
++) {
685 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
687 if (type
== 7) { /* extension substitution */
689 tab
= tab
+ U32(tab
, 4);
692 otf_gsubtype1(otf
, tab
, feat
, &ctx
);
694 otf_gsubtype3(otf
, tab
, feat
, &ctx
);
696 otf_gsubtype4(otf
, tab
, feat
, &ctx
);
701 /* an otf gsub/gpos lookup */
703 char scrp
[8]; /* script name */
704 char feat
[8]; /* feature name */
705 int lookup
; /* index into the lookup table */
708 /* parse the given gsub/gpos feature table */
709 static int otf_featrec(void *otf
, void *gtab
, void *featrec
, char *script
, struct otflookup
*lookups
)
711 void *feats
= gtab
+ U16(gtab
, 6);
712 void *feat
= feats
+ U16(featrec
, 4);
713 int nlookups
= U16(feat
, 2);
715 for (i
= 0; i
< nlookups
; i
++) {
716 memcpy(lookups
[i
].feat
, featrec
, 4);
717 lookups
[i
].feat
[4] = '\0';
718 strcpy(lookups
[i
].scrp
, script
);
719 lookups
[i
].lookup
= U16(feat
, 4 + 2 * i
);
724 /* parse the given language table and its feature tables */
725 static int otf_lang(void *otf
, void *gtab
, void *lang
, char *script
, struct otflookup
*lookups
)
727 void *feats
= gtab
+ U16(gtab
, 6);
728 int featidx
= U16(lang
, 2);
729 int nfeat
= U16(lang
, 4);
732 if (featidx
!= 0xffff)
733 n
+= otf_featrec(otf
, gtab
, feats
+ 2 + 6 * featidx
, script
, lookups
+ n
);
734 for (i
= 0; i
< nfeat
; i
++)
735 n
+= otf_featrec(otf
, gtab
,
736 feats
+ 2 + 6 * U16(lang
, 6 + 2 * i
), script
, lookups
+ n
);
740 static int lookupcmp(void *v1
, void *v2
)
742 struct otflookup
*l1
= v1
;
743 struct otflookup
*l2
= v2
;
744 if (strcmp(l1
->scrp
, l2
->scrp
))
745 return strcmp(l1
->scrp
, l2
->scrp
);
746 if (trfn_featrank(l1
->scrp
, l1
->feat
) != trfn_featrank(l1
->scrp
, l2
->feat
))
747 return trfn_featrank(l1
->scrp
, l1
->feat
) - trfn_featrank(l1
->scrp
, l2
->feat
);
748 return l1
->lookup
- l2
->lookup
;
751 /* extract lookup tables for all features of the given gsub/gpos table */
752 static int otf_gtab(void *otf
, void *gpos
, struct otflookup
*lookups
)
754 void *scripts
= gpos
+ U16(gpos
, 4);
755 int nscripts
, nlangs
;
757 char stag
[8], ltag
[8]; /* script and language tags */
760 nscripts
= U16(scripts
, 0);
761 for (i
= 0; i
< nscripts
; i
++) {
762 void *grec
= scripts
+ 2 + 6 * i
;
763 memcpy(stag
, grec
, 4);
765 if (!trfn_script(stag
, nscripts
))
767 script
= scripts
+ U16(grec
, 4);
768 nlangs
= U16(script
, 2);
769 if (U16(script
, 0) && trfn_lang(NULL
, nlangs
+ (U16(script
, 0) != 0)))
770 n
+= otf_lang(otf
, gpos
, script
+ U16(script
, 0),
772 for (j
= 0; j
< nlangs
; j
++) {
773 void *lrec
= script
+ 4 + 6 * j
;
774 memcpy(ltag
, lrec
, 4);
776 if (trfn_lang(ltag
, nlangs
+ (U16(script
, 0) != 0)))
777 n
+= otf_lang(otf
, gpos
, script
+ U16(lrec
, 4),
781 qsort(lookups
, n
, sizeof(lookups
[0]), (void *) lookupcmp
);
785 static void otf_gpos(void *otf
, void *gpos
)
787 struct otflookup lookups
[NLOOKUPS
];
788 void *lookuplist
= gpos
+ U16(gpos
, 8);
789 int nlookups
= otf_gtab(otf
, gpos
, lookups
);
792 for (i
= 0; i
< nlookups
; i
++) {
793 void *lookup
= lookuplist
+ U16(lookuplist
, 2 + 2 * lookups
[i
].lookup
);
794 int ltype
= U16(lookup
, 0);
795 int ntabs
= U16(lookup
, 4);
796 sprintf(tag
, "%s:%s", lookups
[i
].feat
,
797 lookups
[i
].scrp
[0] ? lookups
[i
].scrp
: "DFLT");
798 for (j
= 0; j
< ntabs
; j
++) {
799 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
801 if (type
== 9) { /* extension positioning */
803 tab
= tab
+ U32(tab
, 4);
807 otf_gpostype1(otf
, tab
, tag
);
810 otf_gpostype2(otf
, tab
, tag
);
813 otf_gpostype3(otf
, tab
, tag
);
816 otf_gpostype4(otf
, tab
, tag
);
819 otf_unsupported("GPOS", type
, 0);
825 static void otf_gsub(void *otf
, void *gsub
)
827 struct otflookup lookups
[NLOOKUPS
];
828 void *lookuplist
= gsub
+ U16(gsub
, 8);
829 int nlookups
= otf_gtab(otf
, gsub
, lookups
);
832 for (i
= 0; i
< nlookups
; i
++) {
833 void *lookup
= lookuplist
+ U16(lookuplist
, 2 + 2 * lookups
[i
].lookup
);
834 int ltype
= U16(lookup
, 0);
835 int ntabs
= U16(lookup
, 4);
836 sprintf(tag
, "%s:%s", lookups
[i
].feat
,
837 lookups
[i
].scrp
[0] ? lookups
[i
].scrp
: "DFLT");
838 for (j
= 0; j
< ntabs
; j
++) {
839 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
841 if (type
== 7) { /* extension substitution */
843 tab
= tab
+ U32(tab
, 4);
847 otf_gsubtype1(otf
, tab
, tag
, NULL
);
850 otf_gsubtype3(otf
, tab
, tag
, NULL
);
853 otf_gsubtype4(otf
, tab
, tag
, NULL
);
856 otf_gsubtype6(otf
, tab
, tag
, gsub
);
859 otf_unsupported("GSUB", type
, 0);
865 static int xread(int fd
, char *buf
, int len
)
869 int ret
= read(fd
, buf
+ nr
, len
- nr
);
870 if (ret
== -1 && (errno
== EAGAIN
|| errno
== EINTR
))
879 static char buf
[BUFLEN
];
884 if (xread(0, buf
, sizeof(buf
)) <= 0)
886 upm
= U16(otf_table(buf
, "head"), 18);
887 otf_name(buf
, otf_table(buf
, "name"));
888 otf_cmap(buf
, otf_table(buf
, "cmap"));
889 otf_post(buf
, otf_table(buf
, "post"));
890 if (otf_table(buf
, "glyf"))
891 otf_glyf(buf
, otf_table(buf
, "glyf"));
892 otf_hmtx(buf
, otf_table(buf
, "hmtx"));
893 for (i
= 0; i
< glyph_n
; i
++) {
894 trfn_char(glyph_name
[i
], -1,
895 glyph_code
[i
] != 0xffff ? glyph_code
[i
] : 0,
897 owid(glyph_bbox
[i
][0]), owid(glyph_bbox
[i
][1]),
898 owid(glyph_bbox
[i
][2]), owid(glyph_bbox
[i
][3]));
900 if (otf_table(buf
, "kern"))
901 otf_kern(buf
, otf_table(buf
, "kern"));
905 void otf_feat(int r
, int k
, int w
)
910 if (otf_table(buf
, "GSUB"))
911 otf_gsub(buf
, otf_table(buf
, "GSUB"));
912 if (otf_table(buf
, "GPOS"))
913 otf_gpos(buf
, otf_table(buf
, "GPOS"));
917 static int *ggrp_g
[NGRPS
];
918 static int ggrp_len
[NGRPS
];
921 static int ggrp_find(int *src
, int n
)
924 for (i
= 0; i
< ggrp_n
; i
++) {
925 if (ggrp_len
[i
] == n
) {
926 for (j
= 0; j
< n
; j
++)
927 if (src
[j
] != ggrp_g
[i
][j
])
936 int ggrp_make(int *src
, int n
)
938 int id
= ggrp_find(src
, n
);
943 ggrp_g
[id
] = malloc(n
* sizeof(ggrp_g
[id
][0]));
945 for (i
= 0; i
< n
; i
++)
946 ggrp_g
[id
][i
] = src
[i
];
947 printf("ggrp %d %d", id
, n
);
948 for (i
= 0; i
< n
; i
++)
949 printf(" %s", glyph_name
[src
[i
]]);
954 static char *macset
[] = {
955 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
956 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
957 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
958 "comma", "hyphen", "period", "slash", "zero",
959 "one", "two", "three", "four", "five",
960 "six", "seven", "eight", "nine", "colon",
961 "semicolon", "less", "equal", "greater", "question",
962 "at", "A", "B", "C", "D",
963 "E", "F", "G", "H", "I",
964 "J", "K", "L", "M", "N",
965 "O", "P", "Q", "R", "S",
966 "T", "U", "V", "W", "X",
967 "Y", "Z", "bracketleft", "backslash", "bracketright",
968 "asciicircum", "underscore", "grave", "a", "b",
969 "c", "d", "e", "f", "g",
970 "h", "i", "j", "k", "l",
971 "m", "n", "o", "p", "q",
972 "r", "s", "t", "u", "v",
973 "w", "x", "y", "z", "braceleft",
974 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
975 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
976 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
977 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
978 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
979 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
980 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
981 "dagger", "degree", "cent", "sterling", "section",
982 "bullet", "paragraph", "germandbls", "registered", "copyright",
983 "trademark", "acute", "dieresis", "notequal", "AE",
984 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
985 "yen", "mu", "partialdiff", "summation", "product",
986 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
987 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
988 "radical", "florin", "approxequal", "Delta", "guillemotleft",
989 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
990 "Otilde", "OE", "oe", "endash", "emdash",
991 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
992 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
993 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
994 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
995 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
996 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
997 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
998 "dotlessi", "circumflex", "tilde", "macron", "breve",
999 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
1000 "caron", "Lslash", "lslash", "Scaron", "scaron",
1001 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
1002 "Yacute", "yacute", "Thorn", "thorn", "minus",
1003 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
1004 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
1005 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
1006 "Ccaron", "ccaron", "dcroat",