1 /* Copyright (C) 2000-2008 by George Williams */
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.
32 #include <gimage.h> /* For COLOR_DEFAULT */
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
,
56 char *start
, *pt
, *end
;
59 fseek(ttf
,base
,SEEK_SET
);
60 use_utf8
= getushort(ttf
);
61 if ( use_utf8
!=0 && use_utf8
!=1 )
62 return; /* Bad version number */
64 start
= pt
= galloc(len
+1);
72 *pt
++ = getushort(ttf
);
76 pt
= latin1_2_utf8_copy(info
->fontcomments
);
81 info
->fontlog
= start
;
83 info
->fontcomments
= start
;
86 static char *pfed_read_utf8(FILE *ttf
, uint32 start
) {
90 fseek( ttf
, start
, SEEK_SET
);
92 while ( (ch
=getc(ttf
))!='\0' && ch
!=EOF
)
94 fseek( ttf
, start
, SEEK_SET
);
95 str
= pt
= galloc(len
+1);
96 while ( (ch
=getc(ttf
))!='\0' && ch
!=EOF
)
102 static char *pfed_read_ucs2_len(FILE *ttf
,uint32 offset
,int len
) {
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);
120 pt
= utf8_idpb(pt
,uch
);
124 pt
= utf8_idpb(pt
,uch
);
127 return( grealloc(str
,pt
-str
) );
130 static char *pfed_read_utf8_len(FILE *ttf
,uint32 offset
,int len
) {
137 pt
= str
= galloc(len
+1);
138 fseek(ttf
,offset
,SEEK_SET
);
139 for ( i
=0; i
<len
; ++i
)
145 static void pfed_readcvtcomments(FILE *ttf
,struct ttfinfo
*info
,uint32 base
) {
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
) {
160 info
->cvt_names
[i
] = NULL
;
162 info
->cvt_names
[i
] = pfed_read_utf8(ttf
,base
+offsets
[i
]);
167 static void pfed_readglyphcomments(FILE *ttf
,struct ttfinfo
*info
,uint32 base
) {
169 struct grange
{ int start
, end
; uint32 offset
; } *grange
;
173 fseek(ttf
,base
,SEEK_SET
);
174 use_utf8
= getushort(ttf
);
175 if ( use_utf8
!=0 && use_utf8
!=1 )
176 return; /* Bad version number */
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
);
194 info
->chars
[j
]->comment
= pfed_read_utf8_len(ttf
,base
+offset
,next
-offset
);
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
);
205 static void pfed_readcolours(FILE *ttf
,struct ttfinfo
*info
,uint32 base
) {
206 int n
, i
, j
, start
, end
;
209 fseek(ttf
,base
,SEEK_SET
);
210 if ( getushort(ttf
)!=0 )
211 return; /* Bad version number */
213 for ( i
=0; i
<n
; ++i
) {
214 start
= getushort(ttf
);
215 end
= getushort(ttf
);
217 if ( start
>end
|| end
>info
->glyph_cnt
)
218 LogError( _("Bad glyph range specified in colour subtable of PfEd table\n") );
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
,
229 struct lookup_subtable
*sub
;
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 */
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
);
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");
265 fseek(ttf
,base
+ss
[j
].subs_off
,SEEK_SET
);
267 as
= galloc(a
*sizeof(struct lstruct
));
268 for ( k
=0; k
<a
; ++k
) {
269 as
[k
].name_off
= getushort(ttf
);
272 for ( ac
=info
->ahead
; ac
!=NULL
; ac
=ac
->next
) {
273 if ( ac
->subtable
==sub
) {
274 if ( as
[k
].name_off
!=0 ) {
276 ac
->name
= pfed_read_utf8(ttf
,base
+as
[k
].name_off
);
285 /* I guess it's ok for some subtables to be unnamed, so no check for sub!=NULL */
287 LogError("Whoops, more names than subtables of lookup %s\n", otl
->lookup_name
);
291 /* I guess it's ok for some lookups to be unnamed, so no check for otf!=NULL */
293 LogError("Whoops, more names than lookups\n" );
297 static float pfed_get_coord(FILE *ttf
,int mod
) {
299 return( (float) (signed char) getc(ttf
) );
301 return( (float) (short) getushort(ttf
));
303 return( getlong(ttf
)/256.0 );
305 LogError( "Bad data type in contour verb in 'PfEd'\n");
310 static void pfed_read_normal_contour(FILE *ttf
,SplineSet
*ss
,
311 uint32 base
, int type
) {
312 SplinePoint
*sp
, *current
;
314 float offx
, offy
, offx1
= 0, offy1
= 0, offx2
, offy2
;
315 int was_implicit
=false;
317 fseek(ttf
,base
,SEEK_SET
);
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);
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
);
330 v
= COM_VERB(verb
); m
= COM_MOD(verb
);
332 LogError("Bad data modifier in contour command in 'PfEd'\n" );
335 if ( verb
==V_Close
|| verb
==V_End
)
337 else if ( v
>=V_LineTo
&& v
<=V_VLineTo
) {
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;
405 LogError("Whoops, unexpected verb in contour %d.%d\n", v
, m
);
408 SplineMake(current
,sp
,type
==2);
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
);
423 SplineMake(current
,ss
->first
,type
==2);
424 ss
->last
= ss
->first
;
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
;
436 struct contours
{ int data_off
, name_off
; SplineSet
*ss
; } *contours
;
440 fseek(ttf
,base
,SEEK_SET
);
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
);
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
];
459 cur
->unicode_enc
= cur
->sc
->unicodeenc
;
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
));
472 ly
->splines
= contours
[i
].ss
;
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
);
483 static void pfed_readguidelines(FILE *ttf
,struct ttfinfo
*info
,uint32 base
) {
486 SplinePoint
*sp
, *nsp
;
489 fseek(ttf
,base
,SEEK_SET
);
490 version
= getushort(ttf
);
492 return; /* Bad version number */
495 (void) getushort(ttf
);
496 off
= getushort(ttf
);
499 pfed_read_glyph_layer(ttf
,info
,&info
->guidelines
,base
+off
,info
->to_order2
?2:3,version
);
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
);
539 static void pfed_redo_refs(SplineChar
*sc
,int layer
) {
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
));
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
) {
573 ly
= &sc
->layers
[layer
];
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
;
589 struct layer_info
{ int type
, name_off
, data_off
, sf_layer
; char *name
; } *layers
;
593 fseek(ttf
,base
,SEEK_SET
);
594 version
= getushort(ttf
);
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;
607 for ( i
=0; i
<lcnt
; ++i
) {
608 if ( layers
[i
].name_off
==0 )
609 layers
[i
].name
= copy("Unnamed");
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 )
615 if ( layers
[i
].type
==2 || layers
[i
].type
==3 || layers
[i
].type
==0x102 || layers
[i
].type
==0x103 )
618 if ( spiro_index
==-1 ) {
619 for ( i
=0; i
<lcnt
; ++i
)
620 if ( layers
[i
].type
==1 ) {
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;
633 if ( (layers
[i
].type
&0xff)==1 )
635 if ( layers
[i
].type
&0x100 ) {
636 /* first layer output is foreground, so it can't replace the background layer */
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
);
668 void pfed_read(FILE *ttf
,struct ttfinfo
*info
) {
670 struct tagoff
{ uint32 tag
, offset
; } tagoff
[MAX_SUBTABLE_TYPES
+30];
672 fseek(ttf
,info
->pfed_start
,SEEK_SET
);
674 if ( getlong(ttf
)!=0x00010000 )
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
);
688 pfed_readcvtcomments(ttf
,info
,info
->pfed_start
+tagoff
[i
].offset
);
691 pfed_readglyphcomments(ttf
,info
,info
->pfed_start
+tagoff
[i
].offset
);
694 pfed_readcolours(ttf
,info
,info
->pfed_start
+tagoff
[i
].offset
);
697 pfed_readlookupnames(ttf
,info
,info
->pfed_start
+tagoff
[i
].offset
,info
->gpos_lookups
);
700 pfed_readlookupnames(ttf
,info
,info
->pfed_start
+tagoff
[i
].offset
,info
->gsub_lookups
);
703 pfed_readotherlayers(ttf
,info
,info
->pfed_start
+tagoff
[i
].offset
);
706 pfed_readguidelines(ttf
,info
,info
->pfed_start
+tagoff
[i
].offset
);
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 );
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 */
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
752 } subtabs
[MAX_SUBTABLE_TYPES
];
755 static uint32 tex_text_params
[] = {
765 static uint32 tex_math_params
[] = {
789 static uint32 tex_mathext_params
[] = {
806 /* ************************* The 'TeX ' table ************************* */
807 /* ************************* Input ************************* */
809 static void TeX_readFontParams(FILE *ttf
,struct ttfinfo
*info
,uint32 base
) {
811 static uint32
*alltags
[] = { tex_text_params
, tex_math_params
, tex_mathext_params
};
816 fseek(ttf
,base
,SEEK_SET
);
817 if ( getushort(ttf
)!=0 ) /* Don't know how to read this version of the subtable */
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
) {
826 for ( j
=0; j
<3; ++j
) {
827 for ( k
=0; alltags
[j
][k
]!=0; ++k
)
828 if ( alltags
[j
][k
]==tag
)
830 if ( alltags
[j
][k
]==tag
)
834 info
->texdata
.params
[k
] = val
;
838 static void TeX_readHeightDepth(FILE *ttf
,struct ttfinfo
*info
,uint32 base
) {
841 fseek(ttf
,base
,SEEK_SET
);
842 if ( getushort(ttf
)!=0 ) /* Don't know how to read this version of the subtable */
844 gcnt
= getushort(ttf
);
845 for ( i
=0; i
<gcnt
&& i
<info
->glyph_cnt
; ++i
) {
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
) {
859 fseek(ttf
,base
,SEEK_SET
);
860 if ( getushort(ttf
)!=0 ) /* Don't know how to read this version of the subtable */
862 gcnt
= getushort(ttf
);
863 for ( i
=0; i
<gcnt
&& i
<info
->glyph_cnt
; ++i
) {
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
) {
874 struct tagoff
{ uint32 tag
, offset
; } tagoff
[MAX_SUBTABLE_TYPES
+30];
876 fseek(ttf
,info
->tex_start
,SEEK_SET
);
878 if ( getlong(ttf
)!=0x00010000 )
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
);
891 case CHR('h','t','d','p'):
892 TeX_readHeightDepth(ttf
,info
,info
->tex_start
+tagoff
[i
].offset
);
894 case CHR('i','t','l','c'):
895 TeX_readItalicCorr(ttf
,info
,info
->tex_start
+tagoff
[i
].offset
);
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 );