beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / luafontloader / fontforge / fontforge / ttfspecial.c
blobdad61caa268165174423c796b4a2e8b54c4a7d26
1 /* Copyright (C) 2000-2008 by George Williams */
2 /*
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright notice, this
7 * list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
13 * The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "pfaedit.h"
28 #include <math.h>
29 #include <time.h>
30 #include <utype.h>
31 #include <ustring.h>
32 #include <gimage.h> /* For COLOR_DEFAULT */
34 #include "ttf.h"
36 /* This file contains routines to generate non-standard true/opentype tables */
37 /* The first is the 'PfEd' table containing PfaEdit specific information */
38 /* glyph comments & colours ... perhaps other info later */
40 /* ************************************************************************** */
41 /* ************************* The 'PfEd' table ************************* */
42 /* ************************* Output ************************* */
43 /* ************************************************************************** */
45 #include "PfEd.h" /* This describes the format of the 'PfEd' table */
46 /* and its many subtables. */
48 #define MAX_SUBTABLE_TYPES 20
50 /* ************************* The 'PfEd' table ************************* */
51 /* ************************* Input ************************* */
53 static void pfed_readfontcomment(FILE *ttf,struct ttfinfo *info,uint32 base,
54 uint32 tag) {
55 int len;
56 char *start, *pt, *end;
57 int use_utf8;
59 fseek(ttf,base,SEEK_SET);
60 use_utf8 = getushort(ttf);
61 if ( use_utf8!=0 && use_utf8!=1 )
62 return; /* Bad version number */
63 len = getushort(ttf);
64 start = pt = galloc(len+1);
66 end = pt+len;
67 if ( use_utf8 ) {
68 while ( pt<end )
69 *pt++ = getc(ttf);
70 } else {
71 while ( pt<end )
72 *pt++ = getushort(ttf);
74 *pt = '\0';
75 if ( !use_utf8 ) {
76 pt = latin1_2_utf8_copy(info->fontcomments);
77 free(start);
78 start = pt;
80 if ( tag==flog_TAG )
81 info->fontlog = start;
82 else
83 info->fontcomments = start;
86 static char *pfed_read_utf8(FILE *ttf, uint32 start) {
87 int ch, len;
88 char *str, *pt;
90 fseek( ttf, start, SEEK_SET);
91 len = 0;
92 while ( (ch=getc(ttf))!='\0' && ch!=EOF )
93 ++len;
94 fseek( ttf, start, SEEK_SET);
95 str = pt = galloc(len+1);
96 while ( (ch=getc(ttf))!='\0' && ch!=EOF )
97 *pt++ = ch;
98 *pt = '\0';
99 return( str );
102 static char *pfed_read_ucs2_len(FILE *ttf,uint32 offset,int len) {
103 char *pt, *str;
104 uint32 uch, uch2;
105 int i;
107 if ( len<0 )
108 return( NULL );
110 len>>=1;
111 pt = str = galloc(3*len);
112 fseek(ttf,offset,SEEK_SET);
113 for ( i=0; i<len; ++i ) {
114 uch = getushort(ttf);
115 if ( uch>=0xd800 && uch<0xdc00 ) {
116 uch2 = getushort(ttf);
117 if ( uch2>=0xdc00 && uch2<0xe000 )
118 uch = ((uch-0xd800)<<10) | (uch2&0x3ff);
119 else {
120 pt = utf8_idpb(pt,uch);
121 uch = uch2;
124 pt = utf8_idpb(pt,uch);
126 *pt++ = 0;
127 return( grealloc(str,pt-str) );
130 static char *pfed_read_utf8_len(FILE *ttf,uint32 offset,int len) {
131 char *pt, *str;
132 int i;
134 if ( len<0 )
135 return( NULL );
137 pt = str = galloc(len+1);
138 fseek(ttf,offset,SEEK_SET);
139 for ( i=0; i<len; ++i )
140 *pt++ = getc(ttf);
141 *pt = '\0';
142 return( str );
145 static void pfed_readcvtcomments(FILE *ttf,struct ttfinfo *info,uint32 base ) {
146 int count, i;
147 uint16 *offsets;
149 fseek(ttf,base,SEEK_SET);
150 if ( getushort(ttf)!=0 )
151 return; /* Bad version number */
152 count = getushort(ttf);
154 offsets = galloc(count*sizeof(uint16));
155 info->cvt_names = galloc((count+1)*sizeof(char *));
156 for ( i=0; i<count; ++i )
157 offsets[i] = getushort(ttf);
158 for ( i=0; i<count; ++i ) {
159 if ( offsets[i]==0 )
160 info->cvt_names[i] = NULL;
161 else
162 info->cvt_names[i] = pfed_read_utf8(ttf,base+offsets[i]);
164 free(offsets);
167 static void pfed_readglyphcomments(FILE *ttf,struct ttfinfo *info,uint32 base) {
168 int n, i, j;
169 struct grange { int start, end; uint32 offset; } *grange;
170 uint32 offset, next;
171 int use_utf8;
173 fseek(ttf,base,SEEK_SET);
174 use_utf8 = getushort(ttf);
175 if ( use_utf8!=0 && use_utf8!=1 )
176 return; /* Bad version number */
177 n = getushort(ttf);
178 grange = galloc(n*sizeof(struct grange));
179 for ( i=0; i<n; ++i ) {
180 grange[i].start = getushort(ttf);
181 grange[i].end = getushort(ttf);
182 grange[i].offset = getlong(ttf);
183 if ( grange[i].start>grange[i].end || grange[i].end>info->glyph_cnt ) {
184 LogError( _("Bad glyph range specified in glyph comment subtable of PfEd table\n") );
185 grange[i].start = 1; grange[i].end = 0;
188 for ( i=0; i<n; ++i ) {
189 for ( j=grange[i].start; j<=grange[i].end; ++j ) {
190 fseek( ttf,base+grange[i].offset+(j-grange[i].start)*sizeof(uint32),SEEK_SET);
191 offset = getlong(ttf);
192 next = getlong(ttf);
193 if ( use_utf8 )
194 info->chars[j]->comment = pfed_read_utf8_len(ttf,base+offset,next-offset);
195 else
196 info->chars[j]->comment = pfed_read_ucs2_len(ttf,base+offset,next-offset);
197 if ( info->chars[j]->comment == NULL )
198 LogError("Invalid comment string (negative length?) in 'PfEd' table for glyph %s.",
199 info->chars[j]->name );
202 free(grange);
205 static void pfed_readcolours(FILE *ttf,struct ttfinfo *info,uint32 base) {
206 int n, i, j, start, end;
207 uint32 col;
209 fseek(ttf,base,SEEK_SET);
210 if ( getushort(ttf)!=0 )
211 return; /* Bad version number */
212 n = getushort(ttf);
213 for ( i=0; i<n; ++i ) {
214 start = getushort(ttf);
215 end = getushort(ttf);
216 col = getlong(ttf);
217 if ( start>end || end>info->glyph_cnt )
218 LogError( _("Bad glyph range specified in colour subtable of PfEd table\n") );
219 else {
220 for ( j=start; j<=end; ++j )
221 info->chars[j]->color = col;
226 static void pfed_readlookupnames(FILE *ttf,struct ttfinfo *info,uint32 base,
227 OTLookup *lookups) {
228 OTLookup *otl;
229 struct lookup_subtable *sub;
230 AnchorClass *ac;
231 int i, j, k, n, s, a;
232 struct lstruct { int name_off, subs_off; } *ls, *ss, *as;
234 fseek(ttf,base,SEEK_SET);
235 if ( getushort(ttf)!=0 )
236 return; /* Bad version number */
237 n = getushort(ttf);
238 ls = galloc(n*sizeof(struct lstruct));
239 for ( i=0; i<n; ++i ) {
240 ls[i].name_off = getushort(ttf);
241 ls[i].subs_off = getushort(ttf);
243 for ( i=0, otl=lookups; i<n && otl!=NULL; ++i, otl=otl->next ) {
244 if ( ls[i].name_off!=0 ) {
245 free( otl->lookup_name );
246 otl->lookup_name = pfed_read_utf8(ttf,base+ls[i].name_off);
248 if ( ls[i].subs_off!=0 ) {
249 fseek(ttf,base+ls[i].subs_off,SEEK_SET);
250 s = getushort(ttf);
251 ss = galloc(s*sizeof(struct lstruct));
252 for ( j=0; j<s; ++j ) {
253 ss[j].name_off = getushort(ttf);
254 ss[j].subs_off = getushort(ttf);
256 for ( j=0, sub=otl->subtables; j<s && sub!=NULL; ++j, sub=sub->next ) {
257 if ( ss[j].name_off!=0 ) {
258 free( sub->subtable_name );
259 sub->subtable_name = pfed_read_utf8(ttf,base+ss[j].name_off);
261 if ( ss[j].subs_off!=0 ) {
262 if ( !sub->anchor_classes )
263 LogError("Whoops, attempt to name anchors in a subtable which doesn't contain any\n");
264 else {
265 fseek(ttf,base+ss[j].subs_off,SEEK_SET);
266 a = getushort(ttf);
267 as = galloc(a*sizeof(struct lstruct));
268 for ( k=0; k<a; ++k ) {
269 as[k].name_off = getushort(ttf);
271 k=0;
272 for ( ac=info->ahead; ac!=NULL; ac=ac->next ) {
273 if ( ac->subtable==sub ) {
274 if ( as[k].name_off!=0 ) {
275 free( ac->name );
276 ac->name = pfed_read_utf8(ttf,base+as[k].name_off);
278 ++k;
281 free(as);
285 /* I guess it's ok for some subtables to be unnamed, so no check for sub!=NULL */
286 if ( j<s )
287 LogError("Whoops, more names than subtables of lookup %s\n", otl->lookup_name );
288 free(ss);
291 /* I guess it's ok for some lookups to be unnamed, so no check for otf!=NULL */
292 if ( i<n )
293 LogError("Whoops, more names than lookups\n" );
294 free(ls);
297 static float pfed_get_coord(FILE *ttf,int mod) {
298 if ( mod==V_B )
299 return( (float) (signed char) getc(ttf) );
300 else if ( mod==V_S )
301 return( (float) (short) getushort(ttf));
302 else if ( mod==V_F )
303 return( getlong(ttf)/256.0 );
304 else {
305 LogError( "Bad data type in contour verb in 'PfEd'\n");
306 return( 0 );
310 static void pfed_read_normal_contour(FILE *ttf,SplineSet *ss,
311 uint32 base, int type) {
312 SplinePoint *sp, *current;
313 int verb, v, m;
314 float offx, offy, offx1 = 0, offy1 = 0, offx2, offy2;
315 int was_implicit=false;
317 fseek(ttf,base,SEEK_SET);
319 verb = getc(ttf);
320 if ( COM_VERB(verb)!=V_MoveTo ) {
321 LogError("Whoops, contours must begin with a move to\n" );
322 ss->first = ss->last = SplinePointCreate(0,0);
323 return;
325 offx = pfed_get_coord(ttf,COM_MOD(verb));
326 offy = pfed_get_coord(ttf,COM_MOD(verb));
327 ss->first = current = SplinePointCreate(offx,offy);
328 forever {
329 verb = getc(ttf);
330 v = COM_VERB(verb); m = COM_MOD(verb);
331 if ( m==3 ) {
332 LogError("Bad data modifier in contour command in 'PfEd'\n" );
333 break;
335 if ( verb==V_Close || verb==V_End )
336 break;
337 else if ( v>=V_LineTo && v<=V_VLineTo ) {
338 offx = offy = 0;
339 if ( v==V_LineTo ) {
340 offx = pfed_get_coord(ttf,m);
341 offy = pfed_get_coord(ttf,m);
342 } else if ( v==V_HLineTo )
343 offx = pfed_get_coord(ttf,m);
344 else if ( v==V_VLineTo )
345 offy = pfed_get_coord(ttf,m);
346 sp = SplinePointCreate(current->me.x+offx,current->me.y+offy);
347 } else if ( v>=V_QCurveTo && v<=V_QVImplicit ) {
348 int will_be_implicit = true;
349 offx = offy = 0; offx1 = offy1 = 1; /* else implicit points become straight lines too soon */
350 if ( v==V_QCurveTo ) {
351 offx = pfed_get_coord(ttf,m);
352 offy = pfed_get_coord(ttf,m);
353 offx1 = pfed_get_coord(ttf,m);
354 offy1 = pfed_get_coord(ttf,m);
355 will_be_implicit = false;
356 } else if ( v==V_QImplicit ) {
357 offx = pfed_get_coord(ttf,m);
358 offy = pfed_get_coord(ttf,m);
359 } else if ( v==V_QHImplicit ) {
360 offx = pfed_get_coord(ttf,m);
361 } else if ( v==V_QVImplicit ) {
362 offy = pfed_get_coord(ttf,m);
365 current->nextcp.x = current->me.x+offx;
366 current->nextcp.y = current->me.y+offy;
367 current->nonextcp = false;
368 sp = SplinePointCreate(current->nextcp.x+offx1,current->nextcp.y+offy1);
369 sp->prevcp = current->nextcp;
370 sp->noprevcp = false;
371 if ( was_implicit ) {
372 current->me.x = (current->prevcp.x + current->nextcp.x)/2;
373 current->me.y = (current->prevcp.y + current->nextcp.y)/2;
374 SplineRefigure(current->prev);
376 was_implicit = will_be_implicit;
377 } else if ( v>=V_CurveTo && v<=V_HVCurveTo ) {
378 offx=offy=offx2=offy2=0;
379 if ( v==V_CurveTo ) {
380 offx = pfed_get_coord(ttf,m);
381 offy = pfed_get_coord(ttf,m);
382 offx1 = pfed_get_coord(ttf,m);
383 offy1 = pfed_get_coord(ttf,m);
384 offx2 = pfed_get_coord(ttf,m);
385 offy2 = pfed_get_coord(ttf,m);
386 } else if ( v==V_VHCurveTo ) {
387 offy = pfed_get_coord(ttf,m);
388 offx1 = pfed_get_coord(ttf,m);
389 offy1 = pfed_get_coord(ttf,m);
390 offx2 = pfed_get_coord(ttf,m);
391 } else if ( v==V_HVCurveTo ) {
392 offx = pfed_get_coord(ttf,m);
393 offx1 = pfed_get_coord(ttf,m);
394 offy1 = pfed_get_coord(ttf,m);
395 offy2 = pfed_get_coord(ttf,m);
397 current->nextcp.x = current->me.x+offx;
398 current->nextcp.y = current->me.y+offy;
399 current->nonextcp = false;
400 sp = SplinePointCreate(current->nextcp.x+offx1+offx2,current->nextcp.y+offy1+offy2);
401 sp->prevcp.x = current->nextcp.x+offx1;
402 sp->prevcp.y = current->nextcp.y+offy1;
403 sp->noprevcp = false;
404 } else {
405 LogError("Whoops, unexpected verb in contour %d.%d\n", v, m );
406 break;
408 SplineMake(current,sp,type==2);
409 current = sp;
411 if ( verb==V_Close ) {
412 if ( was_implicit ) {
413 current->me.x = (current->prevcp.x + ss->first->nextcp.x)/2;
414 current->me.y = (current->prevcp.y + ss->first->nextcp.y)/2;
416 if ( current->me.x==ss->first->me.x && current->me.y==ss->first->me.y ) {
417 current->prev->to = ss->first;
418 ss->first->prev = current->prev;
419 ss->first->prevcp = current->prevcp;
420 ss->first->noprevcp = current->noprevcp;
421 SplinePointFree(current);
422 } else
423 SplineMake(current,ss->first,type==2);
424 ss->last = ss->first;
425 } else {
426 ss->last = current;
428 SPLCatagorizePoints(ss);
432 static void pfed_read_glyph_layer(FILE *ttf,struct ttfinfo *info,Layer *ly,
433 uint32 base, int type, int version) {
434 int cc, ic, rc, i, j;
435 SplineSet *ss;
436 struct contours { int data_off, name_off; SplineSet *ss; } *contours;
437 int gid;
438 RefChar *last, *cur;
440 fseek(ttf,base,SEEK_SET);
441 cc = getushort(ttf);
442 rc = 0;
443 if ( version==1 )
444 rc = getushort(ttf);
445 ic = getushort(ttf);
446 contours = galloc(cc*sizeof(struct contours));
447 for ( i=0; i<cc; ++i ) {
448 contours[i].data_off = getushort(ttf);
449 contours[i].name_off = getushort(ttf);
451 last = NULL;
452 for ( i=0; i<rc; ++i ) {
453 cur = RefCharCreate();
454 for ( j=0; j<6; ++j )
455 cur->transform[j] = getlong(ttf)/32768.0;
456 gid = getushort(ttf);
457 cur->sc = info->chars[gid];
458 cur->orig_pos = gid;
459 cur->unicode_enc = cur->sc->unicodeenc;
460 if ( last==NULL )
461 ly->refs = cur;
462 else
463 last->next = cur;
464 last = cur;
467 ss = ly->splines; /* Only relevant for spiros where they live in someone else's layer */
468 for ( i=0; i<cc; ++i ) {
469 if ( type!=1 ) { /* Not spiros */
470 contours[i].ss = chunkalloc(sizeof(SplineSet));
471 if ( i==0 )
472 ly->splines = contours[i].ss;
473 else
474 contours[i-1].ss->next = contours[i].ss;
475 if ( contours[i].name_off!=0 )
476 contours[i].ss->contour_name = pfed_read_utf8(ttf,base+contours[i].name_off);
477 pfed_read_normal_contour(ttf,contours[i].ss,base+contours[i].data_off,type);
480 free(contours);
483 static void pfed_readguidelines(FILE *ttf,struct ttfinfo *info,uint32 base) {
484 int i,v,h,off;
485 int version;
486 SplinePoint *sp, *nsp;
487 SplineSet *ss;
489 fseek(ttf,base,SEEK_SET);
490 version = getushort(ttf);
491 if ( version>1 )
492 return; /* Bad version number */
493 v = getushort(ttf);
494 h = getushort(ttf);
495 (void) getushort(ttf);
496 off = getushort(ttf);
498 if ( off!=0 ) {
499 pfed_read_glyph_layer(ttf,info,&info->guidelines,base+off,info->to_order2?2:3,version);
500 } else {
501 struct npos { int pos; int offset; } *vs, *hs;
502 vs = galloc(v*sizeof(struct npos));
503 hs = galloc(h*sizeof(struct npos));
504 for ( i=0; i<v; ++i ) {
505 vs[i].pos = (short) getushort(ttf);
506 vs[i].offset = getushort(ttf);
508 for ( i=0; i<h; ++i ) {
509 hs[i].pos = (short) getushort(ttf);
510 hs[i].offset = getushort(ttf);
512 for ( i=0; i<v; ++i ) {
513 sp = SplinePointCreate(vs[i].pos,-info->emsize);
514 nsp = SplinePointCreate(vs[i].pos,2*info->emsize);
515 SplineMake(sp,nsp,info->to_order2);
516 ss = chunkalloc(sizeof(SplineSet));
517 ss->first = sp; ss->last = nsp;
518 if ( vs[i].offset!=0 )
519 ss->contour_name = pfed_read_utf8(ttf,base+vs[i].offset);
520 ss->next = info->guidelines.splines;
521 info->guidelines.splines = ss;
523 for ( i=0; i<h; ++i ) {
524 sp = SplinePointCreate(-info->emsize,hs[i].pos);
525 nsp = SplinePointCreate(2*info->emsize,hs[i].pos);
526 SplineMake(sp,nsp,info->to_order2);
527 ss = chunkalloc(sizeof(SplineSet));
528 ss->first = sp; ss->last = nsp;
529 if ( hs[i].offset!=0 )
530 ss->contour_name = pfed_read_utf8(ttf,base+hs[i].offset);
531 ss->next = info->guidelines.splines;
532 info->guidelines.splines = ss;
534 SPLCatagorizePoints(info->guidelines.splines);
535 free(vs); free(hs);
539 static void pfed_redo_refs(SplineChar *sc,int layer) {
540 RefChar *refs;
542 sc->ticked = true;
543 for ( refs=sc->layers[layer].refs; refs!=NULL; refs=refs->next ) {
544 if ( !refs->sc->ticked )
545 pfed_redo_refs(refs->sc,layer);
546 SCReinstanciateRefChar(sc,refs,layer);
550 static void pfed_read_layer(FILE *ttf,struct ttfinfo *info,int layer,int type, uint32 base,
551 uint32 start,int version) {
552 uint32 *loca = gcalloc(info->glyph_cnt,sizeof(uint32));
553 int i,j;
554 SplineChar *sc;
555 int rcnt;
556 struct range { int start, last; uint32 offset; } *ranges;
558 fseek(ttf,start,SEEK_SET);
559 rcnt = getushort(ttf);
560 ranges = galloc(rcnt*sizeof(struct range));
561 for ( i=0; i<rcnt; ++i ) {
562 ranges[i].start = getushort(ttf);
563 ranges[i].last = getushort(ttf);
564 ranges[i].offset = getlong(ttf);
566 for ( i=0; i<rcnt; ++i ) {
567 fseek(ttf,base+ranges[i].offset,SEEK_SET);
568 for ( j=ranges[i].start; j<=ranges[i].last; ++j )
569 loca[j] = getlong(ttf);
570 for ( j=ranges[i].start; j<=ranges[i].last; ++j ) {
571 Layer *ly;
572 sc = info->chars[j];
573 ly = &sc->layers[layer];
574 if ( loca[j]!=0 )
575 pfed_read_glyph_layer(ttf,info,ly,base+loca[j],type,version);
578 free(ranges); free(loca);
580 for ( i=0; i<info->glyph_cnt; ++i ) if ( info->chars[i]!=NULL )
581 info->chars[i]->ticked = false;
582 for ( i=0; i<info->glyph_cnt; ++i ) if ( info->chars[i]!=NULL )
583 pfed_redo_refs(info->chars[i],layer);
586 static void pfed_readotherlayers(FILE *ttf,struct ttfinfo *info,uint32 base) {
587 int i, l, lcnt, spiro_index, gid;
588 int version;
589 struct layer_info { int type, name_off, data_off, sf_layer; char *name; } *layers;
590 int non_spiro_cnt=0;
591 SplineChar *sc;
593 fseek(ttf,base,SEEK_SET);
594 version = getushort(ttf);
595 if ( version>1 )
596 return; /* Bad version number */
597 lcnt = getushort(ttf);
598 layers = galloc(lcnt*sizeof(struct layer_info));
599 for ( i=0; i<lcnt; ++i ) {
600 layers[i].type = getushort(ttf);
601 layers[i].name_off = getushort(ttf);
602 layers[i].data_off = getlong(ttf);
603 layers[i].sf_layer = -1;
605 spiro_index = -1;
606 non_spiro_cnt = 0;
607 for ( i=0; i<lcnt; ++i ) {
608 if ( layers[i].name_off==0 )
609 layers[i].name = copy("Unnamed");
610 else {
611 layers[i].name = pfed_read_utf8(ttf,base+layers[i].name_off);
612 if ( layers[i].type==1 && strcmp(layers[i].name,"Spiro")==0 )
613 spiro_index = i;
615 if ( layers[i].type==2 || layers[i].type==3 || layers[i].type==0x102 || layers[i].type==0x103 )
616 ++non_spiro_cnt;
618 if ( spiro_index==-1 ) {
619 for ( i=0; i<lcnt; ++i )
620 if ( layers[i].type==1 ) {
621 spiro_index=i;
622 break;
626 if ( non_spiro_cnt!=0 ) {
627 info->layer_cnt = non_spiro_cnt+1;
628 info->layers = gcalloc(info->layer_cnt+1,sizeof(LayerInfo));
629 info->layers[ly_back].background = true;
630 info->layers[ly_fore].order2 = info->to_order2;
631 info->layers[ly_fore].background = false;
632 l = i = 0;
633 if ( (layers[i].type&0xff)==1 )
634 ++i;
635 if ( layers[i].type&0x100 ) {
636 /* first layer output is foreground, so it can't replace the background layer */
637 ++info->layer_cnt;
638 l = 2;
639 info->layers[ly_back].order2 = info->to_order2;
641 for ( ; i<lcnt; ++i ) if ( (layers[i].type&0xff)==2 || (layers[i].type&0xff)==3 ) {
642 info->layers[l].name = layers[i].name;
643 layers[i].name = NULL;
644 layers[i].sf_layer = l;
645 info->layers[l].order2 = (layers[i].type&0xff)==2;
646 info->layers[l].background = (layers[i].type&0x100)?0:1;
647 if ( l==0 ) l=2; else ++l;
649 if ( info->layer_cnt!=2 ) {
650 for ( gid = 0; gid<info->glyph_cnt; ++gid ) if ((sc=info->chars[gid])!=NULL ) {
651 sc->layers = grealloc(sc->layers,info->layer_cnt*sizeof(Layer));
652 memset(sc->layers+2,0,(info->layer_cnt-2)*sizeof(Layer));
653 sc->layer_cnt = info->layer_cnt;
657 if ( spiro_index!=-1 )
658 pfed_read_layer(ttf,info,ly_fore,layers[spiro_index].type,base,base+layers[spiro_index].data_off,version);
659 for ( i=0; i<lcnt; ++i ) if ( layers[i].sf_layer!=-1 ) {
660 pfed_read_layer(ttf,info,layers[i].sf_layer,layers[i].type&0xff,
661 base,base+layers[i].data_off,version);
663 for ( i=0; i<lcnt; ++i )
664 free( layers[i].name );
665 free( layers );
668 void pfed_read(FILE *ttf,struct ttfinfo *info) {
669 int n,i;
670 struct tagoff { uint32 tag, offset; } tagoff[MAX_SUBTABLE_TYPES+30];
672 fseek(ttf,info->pfed_start,SEEK_SET);
674 if ( getlong(ttf)!=0x00010000 )
675 return;
676 n = getlong(ttf);
677 if ( n>=MAX_SUBTABLE_TYPES+30 )
678 n = MAX_SUBTABLE_TYPES+30;
679 for ( i=0; i<n; ++i ) {
680 tagoff[i].tag = getlong(ttf);
681 tagoff[i].offset = getlong(ttf);
683 for ( i=0; i<n; ++i ) switch ( tagoff[i].tag ) {
684 case fcmt_TAG: case flog_TAG:
685 pfed_readfontcomment(ttf,info,info->pfed_start+tagoff[i].offset, tagoff[i].tag);
686 break;
687 case cvtc_TAG:
688 pfed_readcvtcomments(ttf,info,info->pfed_start+tagoff[i].offset);
689 break;
690 case cmnt_TAG:
691 pfed_readglyphcomments(ttf,info,info->pfed_start+tagoff[i].offset);
692 break;
693 case colr_TAG:
694 pfed_readcolours(ttf,info,info->pfed_start+tagoff[i].offset);
695 break;
696 case GPOS_TAG:
697 pfed_readlookupnames(ttf,info,info->pfed_start+tagoff[i].offset,info->gpos_lookups);
698 break;
699 case GSUB_TAG:
700 pfed_readlookupnames(ttf,info,info->pfed_start+tagoff[i].offset,info->gsub_lookups);
701 break;
702 case layr_TAG:
703 pfed_readotherlayers(ttf,info,info->pfed_start+tagoff[i].offset);
704 break;
705 case guid_TAG:
706 pfed_readguidelines(ttf,info,info->pfed_start+tagoff[i].offset);
707 break;
708 default:
709 LogError( _("Unknown subtable '%c%c%c%c' in 'PfEd' table, ignored\n"),
710 tagoff[i].tag>>24, (tagoff[i].tag>>16)&0xff, (tagoff[i].tag>>8)&0xff, tagoff[i].tag&0xff );
711 break;
715 /* 'TeX ' table format is as follows... */
716 /* uint32 version number 0x00010000 */
717 /* uint32 subtable count */
718 /* struct { uint32 tab, offset } tag/offset for first subtable */
719 /* struct { uint32 tab, offset } tag/offset for second subtable */
720 /* ... */
722 /* 'TeX ' 'ftpm' font parameter subtable format */
723 /* short version number 0 */
724 /* parameter count */
725 /* array of { 4chr tag, value } */
727 /* 'TeX ' 'htdp' per-glyph height/depth subtable format */
728 /* short version number 0 */
729 /* short glyph-count */
730 /* array[glyph-count] of { int16 height,depth } */
732 /* 'TeX ' 'itlc' per-glyph italic correction subtable */
733 /* short version number 0 */
734 /* short glyph-count */
735 /* array[glyph-count] of int16 italic_correction */
737 /* !!!!!!!!!!! OBSOLETE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
738 /* 'TeX ' 'sbsp' per-glyph sub/super script positioning subtable */
739 /* short version number 0 */
740 /* short glyph-count */
741 /* array[glyph-count] of { int16 sub,super } */
743 #undef MAX_SUBTABLE_TYPES
744 #define MAX_SUBTABLE_TYPES 4
746 struct TeX_subtabs {
747 int next;
748 struct {
749 FILE *data;
750 uint32 tag;
751 uint32 offset;
752 } subtabs[MAX_SUBTABLE_TYPES];
755 static uint32 tex_text_params[] = {
756 TeX_Slant,
757 TeX_Space,
758 TeX_Stretch,
759 TeX_Shrink,
760 TeX_XHeight,
761 TeX_Quad,
762 TeX_ExtraSp,
765 static uint32 tex_math_params[] = {
766 TeX_Slant,
767 TeX_Space,
768 TeX_Stretch,
769 TeX_Shrink,
770 TeX_XHeight,
771 TeX_Quad,
772 TeX_MathSp,
773 TeX_Num1,
774 TeX_Num2,
775 TeX_Num3,
776 TeX_Denom1,
777 TeX_Denom2,
778 TeX_Sup1,
779 TeX_Sup2,
780 TeX_Sup3,
781 TeX_Sub1,
782 TeX_Sub2,
783 TeX_SupDrop,
784 TeX_SubDrop,
785 TeX_Delim1,
786 TeX_Delim2,
787 TeX_AxisHeight,
789 static uint32 tex_mathext_params[] = {
790 TeX_Slant,
791 TeX_Space,
792 TeX_Stretch,
793 TeX_Shrink,
794 TeX_XHeight,
795 TeX_Quad,
796 TeX_MathSp,
797 TeX_DefRuleThick,
798 TeX_BigOpSpace1,
799 TeX_BigOpSpace2,
800 TeX_BigOpSpace3,
801 TeX_BigOpSpace4,
802 TeX_BigOpSpace5,
806 /* ************************* The 'TeX ' table ************************* */
807 /* ************************* Input ************************* */
809 static void TeX_readFontParams(FILE *ttf,struct ttfinfo *info,uint32 base) {
810 int i,pcnt;
811 static uint32 *alltags[] = { tex_text_params, tex_math_params, tex_mathext_params };
812 int j,k;
813 uint32 tag;
814 int32 val;
816 fseek(ttf,base,SEEK_SET);
817 if ( getushort(ttf)!=0 ) /* Don't know how to read this version of the subtable */
818 return;
819 pcnt = getushort(ttf);
820 if ( pcnt==22 ) info->texdata.type = tex_math;
821 else if ( pcnt==13 ) info->texdata.type = tex_mathext;
822 else if ( pcnt>=7 ) info->texdata.type = tex_text;
823 for ( i=0; i<pcnt; ++i ) {
824 tag = getlong(ttf);
825 val = getlong(ttf);
826 for ( j=0; j<3; ++j ) {
827 for ( k=0; alltags[j][k]!=0; ++k )
828 if ( alltags[j][k]==tag )
829 break;
830 if ( alltags[j][k]==tag )
831 break;
833 if ( j<3 )
834 info->texdata.params[k] = val;
838 static void TeX_readHeightDepth(FILE *ttf,struct ttfinfo *info,uint32 base) {
839 int i,gcnt;
841 fseek(ttf,base,SEEK_SET);
842 if ( getushort(ttf)!=0 ) /* Don't know how to read this version of the subtable */
843 return;
844 gcnt = getushort(ttf);
845 for ( i=0; i<gcnt && i<info->glyph_cnt; ++i ) {
846 int h, d;
847 h = getushort(ttf);
848 d = getushort(ttf);
849 if ( info->chars[i]!=NULL ) {
850 info->chars[i]->tex_height = h;
851 info->chars[i]->tex_depth = d;
856 static void TeX_readItalicCorr(FILE *ttf,struct ttfinfo *info,uint32 base) {
857 int i,gcnt;
859 fseek(ttf,base,SEEK_SET);
860 if ( getushort(ttf)!=0 ) /* Don't know how to read this version of the subtable */
861 return;
862 gcnt = getushort(ttf);
863 for ( i=0; i<gcnt && i<info->glyph_cnt; ++i ) {
864 int ital;
865 ital = getushort(ttf);
866 if ( info->chars[i]!=NULL ) {
867 info->chars[i]->italic_correction = ital;
872 void tex_read(FILE *ttf,struct ttfinfo *info) {
873 int n,i;
874 struct tagoff { uint32 tag, offset; } tagoff[MAX_SUBTABLE_TYPES+30];
876 fseek(ttf,info->tex_start,SEEK_SET);
878 if ( getlong(ttf)!=0x00010000 )
879 return;
880 n = getlong(ttf);
881 if ( n>=MAX_SUBTABLE_TYPES+30 )
882 n = MAX_SUBTABLE_TYPES+30;
883 for ( i=0; i<n; ++i ) {
884 tagoff[i].tag = getlong(ttf);
885 tagoff[i].offset = getlong(ttf);
887 for ( i=0; i<n; ++i ) switch ( tagoff[i].tag ) {
888 case CHR('f','t','p','m'):
889 TeX_readFontParams(ttf,info,info->tex_start+tagoff[i].offset);
890 break;
891 case CHR('h','t','d','p'):
892 TeX_readHeightDepth(ttf,info,info->tex_start+tagoff[i].offset);
893 break;
894 case CHR('i','t','l','c'):
895 TeX_readItalicCorr(ttf,info,info->tex_start+tagoff[i].offset);
896 break;
897 default:
898 LogError( _("Unknown subtable '%c%c%c%c' in 'TeX ' table, ignored\n"),
899 tagoff[i].tag>>24, (tagoff[i].tag>>16)&0xff, (tagoff[i].tag>>8)&0xff, tagoff[i].tag&0xff );
900 break;