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 */
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 /* report unsupported otf tables */
54 static void otf_unsupported(char *sub
, int type
, int fmt
)
57 fprintf(stderr
, "neatmkfn: unsupported %s lookup %d", sub
, type
);
59 fprintf(stderr
, " format %d", fmt
);
60 fprintf(stderr
, "\n");
64 /* find the otf table with the given name */
65 static void *otf_table(void *otf
, char *name
)
67 int nrecs
= U16(otf
, 4);
69 for (i
= 0; i
< nrecs
; i
++) {
70 void *rec
= otf
+ 12 + i
* 16; /* an otf table record */
71 if (!strncmp(rec
, name
, 4))
72 return otf
+ U32(rec
, 8);
77 /* obtain postscript font name from name table */
78 static void otf_name(void *otf
, void *tab
)
81 void *str
= tab
+ U16(tab
, 4); /* storage area */
82 int n
= U16(tab
, 2); /* number of name records */
84 for (i
= 0; i
< n
; i
++) {
85 void *rec
= tab
+ 6 + 12 * i
;
86 int pid
= U16(rec
, 0); /* platform id */
87 int eid
= U16(rec
, 2); /* encoding id */
88 int lid
= U16(rec
, 4); /* language id */
89 int nid
= U16(rec
, 6); /* name id */
90 int len
= U16(rec
, 8); /* string length */
91 int off
= U16(rec
, 10); /* string offset */
92 if (pid
== 1 && eid
== 0 && lid
== 0 && nid
== 6) {
93 memcpy(name
, str
+ off
, len
);
100 /* parse otf cmap format 4 subtable */
101 static void otf_cmap4(void *otf
, void *cmap4
)
104 void *ends
, *begs
, *deltas
, *offsets
;
105 int beg
, end
, delta
, offset
;
107 nsegs
= U16(cmap4
, 6) / 2;
109 begs
= ends
+ 2 * nsegs
+ 2;
110 deltas
= begs
+ 2 * nsegs
;
111 offsets
= deltas
+ 2 * nsegs
;
112 for (i
= 0; i
< nsegs
; i
++) {
113 beg
= U16(begs
, 2 * i
);
114 end
= U16(ends
, 2 * i
);
115 delta
= U16(deltas
, 2 * i
);
116 offset
= U16(offsets
, 2 * i
);
118 for (j
= beg
; j
<= end
; j
++)
119 glyph_code
[(U16(offsets
+ 2 * i
,
120 offset
+ (j
- beg
) * 2) + delta
) & 0xffff] = j
;
122 for (j
= beg
; j
<= end
; j
++)
123 glyph_code
[(j
+ delta
) & 0xffff] = j
;
128 /* parse otf cmap header */
129 static void otf_cmap(void *otf
, void *cmap
)
131 int nrecs
= U16(cmap
, 2);
133 for (i
= 0; i
< nrecs
; i
++) {
134 void *rec
= cmap
+ 4 + i
* 8; /* a cmap record */
135 int plat
= U16(rec
, 0);
136 int enc
= U16(rec
, 2);
137 void *tab
= cmap
+ U32(rec
, 4); /* a cmap subtable */
138 int fmt
= U16(tab
, 0);
139 if (plat
== 3 && enc
== 1 && fmt
== 4)
144 static void otf_post(void *otf
, void *post
)
146 void *post2
; /* version 2.0 header */
147 void *index
; /* glyph name indices */
148 void *names
; /* glyph names */
151 if (U32(post
, 0) != 0x00020000)
154 glyph_n
= U16(post2
, 0);
156 names
= index
+ 2 * glyph_n
;
157 for (i
= 0; i
< glyph_n
; i
++) {
158 int idx
= U16(index
, 2 * i
);
160 strcpy(glyph_name
[i
], macset
[idx
]);
162 memcpy(glyph_name
[i
], names
+ cname
+ 1,
164 glyph_name
[i
][U8(names
, cname
)] = '\0';
165 cname
+= U8(names
, cname
) + 1;
170 static void otf_glyf(void *otf
, void *glyf
)
172 void *maxp
= otf_table(otf
, "maxp");
173 void *head
= otf_table(otf
, "head");
174 void *loca
= otf_table(otf
, "loca");
177 int n
= U16(maxp
, 4);
178 int fmt
= U16(head
, 50);
180 for (i
= 0; i
< n
; i
++) {
182 gdat
= glyf
+ U32(loca
, 4 * i
);
183 gdat_next
= glyf
+ U32(loca
, 4 * (i
+ 1));
185 gdat
= glyf
+ U16(loca
, 2 * i
) * 2;
186 gdat_next
= glyf
+ U16(loca
, 2 * (i
+ 1)) * 2;
188 if (gdat
< gdat_next
)
189 for (j
= 0; j
< 4; j
++)
190 glyph_bbox
[i
][j
] = S16(gdat
, 2 + 2 * j
);
194 static void otf_hmtx(void *otf
, void *hmtx
)
196 void *hhea
= otf_table(otf
, "hhea");
200 for (i
= 0; i
< n
; i
++)
201 glyph_wid
[i
] = U16(hmtx
, i
* 4);
202 for (i
= n
; i
< glyph_n
; i
++)
203 glyph_wid
[i
] = glyph_wid
[n
- 1];
206 static void otf_kern(void *otf
, void *kern
)
210 int n
= U16(kern
, 2); /* number of kern subtables */
211 for (i
= 0; i
< n
; i
++) {
212 void *tab
= kern
+ off
; /* a kern subtable */
213 int cov
= U16(tab
, 4);
215 if ((cov
>> 8) == 0 && (cov
& 1)) { /* format 0 */
216 int npairs
= U16(tab
, 6);
217 for (j
= 0; j
< npairs
; j
++) {
218 int c1
= U16(tab
, 14 + 6 * j
);
219 int c2
= U16(tab
, 14 + 6 * j
+ 2);
220 int val
= S16(tab
, 14 + 6 * j
+ 4);
221 trfn_kern(glyph_name
[c1
], glyph_name
[c2
],
228 static int coverage(void *cov
, int *out
)
230 int fmt
= U16(cov
, 0);
236 for (i
= 0; i
< n
; i
++)
237 out
[ncov
++] = U16(cov
, 4 + 2 * i
);
240 for (i
= 0; i
< n
; i
++) {
241 beg
= U16(cov
, 4 + 6 * i
);
242 end
= U16(cov
, 4 + 6 * i
+ 2);
243 for (j
= beg
; j
<= end
; j
++)
250 static int classdef(void *tab
, int *gl
, int *cls
)
252 int fmt
= U16(tab
, 0);
256 int beg
= U16(tab
, 2);
258 for (i
= 0; i
< ngl
; i
++) {
260 cls
[i
] = U16(tab
, 6 + 2 * i
);
265 for (i
= 0; i
< n
; i
++) {
266 int beg
= U16(tab
, 4 + 6 * i
);
267 int end
= U16(tab
, 4 + 6 * i
+ 2);
268 for (j
= beg
; j
<= end
; j
++) {
270 cls
[ngl
] = U16(tab
, 4 + 6 * i
+ 4);
278 static int intcmp(void *v1
, void *v2
)
280 return *(int *) v1
- *(int *) v2
;
283 int ggrp_make(int *src
, int n
);
285 static int ggrp_class(int *src
, int *cls
, int nsrc
, int id
)
290 for (i
= 0; i
< nsrc
; i
++)
293 qsort(g
, n
, sizeof(g
[0]), (void *) intcmp
);
294 return ggrp_make(g
, n
);
297 static int ggrp_coverage(int *g
, int n
)
299 qsort(g
, n
, sizeof(g
[0]), (void *) intcmp
);
300 return ggrp_make(g
, n
);
303 static int valuerecord_len(int fmt
)
307 for (i
= 0; i
< 8; i
++)
313 static void valuerecord_print(int fmt
, void *rec
)
318 for (i
= 0; i
< 8; i
++) {
319 if (fmt
& (1 << i
)) {
320 vals
[i
] = uwid(S16(rec
, off
));
325 printf(":%+d%+d%+d%+d", vals
[0], vals
[1], vals
[2], vals
[3]);
328 static int valuerecord_small(int fmt
, void *rec
)
332 for (i
= 0; i
< 8; i
++) {
333 if (fmt
& (1 << i
)) {
334 if (abs(uwid(S16(rec
, off
))) >= MAX(1, kmin
))
342 /* single adjustment positioning */
343 static void otf_gpostype1(void *otf
, void *sub
, char *feat
)
345 int fmt
= U16(sub
, 0);
346 int vfmt
= U16(sub
, 4);
349 int vlen
= valuerecord_len(vfmt
);
351 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
353 for (i
= 0; i
< ncov
; i
++) {
354 if (valuerecord_small(vfmt
, sub
+ 6))
356 printf("gpos %s 1 %s", feat
, glyph_name
[cov
[i
]]);
357 valuerecord_print(vfmt
, sub
+ 6);
363 for (i
= 0; i
< nvals
; i
++) {
364 if (valuerecord_small(vfmt
, sub
+ 6))
366 printf("gpos %s 1 %s", feat
, glyph_name
[cov
[i
]]);
367 valuerecord_print(vfmt
, sub
+ 8 + i
* vlen
);
373 /* pair adjustment positioning */
374 static void otf_gpostype2(void *otf
, void *sub
, char *feat
)
376 int fmt
= U16(sub
, 0);
377 int vfmt1
= U16(sub
, 4); /* valuerecord 1 */
378 int vfmt2
= U16(sub
, 6); /* valuerecord 2 */
379 int fmtoff1
, fmtoff2
;
380 int vrlen
; /* the length of vfmt1 and vfmt2 */
382 vrlen
= valuerecord_len(vfmt1
) + valuerecord_len(vfmt2
);
385 int nc1
= U16(sub
, 8);
386 coverage(sub
+ U16(sub
, 2), cov
);
387 for (i
= 0; i
< nc1
; i
++) {
388 void *c2
= sub
+ U16(sub
, 10 + 2 * i
);
389 int nc2
= U16(c2
, 0);
390 for (j
= 0; j
< nc2
; j
++) {
391 int second
= U16(c2
+ 2 + (2 + vrlen
) * j
, 0);
392 fmtoff1
= 2 + (2 + vrlen
) * j
+ 2;
393 fmtoff2
= fmtoff1
+ valuerecord_len(vfmt1
);
394 if (valuerecord_small(vfmt1
, c2
+ fmtoff1
) &&
395 valuerecord_small(vfmt2
, c2
+ fmtoff2
))
397 printf("gpos %s 2", feat
);
398 printf(" %s", glyph_name
[cov
[i
]]);
399 valuerecord_print(vfmt1
, c2
+ fmtoff1
);
400 printf(" %s", glyph_name
[second
]);
401 valuerecord_print(vfmt2
, c2
+ fmtoff2
);
407 int gl1
[NGLYPHS
], gl2
[NGLYPHS
];
408 int cls1
[NGLYPHS
], cls2
[NGLYPHS
];
409 int grp1
[NGLYPHS
], grp2
[NGLYPHS
];
410 int ngl1
= classdef(sub
+ U16(sub
, 8), gl1
, cls1
);
411 int ngl2
= classdef(sub
+ U16(sub
, 10), gl2
, cls2
);
412 int ncls1
= U16(sub
, 12);
413 int ncls2
= U16(sub
, 14);
414 for (i
= 0; i
< ncls1
; i
++)
415 grp1
[i
] = ggrp_class(gl1
, cls1
, ngl1
, i
);
416 for (i
= 0; i
< ncls2
; i
++)
417 grp2
[i
] = ggrp_class(gl2
, cls2
, ngl2
, i
);
418 for (i
= 0; i
< ncls1
; i
++) {
419 for (j
= 0; j
< ncls2
; j
++) {
420 fmtoff1
= 16 + (i
* ncls2
+ j
) * vrlen
;
421 fmtoff2
= fmtoff1
+ valuerecord_len(vfmt1
);
422 if (valuerecord_small(vfmt1
, sub
+ fmtoff1
) &&
423 valuerecord_small(vfmt2
, sub
+ fmtoff2
))
425 printf("gpos %s %d", feat
, 2);
426 printf(" @%d", grp1
[i
]);
427 valuerecord_print(vfmt1
, sub
+ fmtoff1
);
428 printf(" @%d", grp2
[j
]);
429 valuerecord_print(vfmt2
, sub
+ fmtoff2
);
436 /* cursive attachment positioning */
437 static void otf_gpostype3(void *otf
, void *sub
, char *feat
)
439 int fmt
= U16(sub
, 0);
442 coverage(sub
+ U16(sub
, 2), cov
);
446 for (i
= 0; i
< n
; i
++) {
447 int prev
= U16(sub
, 6 + 4 * i
);
448 int next
= U16(sub
, 6 + 4 * i
+ 2);
449 printf("gcur %s %s", feat
, glyph_name
[cov
[i
]]);
451 printf(" %d %d", uwid(S16(sub
, prev
+ 2)),
452 uwid(S16(sub
, prev
+ 4)));
456 printf(" %d %d", uwid(S16(sub
, next
+ 2)),
457 uwid(S16(sub
, next
+ 4)));
464 /* mark-to-base attachment positioning */
465 static void otf_gpostype4(void *otf
, void *sub
, char *feat
)
467 int fmt
= U16(sub
, 0);
468 int mcov
[NGLYPHS
]; /* mark coverage */
469 int bcov
[NGLYPHS
]; /* base coverage */
470 int cgrp
[1024]; /* glyph groups assigned to classes */
471 int bgrp
; /* the group assigned to base glyphs */
472 int mcnt
; /* mark coverage size */
473 int bcnt
; /* base coverage size */
474 int ccnt
; /* class count */
475 void *marks
; /* mark array table */
476 void *bases
; /* base array table */
480 mcnt
= coverage(sub
+ U16(sub
, 2), mcov
);
481 bcnt
= coverage(sub
+ U16(sub
, 4), bcov
);
483 marks
= sub
+ U16(sub
, 8);
484 bases
= sub
+ U16(sub
, 10);
485 bgrp
= ggrp_coverage(bcov
, bcnt
);
486 for (i
= 0; i
< ccnt
; i
++) {
489 for (j
= 0; j
< mcnt
; j
++)
490 if (U16(marks
, 2 + 4 * j
) == i
)
491 grp
[cnt
++] = mcov
[j
];
492 cgrp
[i
] = ggrp_coverage(grp
, cnt
);
494 for (i
= 0; i
< mcnt
; i
++) {
495 void *mark
= marks
+ U16(marks
, 2 + 4 * i
+ 2); /* mark anchor */
496 int dx
= -uwid(S16(mark
, 2));
497 int dy
= uwid(S16(mark
, 4));
498 printf("gpos %s 2 @%d %s:%+d%+d%+d%+d\n",
499 feat
, bgrp
, glyph_name
[mcov
[i
]], dx
, dy
, 0, 0);
501 for (i
= 0; i
< bcnt
; i
++) {
502 for (j
= 0; j
< ccnt
; j
++) {
503 void *base
= bases
+ U16(bases
, 2 + ccnt
* 2 * i
+ 2 * j
);
504 int dx
= uwid(S16(base
, 2));
505 int dy
= -uwid(S16(base
, 4));
506 printf("gpos %s 2 %s @%d:%+d%+d%+d%+d\n",
507 feat
, glyph_name
[bcov
[i
]], cgrp
[j
], dx
, dy
, 0, 0);
514 int bgrp
[GCTXLEN
]; /* backtrack coverage arrays */
515 int igrp
[GCTXLEN
]; /* input coverage arrays */
516 int lgrp
[GCTXLEN
]; /* lookahead coverage arrays*/
517 int bn
, in
, ln
; /* size of b[], i[], l[] */
518 int seqidx
; /* sequence index */
521 static int gctx_len(struct gctx
*ctx
, int patlen
)
523 return ctx
? ctx
->bn
+ ctx
->in
+ ctx
->ln
- patlen
: 0;
526 static void gctx_backtrack(struct gctx
*ctx
)
531 for (i
= 0; i
< ctx
->bn
; i
++)
532 printf(" =@%d", ctx
->bgrp
[i
]);
533 for (i
= 0; i
< ctx
->seqidx
; i
++)
534 printf(" =@%d", ctx
->igrp
[i
]);
537 static void gctx_lookahead(struct gctx
*ctx
, int patlen
)
542 for (i
= ctx
->seqidx
+ patlen
; i
< ctx
->in
; i
++)
543 printf(" =@%d", ctx
->igrp
[i
]);
544 for (i
= 0; i
< ctx
->ln
; i
++)
545 printf(" =@%d", ctx
->lgrp
[i
]);
548 /* single substitution */
549 static void otf_gsubtype1(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
552 int fmt
= U16(sub
, 0);
555 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
557 for (i
= 0; i
< ncov
; i
++) {
558 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
560 printf(" -%s +%s", glyph_name
[cov
[i
]],
561 glyph_name
[cov
[i
] + S16(sub
, 4)]);
562 gctx_lookahead(ctx
, 1);
568 for (i
= 0; i
< n
; i
++) {
569 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
571 printf(" -%s +%s", glyph_name
[cov
[i
]],
572 glyph_name
[U16(sub
, 6 + 2 * i
)]);
573 gctx_lookahead(ctx
, 1);
579 /* alternate substitution */
580 static void otf_gsubtype3(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
583 int fmt
= U16(sub
, 0);
587 coverage(sub
+ U16(sub
, 2), cov
);
589 for (i
= 0; i
< n
; i
++) {
590 void *alt
= sub
+ U16(sub
, 6 + 2 * i
);
591 int nalt
= U16(alt
, 0);
592 for (j
= 0; j
< nalt
; j
++) {
593 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
595 printf(" -%s +%s", glyph_name
[cov
[i
]],
596 glyph_name
[U16(alt
, 2 + 2 * j
)]);
597 gctx_lookahead(ctx
, 1);
603 /* ligature substitution */
604 static void otf_gsubtype4(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
606 int fmt
= U16(sub
, 0);
611 coverage(sub
+ U16(sub
, 2), cov
);
613 for (i
= 0; i
< n
; i
++) {
614 void *set
= sub
+ U16(sub
, 6 + 2 * i
);
615 int nset
= U16(set
, 0);
616 for (j
= 0; j
< nset
; j
++) {
617 void *lig
= set
+ U16(set
, 2 + 2 * j
);
618 int nlig
= U16(lig
, 2);
619 printf("gsub %s %d", feat
, nlig
+ 1 + gctx_len(ctx
, nlig
));
621 printf(" -%s", glyph_name
[cov
[i
]]);
622 for (k
= 0; k
< nlig
- 1; k
++)
623 printf(" -%s", glyph_name
[U16(lig
, 4 + 2 * k
)]);
624 printf(" +%s", glyph_name
[U16(lig
, 0)]);
625 gctx_lookahead(ctx
, nlig
);
631 /* chaining contextual substitution */
632 static void otf_gsubtype6(void *otf
, void *sub
, char *feat
, void *gsub
)
634 struct gctx ctx
= {{0}};
635 void *lookups
= gsub
+ U16(gsub
, 8);
636 int fmt
= U16(sub
, 0);
638 int i
, j
, nsub
, ncov
;
641 otf_unsupported("GSUB", 6, fmt
);
644 ctx
.bn
= U16(sub
, off
);
645 for (i
= 0; i
< ctx
.bn
; i
++) {
646 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
647 ctx
.bgrp
[i
] = ggrp_coverage(cov
, ncov
);
649 off
+= 2 + 2 * ctx
.bn
;
650 ctx
.in
= U16(sub
, off
);
651 for (i
= 0; i
< ctx
.in
; i
++) {
652 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
653 ctx
.igrp
[i
] = ggrp_coverage(cov
, ncov
);
655 off
+= 2 + 2 * ctx
.in
;
656 ctx
.ln
= U16(sub
, off
);
657 for (i
= 0; i
< ctx
.ln
; i
++) {
658 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
659 ctx
.lgrp
[i
] = ggrp_coverage(cov
, ncov
);
661 off
+= 2 + 2 * ctx
.ln
;
662 nsub
= U16(sub
, off
); /* nsub > 1 is not supported */
663 for (i
= 0; i
< nsub
&& i
< 1; i
++) {
664 int lidx
= U16(sub
, off
+ 2 + 4 * i
+ 2);
665 void *lookup
= lookups
+ U16(lookups
, 2 + 2 * lidx
);
666 int ltype
= U16(lookup
, 0);
667 int ntabs
= U16(lookup
, 4);
668 ctx
.seqidx
= U16(sub
, off
+ 2 + 4 * i
);
669 for (j
= 0; j
< ntabs
; j
++) {
670 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
672 if (type
== 7) { /* extension substitution */
674 tab
= tab
+ U32(tab
, 4);
677 otf_gsubtype1(otf
, tab
, feat
, &ctx
);
679 otf_gsubtype3(otf
, tab
, feat
, &ctx
);
681 otf_gsubtype4(otf
, tab
, feat
, &ctx
);
686 /* an otf gsub/gpos lookup */
688 char feat
[8]; /* feature name */
689 int lookup
; /* index into the lookup table */
692 /* parse the given gsub/gpos feature table */
693 static int otf_featrec(void *otf
, void *gtab
, void *featrec
, struct otflookup
*lookups
)
695 void *feats
= gtab
+ U16(gtab
, 6);
696 void *feat
= feats
+ U16(featrec
, 4);
697 int nlookups
= U16(feat
, 2);
699 for (i
= 0; i
< nlookups
; i
++) {
700 memcpy(lookups
[i
].feat
, featrec
, 4);
701 lookups
[i
].feat
[4] = '\0';
702 lookups
[i
].lookup
= U16(feat
, 4 + 2 * i
);
707 /* parse the given language table and its feature tables */
708 static int otf_lang(void *otf
, void *gtab
, void *lang
, struct otflookup
*lookups
)
710 void *feats
= gtab
+ U16(gtab
, 6);
711 int featidx
= U16(lang
, 2);
712 int nfeat
= U16(lang
, 4);
715 if (featidx
!= 0xffff)
716 n
+= otf_featrec(otf
, gtab
, feats
+ 2 + 6 * featidx
, lookups
+ n
);
717 for (i
= 0; i
< nfeat
; i
++)
718 n
+= otf_featrec(otf
, gtab
,
719 feats
+ 2 + 6 * U16(lang
, 6 + 2 * i
), lookups
+ n
);
723 static int lookupcmp(void *v1
, void *v2
)
725 struct otflookup
*l1
= v1
;
726 struct otflookup
*l2
= v2
;
727 if (trfn_featrank(l1
->feat
) != trfn_featrank(l2
->feat
))
728 return trfn_featrank(l1
->feat
) - trfn_featrank(l2
->feat
);
729 return l1
->lookup
- l2
->lookup
;
732 /* extract lookup tables for all features of the given gsub/gpos table */
733 static int otf_gtab(void *otf
, void *gpos
, struct otflookup
*lookups
)
735 void *scripts
= gpos
+ U16(gpos
, 4);
736 int nscripts
, nlangs
;
741 nscripts
= U16(scripts
, 0);
742 for (i
= 0; i
< nscripts
; i
++) {
743 void *grec
= scripts
+ 2 + 6 * i
;
744 memcpy(tag
, grec
, 4);
746 if (!trfn_script(tag
, nscripts
))
748 script
= scripts
+ U16(grec
, 4);
749 nlangs
= U16(script
, 2);
750 if (U16(script
, 0) && trfn_lang(NULL
, nlangs
+ (U16(script
, 0) != 0)))
751 n
+= otf_lang(otf
, gpos
, script
+ U16(script
, 0), lookups
+ n
);
752 for (j
= 0; j
< nlangs
; j
++) {
753 void *lrec
= script
+ 4 + 6 * j
;
754 memcpy(tag
, lrec
, 4);
756 if (trfn_lang(tag
, nlangs
+ (U16(script
, 0) != 0)))
757 n
+= otf_lang(otf
, gpos
, script
+ U16(lrec
, 4), lookups
+ n
);
760 qsort(lookups
, n
, sizeof(lookups
[0]), (void *) lookupcmp
);
764 static void otf_gpos(void *otf
, void *gpos
)
766 struct otflookup lookups
[NLOOKUPS
];
767 void *lookuplist
= gpos
+ U16(gpos
, 8);
768 int nlookups
= otf_gtab(otf
, gpos
, lookups
);
770 for (i
= 0; i
< nlookups
; i
++) {
771 void *lookup
= lookuplist
+ U16(lookuplist
, 2 + 2 * lookups
[i
].lookup
);
772 char *tag
= lookups
[i
].feat
;
773 int ltype
= U16(lookup
, 0);
774 int ntabs
= U16(lookup
, 4);
775 for (j
= 0; j
< ntabs
; j
++) {
776 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
778 if (type
== 9) { /* extension positioning */
780 tab
= tab
+ U32(tab
, 4);
784 otf_gpostype1(otf
, tab
, tag
);
787 otf_gpostype2(otf
, tab
, tag
);
790 otf_gpostype3(otf
, tab
, tag
);
793 otf_gpostype4(otf
, tab
, tag
);
796 otf_unsupported("GPOS", type
, 0);
802 static void otf_gsub(void *otf
, void *gsub
)
804 struct otflookup lookups
[NLOOKUPS
];
805 void *lookuplist
= gsub
+ U16(gsub
, 8);
806 int nlookups
= otf_gtab(otf
, gsub
, lookups
);
808 for (i
= 0; i
< nlookups
; i
++) {
809 void *lookup
= lookuplist
+ U16(lookuplist
, 2 + 2 * lookups
[i
].lookup
);
810 char *tag
= lookups
[i
].feat
;
811 int ltype
= U16(lookup
, 0);
812 int ntabs
= U16(lookup
, 4);
813 for (j
= 0; j
< ntabs
; j
++) {
814 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
816 if (type
== 7) { /* extension substitution */
818 tab
= tab
+ U32(tab
, 4);
822 otf_gsubtype1(otf
, tab
, tag
, NULL
);
825 otf_gsubtype3(otf
, tab
, tag
, NULL
);
828 otf_gsubtype4(otf
, tab
, tag
, NULL
);
831 otf_gsubtype6(otf
, tab
, tag
, gsub
);
834 otf_unsupported("GSUB", type
, 0);
840 static int xread(int fd
, char *buf
, int len
)
844 int ret
= read(fd
, buf
+ nr
, len
- nr
);
845 if (ret
== -1 && (errno
== EAGAIN
|| errno
== EINTR
))
854 static char buf
[BUFLEN
];
859 if (xread(0, buf
, sizeof(buf
)) <= 0)
861 upm
= U16(otf_table(buf
, "head"), 18);
862 otf_name(buf
, otf_table(buf
, "name"));
863 otf_cmap(buf
, otf_table(buf
, "cmap"));
864 otf_post(buf
, otf_table(buf
, "post"));
865 if (otf_table(buf
, "glyf"))
866 otf_glyf(buf
, otf_table(buf
, "glyf"));
867 otf_hmtx(buf
, otf_table(buf
, "hmtx"));
868 for (i
= 0; i
< glyph_n
; i
++) {
869 trfn_char(glyph_name
[i
], -1,
870 glyph_code
[i
] != 0xffff ? glyph_code
[i
] : 0,
872 owid(glyph_bbox
[i
][0]), owid(glyph_bbox
[i
][1]),
873 owid(glyph_bbox
[i
][2]), owid(glyph_bbox
[i
][3]));
875 if (otf_table(buf
, "kern"))
876 otf_kern(buf
, otf_table(buf
, "kern"));
880 void otf_feat(int r
, int k
, int w
)
885 if (otf_table(buf
, "GSUB"))
886 otf_gsub(buf
, otf_table(buf
, "GSUB"));
887 if (otf_table(buf
, "GPOS"))
888 otf_gpos(buf
, otf_table(buf
, "GPOS"));
892 static int *ggrp_g
[NGRPS
];
893 static int ggrp_len
[NGRPS
];
896 static int ggrp_find(int *src
, int n
)
899 for (i
= 0; i
< ggrp_n
; i
++) {
900 if (ggrp_len
[i
] == n
) {
901 for (j
= 0; j
< n
; j
++)
902 if (src
[j
] != ggrp_g
[i
][j
])
911 int ggrp_make(int *src
, int n
)
913 int id
= ggrp_find(src
, n
);
918 ggrp_g
[id
] = malloc(n
* sizeof(ggrp_g
[id
][0]));
920 for (i
= 0; i
< n
; i
++)
921 ggrp_g
[id
][i
] = src
[i
];
922 printf("ggrp %d %d", id
, n
);
923 for (i
= 0; i
< n
; i
++)
924 printf(" %s", glyph_name
[src
[i
]]);
929 static char *macset
[] = {
930 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
931 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
932 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
933 "comma", "hyphen", "period", "slash", "zero",
934 "one", "two", "three", "four", "five",
935 "six", "seven", "eight", "nine", "colon",
936 "semicolon", "less", "equal", "greater", "question",
937 "at", "A", "B", "C", "D",
938 "E", "F", "G", "H", "I",
939 "J", "K", "L", "M", "N",
940 "O", "P", "Q", "R", "S",
941 "T", "U", "V", "W", "X",
942 "Y", "Z", "bracketleft", "backslash", "bracketright",
943 "asciicircum", "underscore", "grave", "a", "b",
944 "c", "d", "e", "f", "g",
945 "h", "i", "j", "k", "l",
946 "m", "n", "o", "p", "q",
947 "r", "s", "t", "u", "v",
948 "w", "x", "y", "z", "braceleft",
949 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
950 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
951 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
952 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
953 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
954 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
955 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
956 "dagger", "degree", "cent", "sterling", "section",
957 "bullet", "paragraph", "germandbls", "registered", "copyright",
958 "trademark", "acute", "dieresis", "notequal", "AE",
959 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
960 "yen", "mu", "partialdiff", "summation", "product",
961 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
962 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
963 "radical", "florin", "approxequal", "Delta", "guillemotleft",
964 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
965 "Otilde", "OE", "oe", "endash", "emdash",
966 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
967 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
968 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
969 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
970 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
971 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
972 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
973 "dotlessi", "circumflex", "tilde", "macron", "breve",
974 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
975 "caron", "Lslash", "lslash", "Scaron", "scaron",
976 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
977 "Yacute", "yacute", "Thorn", "thorn", "minus",
978 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
979 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
980 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
981 "Ccaron", "ccaron", "dcroat",