10 #define MAX(a, b) ((a) < (b) ? (b) : (a))
12 #define NGLYPHS (1 << 14)
13 #define NLOOKUPS (1 << 12)
17 #define U32(buf, off) (htonl(*(u32 *) ((buf) + (off))))
18 #define U16(buf, off) (htons(*(u16 *) ((buf) + (off))))
19 #define U8(buf, off) (*(u8 *) ((buf) + (off)))
20 #define S16(buf, off) ((s16) htons(*(u16 *) ((buf) + (off))))
21 #define S32(buf, off) ((s32) htonl(*(u32 *) ((buf) + (off))))
23 #define GCTXLEN 16 /* number of context backtrack coverage arrays */
25 typedef unsigned int u32
;
26 typedef unsigned short u16
;
27 typedef unsigned char u8
;
31 static char glyph_name
[NGLYPHS
][GNLEN
];
32 static int glyph_code
[NGLYPHS
];
33 static int glyph_bbox
[NGLYPHS
][4];
34 static int glyph_wid
[NGLYPHS
];
36 static int upm
; /* units per em */
37 static int res
; /* device resolution */
38 static int kmin
; /* minimum kerning value */
39 static int warn
; /* report unsupported tables */
41 static char *macset
[];
43 static int owid(int w
)
45 return (w
< 0 ? w
* 1000 - upm
/ 2 : w
* 1000 + upm
/ 2) / upm
;
48 static int uwid(int w
)
51 return (w
< 0 ? owid(w
) - d
/ 2 : owid(w
) + d
/ 2) / d
;
54 /* weather the script is right-to-left */
55 static int otf_r2l(char *feat
)
57 char *scrp
= strchr(feat
, ':') + 1;
58 return !strcmp("arab", scrp
) || !strcmp("hebr", scrp
);
61 /* report unsupported otf tables */
62 static void otf_unsupported(char *sub
, int type
, int fmt
)
65 fprintf(stderr
, "neatmkfn: unsupported %s lookup %d", sub
, type
);
67 fprintf(stderr
, " format %d", fmt
);
68 fprintf(stderr
, "\n");
72 /* find the otf table with the given name */
73 static void *otf_table(void *otf
, char *name
)
75 int nrecs
= U16(otf
, 4);
77 for (i
= 0; i
< nrecs
; i
++) {
78 void *rec
= otf
+ 12 + i
* 16; /* an otf table record */
79 if (!strncmp(rec
, name
, 4))
80 return otf
+ U32(rec
, 8);
85 /* obtain postscript font name from name table */
86 static void otf_name(void *otf
, void *tab
)
89 void *str
= tab
+ U16(tab
, 4); /* storage area */
90 int n
= U16(tab
, 2); /* number of name records */
92 for (i
= 0; i
< n
; i
++) {
93 void *rec
= tab
+ 6 + 12 * i
;
94 int pid
= U16(rec
, 0); /* platform id */
95 int eid
= U16(rec
, 2); /* encoding id */
96 int lid
= U16(rec
, 4); /* language id */
97 int nid
= U16(rec
, 6); /* name id */
98 int len
= U16(rec
, 8); /* string length */
99 int off
= U16(rec
, 10); /* string offset */
100 if (pid
== 1 && eid
== 0 && lid
== 0 && nid
== 6) {
101 memcpy(name
, str
+ off
, len
);
108 /* parse otf cmap format 4 subtable */
109 static void otf_cmap4(void *otf
, void *cmap4
)
112 void *ends
, *begs
, *deltas
, *offsets
;
113 int beg
, end
, delta
, offset
;
115 nsegs
= U16(cmap4
, 6) / 2;
117 begs
= ends
+ 2 * nsegs
+ 2;
118 deltas
= begs
+ 2 * nsegs
;
119 offsets
= deltas
+ 2 * nsegs
;
120 for (i
= 0; i
< nsegs
; i
++) {
121 beg
= U16(begs
, 2 * i
);
122 end
= U16(ends
, 2 * i
);
123 delta
= U16(deltas
, 2 * i
);
124 offset
= U16(offsets
, 2 * i
);
126 for (j
= beg
; j
<= end
; j
++)
127 glyph_code
[(U16(offsets
+ 2 * i
,
128 offset
+ (j
- beg
) * 2) + delta
) & 0xffff] = j
;
130 for (j
= beg
; j
<= end
; j
++)
131 glyph_code
[(j
+ delta
) & 0xffff] = j
;
136 /* parse otf cmap header */
137 static void otf_cmap(void *otf
, void *cmap
)
139 int nrecs
= U16(cmap
, 2);
141 for (i
= 0; i
< nrecs
; i
++) {
142 void *rec
= cmap
+ 4 + i
* 8; /* a cmap record */
143 int plat
= U16(rec
, 0);
144 int enc
= U16(rec
, 2);
145 void *tab
= cmap
+ U32(rec
, 4); /* a cmap subtable */
146 int fmt
= U16(tab
, 0);
147 if (plat
== 3 && enc
== 1 && fmt
== 4)
152 static void otf_post(void *otf
, void *post
)
154 void *post2
; /* version 2.0 header */
155 void *index
; /* glyph name indices */
156 void *names
; /* glyph names */
159 if (U32(post
, 0) != 0x00020000)
162 glyph_n
= U16(post2
, 0);
164 names
= index
+ 2 * glyph_n
;
165 for (i
= 0; i
< glyph_n
; i
++) {
166 int idx
= U16(index
, 2 * i
);
168 strcpy(glyph_name
[i
], macset
[idx
]);
170 memcpy(glyph_name
[i
], names
+ cname
+ 1,
172 glyph_name
[i
][U8(names
, cname
)] = '\0';
173 cname
+= U8(names
, cname
) + 1;
178 static void otf_glyf(void *otf
, void *glyf
)
180 void *maxp
= otf_table(otf
, "maxp");
181 void *head
= otf_table(otf
, "head");
182 void *loca
= otf_table(otf
, "loca");
185 int n
= U16(maxp
, 4);
186 int fmt
= U16(head
, 50);
188 for (i
= 0; i
< n
; i
++) {
190 gdat
= glyf
+ U32(loca
, 4 * i
);
191 gdat_next
= glyf
+ U32(loca
, 4 * (i
+ 1));
193 gdat
= glyf
+ U16(loca
, 2 * i
) * 2;
194 gdat_next
= glyf
+ U16(loca
, 2 * (i
+ 1)) * 2;
196 if (gdat
< gdat_next
)
197 for (j
= 0; j
< 4; j
++)
198 glyph_bbox
[i
][j
] = S16(gdat
, 2 + 2 * j
);
202 static void otf_hmtx(void *otf
, void *hmtx
)
204 void *hhea
= otf_table(otf
, "hhea");
208 for (i
= 0; i
< n
; i
++)
209 glyph_wid
[i
] = U16(hmtx
, i
* 4);
210 for (i
= n
; i
< glyph_n
; i
++)
211 glyph_wid
[i
] = glyph_wid
[n
- 1];
214 static void otf_kern(void *otf
, void *kern
)
218 int n
= U16(kern
, 2); /* number of kern subtables */
219 for (i
= 0; i
< n
; i
++) {
220 void *tab
= kern
+ off
; /* a kern subtable */
221 int cov
= U16(tab
, 4);
223 if ((cov
>> 8) == 0 && (cov
& 1)) { /* format 0 */
224 int npairs
= U16(tab
, 6);
225 for (j
= 0; j
< npairs
; j
++) {
226 int c1
= U16(tab
, 14 + 6 * j
);
227 int c2
= U16(tab
, 14 + 6 * j
+ 2);
228 int val
= S16(tab
, 14 + 6 * j
+ 4);
229 trfn_kern(glyph_name
[c1
], glyph_name
[c2
],
236 static int coverage(void *cov
, int *out
)
238 int fmt
= U16(cov
, 0);
244 for (i
= 0; i
< n
; i
++)
245 out
[ncov
++] = U16(cov
, 4 + 2 * i
);
248 for (i
= 0; i
< n
; i
++) {
249 beg
= U16(cov
, 4 + 6 * i
);
250 end
= U16(cov
, 4 + 6 * i
+ 2);
251 for (j
= beg
; j
<= end
; j
++)
258 static int classdef(void *tab
, int *gl
, int *cls
)
260 int fmt
= U16(tab
, 0);
264 int beg
= U16(tab
, 2);
266 for (i
= 0; i
< ngl
; i
++) {
268 cls
[i
] = U16(tab
, 6 + 2 * i
);
273 for (i
= 0; i
< n
; i
++) {
274 int beg
= U16(tab
, 4 + 6 * i
);
275 int end
= U16(tab
, 4 + 6 * i
+ 2);
276 for (j
= beg
; j
<= end
; j
++) {
278 cls
[ngl
] = U16(tab
, 4 + 6 * i
+ 4);
286 static int intcmp(void *v1
, void *v2
)
288 return *(int *) v1
- *(int *) v2
;
291 static int ggrp_make(int *src
, int n
);
293 static int ggrp_class(int *src
, int *cls
, int nsrc
, int id
)
298 for (i
= 0; i
< nsrc
; i
++)
301 qsort(g
, n
, sizeof(g
[0]), (void *) intcmp
);
302 return ggrp_make(g
, n
);
305 static int ggrp_coverage(int *g
, int n
)
307 qsort(g
, n
, sizeof(g
[0]), (void *) intcmp
);
308 return ggrp_make(g
, n
);
311 static int valuerecord_len(int fmt
)
315 for (i
= 0; i
< 8; i
++)
321 static void valuerecord_print(int fmt
, void *rec
)
326 for (i
= 0; i
< 8; i
++) {
327 if (fmt
& (1 << i
)) {
328 vals
[i
] = uwid(S16(rec
, off
));
333 printf(":%+d%+d%+d%+d", vals
[0], vals
[1], vals
[2], vals
[3]);
336 static int valuerecord_small(int fmt
, void *rec
)
340 for (i
= 0; i
< 8; i
++) {
341 if (fmt
& (1 << i
)) {
342 if (abs(uwid(S16(rec
, off
))) >= MAX(1, kmin
))
350 /* single adjustment positioning */
351 static void otf_gpostype1(void *otf
, void *sub
, char *feat
)
353 int fmt
= U16(sub
, 0);
354 int vfmt
= U16(sub
, 4);
357 int vlen
= valuerecord_len(vfmt
);
359 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
361 for (i
= 0; i
< ncov
; i
++) {
362 if (valuerecord_small(vfmt
, sub
+ 6))
364 printf("gpos %s 1 %s", feat
, glyph_name
[cov
[i
]]);
365 valuerecord_print(vfmt
, sub
+ 6);
371 for (i
= 0; i
< nvals
; i
++) {
372 if (valuerecord_small(vfmt
, sub
+ 6))
374 printf("gpos %s 1 %s", feat
, glyph_name
[cov
[i
]]);
375 valuerecord_print(vfmt
, sub
+ 8 + i
* vlen
);
381 /* pair adjustment positioning */
382 static void otf_gpostype2(void *otf
, void *sub
, char *feat
)
384 int fmt
= U16(sub
, 0);
385 int vfmt1
= U16(sub
, 4); /* valuerecord 1 */
386 int vfmt2
= U16(sub
, 6); /* valuerecord 2 */
387 int fmtoff1
, fmtoff2
;
388 int vrlen
; /* the length of vfmt1 and vfmt2 */
390 vrlen
= valuerecord_len(vfmt1
) + valuerecord_len(vfmt2
);
393 int nc1
= U16(sub
, 8);
394 coverage(sub
+ U16(sub
, 2), cov
);
395 for (i
= 0; i
< nc1
; i
++) {
396 void *c2
= sub
+ U16(sub
, 10 + 2 * i
);
397 int nc2
= U16(c2
, 0);
398 for (j
= 0; j
< nc2
; j
++) {
399 int second
= U16(c2
+ 2 + (2 + vrlen
) * j
, 0);
400 fmtoff1
= 2 + (2 + vrlen
) * j
+ 2;
401 fmtoff2
= fmtoff1
+ valuerecord_len(vfmt1
);
402 if (valuerecord_small(vfmt1
, c2
+ fmtoff1
) &&
403 valuerecord_small(vfmt2
, c2
+ fmtoff2
))
405 printf("gpos %s 2", feat
);
406 printf(" %s", glyph_name
[cov
[i
]]);
407 valuerecord_print(vfmt1
, c2
+ fmtoff1
);
408 printf(" %s", glyph_name
[second
]);
409 valuerecord_print(vfmt2
, c2
+ fmtoff2
);
415 int gl1
[NGLYPHS
], gl2
[NGLYPHS
];
416 int cls1
[NGLYPHS
], cls2
[NGLYPHS
];
417 int grp1
[NGLYPHS
], grp2
[NGLYPHS
];
418 int ngl1
= classdef(sub
+ U16(sub
, 8), gl1
, cls1
);
419 int ngl2
= classdef(sub
+ U16(sub
, 10), gl2
, cls2
);
420 int ncls1
= U16(sub
, 12);
421 int ncls2
= U16(sub
, 14);
422 for (i
= 0; i
< ncls1
; i
++)
423 grp1
[i
] = ggrp_class(gl1
, cls1
, ngl1
, i
);
424 for (i
= 0; i
< ncls2
; i
++)
425 grp2
[i
] = ggrp_class(gl2
, cls2
, ngl2
, i
);
426 for (i
= 0; i
< ncls1
; i
++) {
427 for (j
= 0; j
< ncls2
; j
++) {
428 fmtoff1
= 16 + (i
* ncls2
+ j
) * vrlen
;
429 fmtoff2
= fmtoff1
+ valuerecord_len(vfmt1
);
430 if (valuerecord_small(vfmt1
, sub
+ fmtoff1
) &&
431 valuerecord_small(vfmt2
, sub
+ fmtoff2
))
433 printf("gpos %s %d", feat
, 2);
434 printf(" @%d", grp1
[i
]);
435 valuerecord_print(vfmt1
, sub
+ fmtoff1
);
436 printf(" @%d", grp2
[j
]);
437 valuerecord_print(vfmt2
, sub
+ fmtoff2
);
444 /* cursive attachment positioning */
445 static void otf_gpostype3(void *otf
, void *sub
, char *feat
)
447 int fmt
= U16(sub
, 0);
455 coverage(sub
+ U16(sub
, 2), cov
);
459 for (i
= 0; i
< n
; i
++)
460 if (U16(sub
, 6 + 4 * i
))
461 ocov
[ocnt
++] = cov
[i
];
462 for (i
= 0; i
< n
; i
++)
463 if (U16(sub
, 6 + 4 * i
+ 2))
464 icov
[icnt
++] = cov
[i
];
465 igrp
= ggrp_coverage(icov
, icnt
);
466 ogrp
= ggrp_coverage(ocov
, ocnt
);
467 for (i
= 0; i
< n
; i
++) {
468 int prev
= U16(sub
, 6 + 4 * i
);
469 int next
= U16(sub
, 6 + 4 * i
+ 2);
471 int dx
= -uwid(S16(sub
, prev
+ 2));
472 int dy
= -uwid(S16(sub
, prev
+ 4));
474 dx
+= uwid(glyph_wid
[cov
[i
]]);
476 printf("gpos %s 2 @%d %s:%+d%+d%+d%+d\n",
477 feat
, igrp
, glyph_name
[cov
[i
]],
481 int dx
= uwid(S16(sub
, next
+ 2)) - uwid(glyph_wid
[cov
[i
]]);
482 int dy
= uwid(S16(sub
, next
+ 4));
484 dx
+= uwid(glyph_wid
[cov
[i
]]);
486 printf("gpos %s 2 %s @%d:%+d%+d%+d%+d\n",
487 feat
, glyph_name
[cov
[i
]], ogrp
,
493 /* mark-to-base attachment positioning */
494 static void otf_gpostype4(void *otf
, void *sub
, char *feat
)
496 int fmt
= U16(sub
, 0);
497 int mcov
[NGLYPHS
]; /* mark coverage */
498 int bcov
[NGLYPHS
]; /* base coverage */
499 int cgrp
[1024]; /* glyph groups assigned to classes */
500 int bgrp
; /* the group assigned to base glyphs */
501 int mcnt
; /* mark coverage size */
502 int bcnt
; /* base coverage size */
503 int ccnt
; /* class count */
504 void *marks
; /* mark array table */
505 void *bases
; /* base array table */
509 mcnt
= coverage(sub
+ U16(sub
, 2), mcov
);
510 bcnt
= coverage(sub
+ U16(sub
, 4), bcov
);
512 marks
= sub
+ U16(sub
, 8);
513 bases
= sub
+ U16(sub
, 10);
514 bgrp
= ggrp_coverage(bcov
, bcnt
);
515 for (i
= 0; i
< ccnt
; i
++) {
518 for (j
= 0; j
< mcnt
; j
++)
519 if (U16(marks
, 2 + 4 * j
) == i
)
520 grp
[cnt
++] = mcov
[j
];
521 cgrp
[i
] = ggrp_coverage(grp
, cnt
);
523 for (i
= 0; i
< mcnt
; i
++) {
524 void *mark
= marks
+ U16(marks
, 2 + 4 * i
+ 2); /* mark anchor */
525 int dx
= -uwid(S16(mark
, 2));
526 int dy
= -uwid(S16(mark
, 4));
528 dx
+= uwid(glyph_wid
[mcov
[i
]]);
531 printf("gpos %s 2 @%d %s:%+d%+d%+d%+d\n",
532 feat
, bgrp
, glyph_name
[mcov
[i
]], dx
, dy
, 0, 0);
534 for (i
= 0; i
< bcnt
; i
++) {
535 for (j
= 0; j
< ccnt
; j
++) {
536 void *base
= bases
+ U16(bases
, 2 + ccnt
* 2 * i
+ 2 * j
);
537 int dx
= uwid(S16(base
, 2)) - uwid(glyph_wid
[bcov
[i
]]);
538 int dy
= uwid(S16(base
, 4));
540 dx
+= uwid(glyph_wid
[bcov
[i
]]);
543 printf("gpos %s 2 %s @%d:%+d%+d%+d%+d\n",
544 feat
, glyph_name
[bcov
[i
]], cgrp
[j
], dx
, dy
, 0, 0);
551 int bgrp
[GCTXLEN
]; /* backtrack coverage arrays */
552 int igrp
[GCTXLEN
]; /* input coverage arrays */
553 int lgrp
[GCTXLEN
]; /* lookahead coverage arrays*/
554 int bn
, in
, ln
; /* size of b[], i[], l[] */
555 int seqidx
; /* sequence index */
558 static int gctx_len(struct gctx
*ctx
, int patlen
)
560 return ctx
? ctx
->bn
+ ctx
->in
+ ctx
->ln
- patlen
: 0;
563 static void gctx_backtrack(struct gctx
*ctx
)
568 for (i
= 0; i
< ctx
->bn
; i
++)
569 printf(" =@%d", ctx
->bgrp
[i
]);
570 for (i
= 0; i
< ctx
->seqidx
; i
++)
571 printf(" =@%d", ctx
->igrp
[i
]);
574 static void gctx_lookahead(struct gctx
*ctx
, int patlen
)
579 for (i
= ctx
->seqidx
+ patlen
; i
< ctx
->in
; i
++)
580 printf(" =@%d", ctx
->igrp
[i
]);
581 for (i
= 0; i
< ctx
->ln
; i
++)
582 printf(" =@%d", ctx
->lgrp
[i
]);
585 /* single substitution */
586 static void otf_gsubtype1(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
589 int fmt
= U16(sub
, 0);
592 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
594 for (i
= 0; i
< ncov
; i
++) {
595 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
597 printf(" -%s +%s", glyph_name
[cov
[i
]],
598 glyph_name
[cov
[i
] + S16(sub
, 4)]);
599 gctx_lookahead(ctx
, 1);
605 for (i
= 0; i
< n
; i
++) {
606 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
608 printf(" -%s +%s", glyph_name
[cov
[i
]],
609 glyph_name
[U16(sub
, 6 + 2 * i
)]);
610 gctx_lookahead(ctx
, 1);
616 /* alternate substitution */
617 static void otf_gsubtype3(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
620 int fmt
= U16(sub
, 0);
624 coverage(sub
+ U16(sub
, 2), cov
);
626 for (i
= 0; i
< n
; i
++) {
627 void *alt
= sub
+ U16(sub
, 6 + 2 * i
);
628 int nalt
= U16(alt
, 0);
629 for (j
= 0; j
< nalt
; j
++) {
630 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
632 printf(" -%s +%s", glyph_name
[cov
[i
]],
633 glyph_name
[U16(alt
, 2 + 2 * j
)]);
634 gctx_lookahead(ctx
, 1);
640 /* ligature substitution */
641 static void otf_gsubtype4(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
643 int fmt
= U16(sub
, 0);
648 coverage(sub
+ U16(sub
, 2), cov
);
650 for (i
= 0; i
< n
; i
++) {
651 void *set
= sub
+ U16(sub
, 6 + 2 * i
);
652 int nset
= U16(set
, 0);
653 for (j
= 0; j
< nset
; j
++) {
654 void *lig
= set
+ U16(set
, 2 + 2 * j
);
655 int nlig
= U16(lig
, 2);
656 printf("gsub %s %d", feat
, nlig
+ 1 + gctx_len(ctx
, nlig
));
658 printf(" -%s", glyph_name
[cov
[i
]]);
659 for (k
= 0; k
< nlig
- 1; k
++)
660 printf(" -%s", glyph_name
[U16(lig
, 4 + 2 * k
)]);
661 printf(" +%s", glyph_name
[U16(lig
, 0)]);
662 gctx_lookahead(ctx
, nlig
);
668 /* chaining contextual substitution */
669 static void otf_gsubtype6(void *otf
, void *sub
, char *feat
, void *gsub
)
671 struct gctx ctx
= {{0}};
672 void *lookups
= gsub
+ U16(gsub
, 8);
673 int fmt
= U16(sub
, 0);
675 int i
, j
, nsub
, ncov
;
678 otf_unsupported("GSUB", 6, fmt
);
681 ctx
.bn
= U16(sub
, off
);
682 for (i
= 0; i
< ctx
.bn
; i
++) {
683 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
684 ctx
.bgrp
[i
] = ggrp_coverage(cov
, ncov
);
686 off
+= 2 + 2 * ctx
.bn
;
687 ctx
.in
= U16(sub
, off
);
688 for (i
= 0; i
< ctx
.in
; i
++) {
689 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
690 ctx
.igrp
[i
] = ggrp_coverage(cov
, ncov
);
692 off
+= 2 + 2 * ctx
.in
;
693 ctx
.ln
= U16(sub
, off
);
694 for (i
= 0; i
< ctx
.ln
; i
++) {
695 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
696 ctx
.lgrp
[i
] = ggrp_coverage(cov
, ncov
);
698 off
+= 2 + 2 * ctx
.ln
;
699 nsub
= U16(sub
, off
); /* nsub > 1 is not supported */
700 for (i
= 0; i
< nsub
&& i
< 1; i
++) {
701 int lidx
= U16(sub
, off
+ 2 + 4 * i
+ 2);
702 void *lookup
= lookups
+ U16(lookups
, 2 + 2 * lidx
);
703 int ltype
= U16(lookup
, 0);
704 int ntabs
= U16(lookup
, 4);
705 ctx
.seqidx
= U16(sub
, off
+ 2 + 4 * i
);
706 for (j
= 0; j
< ntabs
; j
++) {
707 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
709 if (type
== 7) { /* extension substitution */
711 tab
= tab
+ U32(tab
, 4);
714 otf_gsubtype1(otf
, tab
, feat
, &ctx
);
716 otf_gsubtype3(otf
, tab
, feat
, &ctx
);
718 otf_gsubtype4(otf
, tab
, feat
, &ctx
);
723 /* an otf gsub/gpos lookup */
725 char scrp
[8]; /* script name */
726 char feat
[8]; /* feature name */
727 int lookup
; /* index into the lookup table */
730 /* parse the given gsub/gpos feature table */
731 static int otf_featrec(void *otf
, void *gtab
, void *featrec
, char *script
, struct otflookup
*lookups
)
733 void *feats
= gtab
+ U16(gtab
, 6);
734 void *feat
= feats
+ U16(featrec
, 4);
735 int nlookups
= U16(feat
, 2);
737 for (i
= 0; i
< nlookups
; i
++) {
738 memcpy(lookups
[i
].feat
, featrec
, 4);
739 lookups
[i
].feat
[4] = '\0';
740 strcpy(lookups
[i
].scrp
, script
);
741 lookups
[i
].lookup
= U16(feat
, 4 + 2 * i
);
746 /* parse the given language table and its feature tables */
747 static int otf_lang(void *otf
, void *gtab
, void *lang
, char *script
, struct otflookup
*lookups
)
749 void *feats
= gtab
+ U16(gtab
, 6);
750 int featidx
= U16(lang
, 2);
751 int nfeat
= U16(lang
, 4);
754 if (featidx
!= 0xffff)
755 n
+= otf_featrec(otf
, gtab
, feats
+ 2 + 6 * featidx
, script
, lookups
+ n
);
756 for (i
= 0; i
< nfeat
; i
++)
757 n
+= otf_featrec(otf
, gtab
,
758 feats
+ 2 + 6 * U16(lang
, 6 + 2 * i
), script
, lookups
+ n
);
762 static int lookupcmp(void *v1
, void *v2
)
764 struct otflookup
*l1
= v1
;
765 struct otflookup
*l2
= v2
;
766 if (strcmp(l1
->scrp
, l2
->scrp
))
767 return strcmp(l1
->scrp
, l2
->scrp
);
768 if (trfn_featrank(l1
->scrp
, l1
->feat
) != trfn_featrank(l1
->scrp
, l2
->feat
))
769 return trfn_featrank(l1
->scrp
, l1
->feat
) - trfn_featrank(l1
->scrp
, l2
->feat
);
770 return l1
->lookup
- l2
->lookup
;
773 /* extract lookup tables for all features of the given gsub/gpos table */
774 static int otf_gtab(void *otf
, void *gpos
, struct otflookup
*lookups
)
776 void *scripts
= gpos
+ U16(gpos
, 4);
777 int nscripts
, nlangs
;
779 char stag
[8], ltag
[8]; /* script and language tags */
782 nscripts
= U16(scripts
, 0);
783 for (i
= 0; i
< nscripts
; i
++) {
784 void *grec
= scripts
+ 2 + 6 * i
;
785 memcpy(stag
, grec
, 4);
787 if (!trfn_script(stag
, nscripts
))
789 script
= scripts
+ U16(grec
, 4);
790 nlangs
= U16(script
, 2);
791 if (U16(script
, 0) && trfn_lang(NULL
, nlangs
+ (U16(script
, 0) != 0)))
792 n
+= otf_lang(otf
, gpos
, script
+ U16(script
, 0),
794 for (j
= 0; j
< nlangs
; j
++) {
795 void *lrec
= script
+ 4 + 6 * j
;
796 memcpy(ltag
, lrec
, 4);
798 if (trfn_lang(ltag
, nlangs
+ (U16(script
, 0) != 0)))
799 n
+= otf_lang(otf
, gpos
, script
+ U16(lrec
, 4),
803 qsort(lookups
, n
, sizeof(lookups
[0]), (void *) lookupcmp
);
807 static void otf_gpos(void *otf
, void *gpos
)
809 struct otflookup lookups
[NLOOKUPS
];
810 void *lookuplist
= gpos
+ U16(gpos
, 8);
811 int nlookups
= otf_gtab(otf
, gpos
, lookups
);
814 for (i
= 0; i
< nlookups
; i
++) {
815 void *lookup
= lookuplist
+ U16(lookuplist
, 2 + 2 * lookups
[i
].lookup
);
816 int ltype
= U16(lookup
, 0);
817 int ntabs
= U16(lookup
, 4);
818 sprintf(tag
, "%s:%s", lookups
[i
].feat
,
819 lookups
[i
].scrp
[0] ? lookups
[i
].scrp
: "DFLT");
820 for (j
= 0; j
< ntabs
; j
++) {
821 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
823 if (type
== 9) { /* extension positioning */
825 tab
= tab
+ U32(tab
, 4);
829 otf_gpostype1(otf
, tab
, tag
);
832 otf_gpostype2(otf
, tab
, tag
);
835 otf_gpostype3(otf
, tab
, tag
);
838 otf_gpostype4(otf
, tab
, tag
);
841 otf_unsupported("GPOS", type
, 0);
847 static void otf_gsub(void *otf
, void *gsub
)
849 struct otflookup lookups
[NLOOKUPS
];
850 void *lookuplist
= gsub
+ U16(gsub
, 8);
851 int nlookups
= otf_gtab(otf
, gsub
, lookups
);
854 for (i
= 0; i
< nlookups
; i
++) {
855 void *lookup
= lookuplist
+ U16(lookuplist
, 2 + 2 * lookups
[i
].lookup
);
856 int ltype
= U16(lookup
, 0);
857 int ntabs
= U16(lookup
, 4);
858 sprintf(tag
, "%s:%s", lookups
[i
].feat
,
859 lookups
[i
].scrp
[0] ? lookups
[i
].scrp
: "DFLT");
860 for (j
= 0; j
< ntabs
; j
++) {
861 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
863 if (type
== 7) { /* extension substitution */
865 tab
= tab
+ U32(tab
, 4);
869 otf_gsubtype1(otf
, tab
, tag
, NULL
);
872 otf_gsubtype3(otf
, tab
, tag
, NULL
);
875 otf_gsubtype4(otf
, tab
, tag
, NULL
);
878 otf_gsubtype6(otf
, tab
, tag
, gsub
);
881 otf_unsupported("GSUB", type
, 0);
887 static void *otf_input(int fd
)
889 struct sbuf
*sb
= sbuf_make();
892 while ((nr
= read(fd
, buf
, sizeof(buf
))) > 0)
893 sbuf_mem(sb
, buf
, nr
);
894 return sbuf_done(sb
);
897 static char *otf_buf
;
902 otf_buf
= otf_input(0);
903 upm
= U16(otf_table(otf_buf
, "head"), 18);
904 otf_name(otf_buf
, otf_table(otf_buf
, "name"));
905 otf_cmap(otf_buf
, otf_table(otf_buf
, "cmap"));
906 otf_post(otf_buf
, otf_table(otf_buf
, "post"));
907 if (otf_table(otf_buf
, "glyf"))
908 otf_glyf(otf_buf
, otf_table(otf_buf
, "glyf"));
909 otf_hmtx(otf_buf
, otf_table(otf_buf
, "hmtx"));
910 for (i
= 0; i
< glyph_n
; i
++) {
911 trfn_char(glyph_name
[i
], -1,
912 glyph_code
[i
] != 0xffff ? glyph_code
[i
] : 0,
914 owid(glyph_bbox
[i
][0]), owid(glyph_bbox
[i
][1]),
915 owid(glyph_bbox
[i
][2]), owid(glyph_bbox
[i
][3]));
917 if (otf_table(otf_buf
, "kern"))
918 otf_kern(otf_buf
, otf_table(otf_buf
, "kern"));
922 void otf_feat(int r
, int k
, int w
)
927 if (otf_table(otf_buf
, "GSUB"))
928 otf_gsub(otf_buf
, otf_table(otf_buf
, "GSUB"));
929 if (otf_table(otf_buf
, "GPOS"))
930 otf_gpos(otf_buf
, otf_table(otf_buf
, "GPOS"));
934 static int *ggrp_g
[NGRPS
];
935 static int ggrp_len
[NGRPS
];
938 static int ggrp_find(int *src
, int n
)
941 for (i
= 0; i
< ggrp_n
; i
++) {
942 if (ggrp_len
[i
] == n
) {
943 for (j
= 0; j
< n
; j
++)
944 if (src
[j
] != ggrp_g
[i
][j
])
953 static int ggrp_make(int *src
, int n
)
955 int id
= ggrp_find(src
, n
);
960 ggrp_g
[id
] = malloc(n
* sizeof(ggrp_g
[id
][0]));
962 for (i
= 0; i
< n
; i
++)
963 ggrp_g
[id
][i
] = src
[i
];
964 printf("ggrp %d %d", id
, n
);
965 for (i
= 0; i
< n
; i
++)
966 printf(" %s", glyph_name
[src
[i
]]);
971 static char *macset
[] = {
972 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
973 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
974 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
975 "comma", "hyphen", "period", "slash", "zero",
976 "one", "two", "three", "four", "five",
977 "six", "seven", "eight", "nine", "colon",
978 "semicolon", "less", "equal", "greater", "question",
979 "at", "A", "B", "C", "D",
980 "E", "F", "G", "H", "I",
981 "J", "K", "L", "M", "N",
982 "O", "P", "Q", "R", "S",
983 "T", "U", "V", "W", "X",
984 "Y", "Z", "bracketleft", "backslash", "bracketright",
985 "asciicircum", "underscore", "grave", "a", "b",
986 "c", "d", "e", "f", "g",
987 "h", "i", "j", "k", "l",
988 "m", "n", "o", "p", "q",
989 "r", "s", "t", "u", "v",
990 "w", "x", "y", "z", "braceleft",
991 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
992 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
993 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
994 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
995 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
996 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
997 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
998 "dagger", "degree", "cent", "sterling", "section",
999 "bullet", "paragraph", "germandbls", "registered", "copyright",
1000 "trademark", "acute", "dieresis", "notequal", "AE",
1001 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
1002 "yen", "mu", "partialdiff", "summation", "product",
1003 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
1004 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
1005 "radical", "florin", "approxequal", "Delta", "guillemotleft",
1006 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
1007 "Otilde", "OE", "oe", "endash", "emdash",
1008 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
1009 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
1010 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
1011 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
1012 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
1013 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
1014 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
1015 "dotlessi", "circumflex", "tilde", "macron", "breve",
1016 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
1017 "caron", "Lslash", "lslash", "Scaron", "scaron",
1018 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
1019 "Yacute", "yacute", "Thorn", "thorn", "minus",
1020 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
1021 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
1022 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
1023 "Ccaron", "ccaron", "dcroat",