1
/* Copyright (C) 2000-2007 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.
27
#include "pfaeditui.h"
32
#include <sys/types.h>
40
# include </Developer/Headers/FlatCarbon/Files.h>
49
/* no need for iconv here, since PS is 8-bit legacy */
50
#define Isspace(a) ((a)==' '|| ((a) >= '\t' && (a) <= '\r'))
51
#define Isdigit(a) ((a)>='0' && (a)<='9')
52
#define Isalpha(a) (((a)>='a' && (a)<='z') || ((a)>='A' && (a)<='Z'))
53
#define Islower(a) ((a)>='a' && (a)<='z')
54
#define Isupper(a) ((a)>='A' && (a)<='Z')
55
#define Isalnum(a) (Isalpha(a)||Isdigit(a))
56
#define Ishexdigit(a) (((a)>='0' && (a)<='9')||((a)>='a' && (a)<='f')||((a)>='A' && (a)<='F'))
57
static int Tolower (int c) {
64
#define Islower islower
65
#define Tolower tolower
66
#define Isspace isspace
67
#define Isdigit isdigit
68
#define Isalpha isalpha
69
#define Isalnum isalnum
70
#define Ishexdigit ishexdigit
76
const int mac_dpi = 72;
77
/* I had always assumed that the mac still believed in 72dpi screens, but I */
78
/* see that in geneva under OS/9, the pointsize does not match the pixel */
79
/* size of the font. But the dpi is not constant (and the differences */
80
/* excede those supplied by rounding errors) varying between 96 and 84dpi */
82
/* A Mac Resource fork */
83
/* http://developer.apple.com/techpubs/mac/MoreToolbox/MoreToolbox-9.html */
84
/* begins with a 16 byte header containing: */
85
/* resource start offset */
86
/* map start offset */
89
/* then 256-16 bytes of zeros */
90
/* the resource section consists of (many) */
91
/* 4 byte length count */
93
/* the map section contains */
94
/* A copy of the 16 byte header */
95
/* a 4 byte mac internal value (I hope) */
96
/* another 4 bytes of mac internal values (I hope) */
97
/* a 2 byte offset from the start of the map section to the list of resource types */
98
/* a 2 byte offset from the start of the map section to the list of resource names */
99
/* The resource type list consists of */
100
/* a 2 byte count of the number of resource types (-1) */
101
/* (many copies of) */
102
/* a 4 byte resource type ('FOND' for example) */
103
/* a 2 byte count of the number of resources of this type (-1) */
104
/* a 2 byte offset from the type list start to the resource table */
105
/* a resource table looks like */
106
/* a 2 byte offset from the resource name table to a pascal */
107
/* string containing this resource's name (or 0xffff for none) */
108
/* 1 byte of resource flags */
109
/* 3 bytes of offset from the resource section to the length & */
110
/* data of this instance of the resource type */
112
/* The resource name section consists of */
113
/* a bunch of pascal strings (ie. preceded by a length byte) */
115
/* The POST resource isn't noticeably documented, it's pretty much a */
116
/* straight copy of the pfb file cut up into 0x800 byte chunks. */
117
/* (each section of the pfb file has it's own set of chunks, the last may be smaller than 0x800) */
118
/* The NFNT resource http://developer.apple.com/techpubs/mac/Text/Text-250.html */
119
/* The FOND resource http://developer.apple.com/techpubs/mac/Text/Text-269.html */
120
/* The sfnt resource is basically a copy of the ttf file */
122
/* A MacBinary file */
123
/* http://www.lazerware.com/formats/macbinary.html */
124
/* begins with a 128 byte header */
125
/* (which specifies lengths for data/resource forks) */
126
/* (and contains mac type/creator data) */
127
/* (and other stuff) */
128
/* (and finally a crc checksum) */
129
/* is followed by the data section (padded to a mult of 128 bytes) */
130
/* is followed by the resource section (padded to a mult of 128 bytes) */
132
/* Crc code taken from: */
133
/* http://www.ctan.org/tex-archive/tools/macutils/crc/ */
134
/* MacBinary files use the same CRC that binhex does (in the MacBinary header) */
135
extern unsigned long binhex_crc(unsigned char *buffer,int size);
137
/* ******************************** Creation ******************************** */
140
static uint16 HashToId(char *fontname,SplineFont *sf,EncMap *map) {
141
int low = 128, high = 0x3fff;
142
/* A FOND ID should be between these two numbers for roman script (I think) */
147
/* Figure out what language we've got */
148
/* I'm not bothering with all of the apple scripts, and I don't know */
149
/* what to do about cjk fonts */
150
if ( sf->cidmaster!=NULL || sf->subfontcnt!=0 ) {
151
if ( sf->cidmaster != NULL ) sf = sf->cidmaster;
152
if ( sf->ordering != NULL ) {
153
if ( strstrmatch(sf->ordering,"Japan")!=NULL ) {
154
low = 0x4000; high = 0x41ff;
155
} else if ( strstrmatch(sf->ordering,"Korea")!=NULL ) {
156
low = 0x4400; high = 0x45ff;
157
} else if ( strstrmatch(sf->ordering,"CNS")!=NULL ) {
158
low = 0x4200; high = 0x43ff;
159
} else if ( strstrmatch(sf->ordering,"GB")!=NULL ) {
160
low = 0x7200; high = 0x73ff;
163
} else if ( map->enc->is_tradchinese ) {
164
low = 0x4200; high = 0x43ff;
165
} else if ( map->enc->is_japanese ) {
166
low = 0x4000; high = 0x41ff;
167
} else if ( map->enc->is_korean ) {
168
low = 0x4400; high = 0x45ff;
169
} else if ( map->enc->is_simplechinese ) {
170
low = 0x7200; high = 0x73ff;
171
} else for ( i=0; i<map->enccount && i<256; ++i ) if ( (gid=map->map[i])!=-1 && (sc = sf->glyphs[gid])!=NULL ) {
172
/* Japanese between 0x4000 and 0x41ff */
173
/* Trad Chinese 0x4200 and 0x43ff */
174
/* Simp Chinese 0x7200 and 0x73ff */
175
/* Korean 0x4400 and 0x45ff */
176
if (( sc->unicodeenc>=0x0600 && sc->unicodeenc<0x0700 ) ||
177
( sc->unicodeenc>=0xFB50 && sc->unicodeenc<0xfe00 )) {
179
low = 0x4600; high = 0x47ff;
181
} else if (( sc->unicodeenc>=0x0590 && sc->unicodeenc<0x0600 ) ||
182
( sc->unicodeenc>=0xFB1d && sc->unicodeenc<0xFB50 )) {
184
low = 0x4800; high = 0x49ff;
186
} else if ((( sc->unicodeenc>=0x0370 && sc->unicodeenc<0x0400 ) ||
187
( sc->unicodeenc>=0x1f00 && sc->unicodeenc<0x2000 )) &&
188
sc->unicodeenc!=0x3c0 ) { /* In mac encoding */
190
low = 0x4a00; high = 0x4bff;
192
} else if ( sc->unicodeenc>=0x0400 && sc->unicodeenc<0x0530 ) {
194
low = 0x4c00; high = 0x4dff;
196
/* hebrew/arabic symbols 4e00-4fff */
197
} else if ( sc->unicodeenc>=0x0900 && sc->unicodeenc<0x0980 ) {
199
low = 0x5000; high = 0x51ff;
201
} else if ( sc->unicodeenc>=0x0980 && sc->unicodeenc<0x0a00 ) {
202
/* bengali: script=13 */
203
low = 0x5800; high = 0x59ff;
207
while ( *fontname ) {
208
int temp = (hash>>28)&0xf;
209
hash = (hash<<4) | temp;
210
hash ^= *fontname++-' ';
212
hash %= (high-low+1);
217
static int IsMacMonospaced(SplineFont *sf,EncMap *map) {
218
/* Only look at first 256 */
220
double width = 0x80000000;
222
for ( i=0; i<256 && i<map->enccount; ++i ) {
223
int gid = map->map[i];
224
if ( gid!=-1 && SCWorthOutputting(sf->glyphs[gid]) ) {
225
if ( width == 0x80000000 )
226
width = sf->glyphs[gid]->width;
227
else if ( sf->glyphs[gid]->width!=width )
234
SplineChar *SFFindExistingCharMac(SplineFont *sf,EncMap *map,int unienc) {
237
for ( i=0; i<map->enccount && i<256; ++i )
238
if ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL && sf->glyphs[gid]->unicodeenc==unienc )
239
return( sf->glyphs[gid] );
243
static double SFMacWidthMax(SplineFont *sf, EncMap *map) {
244
/* Only look at first 256 */
248
for ( i=0; i<256 && i<map->enccount; ++i ) {
249
if ( (gid=map->map[i])!=-1 && SCWorthOutputting(sf->glyphs[gid]) ) {
250
if ( sf->glyphs[gid]->width>width )
251
width = sf->glyphs[gid]->width;
254
if ( width<0 ) /* No chars, or widths the mac doesn't support */
260
static int SFMacAnyKerns(SplineFont *sf, EncMap *map) {
261
/* Only look at first 256 */
265
for ( i=0; i<256 && i<map->enccount; ++i ) {
266
if ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL ) {
267
for ( kp=sf->glyphs[gid]->kerns; kp!=NULL; kp=kp->next )
268
if ( map->backmap[kp->sc->orig_pos]<256 )
284
struct resourcetype {
286
struct resource *res;
290
struct macbinaryheader {
292
char *binfilename; /* if macfilename is null and this is set we will figure out macfilename by removing .bin */
297
static struct resource *PSToResources(FILE *res,FILE *pfbfile) {
298
/* split the font up into as many small resources as we need and return */
299
/* an array pointing to the start of each */
302
struct resource *resstarts;
305
fstat(fileno(pfbfile),&statb);
306
cnt = 3*(statb.st_size+0x800)/(0x800-2)+1; /* should be (usually) a vast over estimate */
307
resstarts = gcalloc(cnt+1,sizeof(struct resource));
311
if ( getc(pfbfile)!=0x80 ) {
312
IError("We made a pfb file, but didn't get one. Hunh?" );
315
type = getc(pfbfile);
317
/* 501 appears to be magic */
318
/* postscript resources seem to have flags of 0 */
319
resstarts[cnt].id = 501+cnt;
320
resstarts[cnt++].pos = ftell(res);
321
putlong(res,2); /* length */
322
putc(5,res); /* eof mark */
327
len |= (getc(pfbfile))<<8;
328
len |= (getc(pfbfile))<<16;
329
len |= (getc(pfbfile))<<24;
335
resstarts[cnt].id = 501+cnt;
336
resstarts[cnt++].pos = ftell(res);
337
putlong(res,ilen+2); /* length */
338
putc(type,res); /* section type mark */
340
for ( i=0; i<ilen; ++i )
341
putc(getc(pfbfile),res);
344
resstarts[cnt].pos = 0;
348
static uint32 TTFToResource(FILE *res,FILE *ttffile) {
349
/* A truetype font just gets dropped into a resource */
354
fstat(fileno(ttffile),&statb);
355
resstart = ftell(res);
357
putlong(res,statb.st_size);
358
while ( (ch=getc(ttffile))!=EOF )
363
static int BDFCCopyBitmaps(uint8 **rows,int offset,BDFChar *bdfc, BDFFont *bdf) {
364
int i, r, y, ipos, j, c;
366
y = bdf->ascent-1; r = i = 0;
367
if ( bdfc->ymax > bdf->ascent-1 )
368
i = bdfc->ymax-(bdf->ascent-1);
369
else if ( bdfc->ymax<bdf->ascent-1 ) {
370
r = bdf->ascent-1-bdfc->ymax;
373
for ( ; y>=bdfc->ymin && y>=-bdf->descent; --y, ++i ) {
374
/* Mac characters may not extend above the ascent or below the descent */
375
/* but bdf chars can, so if a bdf char does, just ignore that part */
376
ipos = i*bdfc->bytes_per_line;
377
for ( j=0,c=offset; j<=bdfc->xmax-bdfc->xmin; ++j, ++c ) {
378
if ( bdfc->bitmap[ipos+(j>>3)] & (1<<(7-(j&7))) )
379
rows[r][c>>3] |= (1<<(7-(c&7)));
383
return( offset + bdfc->xmax-bdfc->xmin+1 );
386
static uint32 BDFToNFNT(FILE *res, BDFFont *bdf, EncMap *map) {
387
short widths[258], lbearings[258], locs[258]/*, idealwidths[256]*/;
388
uint8 **rows = galloc(bdf->pixelsize*sizeof(uint8 *));
389
int i, k, width, kernMax=1, descentMax=bdf->descent-1, rectMax=1, widMax=3;
390
uint32 rlenpos = ftell(res), end, owloc, owpos;
393
for ( i=width=0; i<256 && i<map->enccount; ++i ) {
394
if ( (gid = map->map[i])!=-1 && gid<bdf->glyphcnt && bdf->glyphs[gid]!=NULL ) {
395
width += bdf->glyphs[gid]->xmax+1-bdf->glyphs[gid]->xmin;
396
if ( bdf->glyphs[gid]->width>widMax )
397
widMax = bdf->glyphs[gid]->width;
398
if ( bdf->glyphs[gid]->xmax+1-bdf->glyphs[gid]->xmin>rectMax )
399
rectMax = bdf->glyphs[gid]->xmax+1-bdf->glyphs[gid]->xmin;
400
if ( bdf->glyphs[gid]->xmin<kernMax )
401
kernMax = bdf->glyphs[gid]->xmin;
402
if ( bdf->glyphs[gid]->ymin<-descentMax )
403
descentMax = -bdf->glyphs[gid]->ymin;
406
if ( descentMax>bdf->descent ) descentMax = bdf->descent;
407
++width; /* For the "undefined character */
408
for ( k=0; k<bdf->pixelsize; ++k )
409
rows[k] = gcalloc((width+7)/8 + 4 , sizeof(uint8));
410
for ( i=width=0; i<256 ; ++i ) {
412
if ( i>=map->enccount || (gid=map->map[i])==-1 || gid>=bdf->glyphcnt || bdf->glyphs[gid]==NULL ||
413
!SCWorthOutputting(bdf->glyphs[gid]->sc) ) {
416
/*idealwidths[i] = 1<<12; */ /* 1 em */
418
lbearings[i] = bdf->glyphs[gid]->xmin-kernMax;
419
widths[i] = bdf->glyphs[gid]->width<0?0:
420
bdf->glyphs[gid]->width>=256?255:
421
bdf->glyphs[gid]->width;
422
/*idealwidths[i] = bdf->glyphs[gid]->sc->width*(1<<12)/(bdf->sf->ascent+bdf->sf->descent);*/
423
width = BDFCCopyBitmaps(rows,width,bdf->glyphs[gid],bdf);
426
/* Now for the "undefined character", just a simple vertical bar */
430
/*idealwidths[i++] = (3<<12)/bdf->pixelsize;*/
431
for ( k = 1; k<bdf->pixelsize-1; ++k )
432
rows[k][width>>3] |= (1<<(7-(width&7)));
433
/* And one more entry to give a size to the last character */
435
lbearings[i] = widths[i] = 0xff;
436
/*idealwidths[i] = 0;*/
439
lbearings[0] = widths[0] = 0;
440
lbearings['\r'] = widths['\r'] = 0;
441
lbearings['\t'] = 0; widths['\t'] = 6;
443
/* We've finished the bitmap conversion, now save it... */
444
putlong(res,0); /* Length, to be filled in later */
445
putshort(res,IsMacMonospaced(bdf->sf,map)?0xb000:0x9000); /* fontType */
448
putshort(res,widMax);
449
putshort(res,kernMax);
450
putshort(res,-descentMax);
451
putshort(res,rectMax);
452
putshort(res,bdf->pixelsize);
455
putshort(res,bdf->ascent);
456
putshort(res,bdf->descent);
457
putshort(res,(short) (bdf->sf->pfminfo.linegap*bdf->pixelsize/(bdf->sf->ascent+bdf->sf->descent)) );
458
putshort(res,(width+15)>>4);
460
for ( k=0; k<bdf->pixelsize; ++k ) {
461
for ( i=0; i<((width+15)>>4) ; ++i ) {
462
putc(rows[k][2*i],res);
463
putc(rows[k][2*i+1],res);
466
for ( i=0; i<258; ++i )
467
putshort(res,locs[i]);
468
owloc = ftell(res); /* valgrind reports an error here (but not above). god knows why */
469
for ( i=0; i<258; ++i ) {
470
putc(lbearings[i],res);
474
fseek(res,rlenpos,SEEK_SET);
475
putlong(res,end-rlenpos-4);
476
fseek(res,owpos,SEEK_SET);
477
putshort(res,(owloc-owpos)/2);
478
fseek(res,0,SEEK_END);
480
for ( k=0; k<bdf->pixelsize; ++k )
487
static uint32 DummyNFNT(FILE *res, BDFFont *bdf, EncMap *map) {
488
/* This produces a stub NFNT which appears when the real data lives inside */
489
/* an sfnt (truetype) resource. We still need to produce an NFNT to tell */
490
/* the system that the pointsize is available. This NFNT has almost nothing */
491
/* in it, just the initial header, no metrics, no bitmaps */
492
int i, width, kernMax=1, descentMax=bdf->descent-1, rectMax=1, widMax=3;
493
uint32 rlenpos = ftell(res);
496
for ( i=width=0; i<256 && i<map->enccount; ++i ) if ( (gid=map->map[i])!=-1 && gid<bdf->glyphcnt && bdf->glyphs[gid]!=NULL ) {
497
width += bdf->glyphs[gid]->xmax+1-bdf->glyphs[gid]->xmin;
498
if ( bdf->glyphs[gid]->width>widMax )
499
widMax = bdf->glyphs[gid]->width;
500
if ( bdf->glyphs[gid]->xmax+1-bdf->glyphs[gid]->xmin>rectMax )
501
rectMax = bdf->glyphs[gid]->xmax+1-bdf->glyphs[gid]->xmin;
502
if ( bdf->glyphs[gid]->xmin<kernMax )
503
kernMax = bdf->glyphs[gid]->xmin;
504
if ( bdf->glyphs[gid]->ymin<-descentMax )
505
descentMax = -bdf->glyphs[gid]->ymin;
507
if ( descentMax>bdf->descent ) descentMax = bdf->descent;
509
putlong(res,26); /* Length */
510
putshort(res,SFOneWidth(bdf->sf)!=-1?0xf000:0xd000); /* fontType */
513
putshort(res,widMax);
514
putshort(res,kernMax);
515
putshort(res,-descentMax);
516
putshort(res,rectMax);
517
putshort(res,bdf->pixelsize);
519
putshort(res,bdf->ascent);
520
putshort(res,bdf->descent);
521
putshort(res,(short) (bdf->sf->pfminfo.linegap*bdf->pixelsize/(bdf->sf->ascent+bdf->sf->descent)) );
527
static struct resource *SFToNFNTs(FILE *res, SplineFont *sf, int32 *sizes,
529
int i, baseresid = HashToId(sf->fontname,sf,map);
530
struct resource *resstarts;
533
if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
535
for ( i=0; sizes[i]!=0; ++i );
536
resstarts = gcalloc(i+1,sizeof(struct resource));
538
for ( i=0; sizes[i]!=0; ++i ) {
539
if ( (sizes[i]>>16)!=1 )
541
if ( (sizes[i]&0xffff)>=256 )
543
for ( bdf=sf->bitmaps; bdf!=NULL && (bdf->pixelsize!=(sizes[i]&0xffff) || BDFDepth(bdf)!=1); bdf=bdf->next );
546
resstarts[i].id = baseresid+bdf->pixelsize;
547
resstarts[i].pos = BDFToNFNT(res,bdf,map);
548
/* NFNTs seem to have resource flags of 0 */
553
static struct resource *SFsToNFNTs(FILE *res, struct sflist *sfs,int baseresid) {
555
struct resource *resstarts;
561
for ( sfi=sfs; sfi!=NULL; sfi=sfi->next ) {
562
if ( sfi->sizes!=NULL ) {
563
for ( i=0; sfi->sizes[i]!=0; ++i );
565
sfi->ids = gcalloc(i+1,sizeof(int));
566
sfi->bdfs = gcalloc(i+1,sizeof(BDFFont *));
570
resstarts = gcalloc(cnt+1,sizeof(struct resource));
573
for ( sfi=sfs; sfi!=NULL; sfi=sfi->next ) {
575
if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
577
if ( sfi->sizes ) for ( i=0; sfi->sizes[i]!=0; ++i ) {
578
if ( (sfi->sizes[i]>>16)!=1 )
580
if ( (sfi->sizes[i]&0xffff)>=256 )
582
for ( bdf=sf->bitmaps; bdf!=NULL && (bdf->pixelsize!=(sfi->sizes[i]&0xffff) || BDFDepth(bdf)!=1); bdf=bdf->next );
585
sfi->ids[j] = baseresid;
587
resstarts[cnt+j].id = baseresid++;
588
resstarts[cnt+j++].pos = BDFToNFNT(res,bdf,sfi->map);
589
/* NFNTs seem to have resource flags of 0 */
596
static struct resource *BuildDummyNFNTlist(FILE *res, SplineFont *sf,
597
int32 *sizes, int baseresid, EncMap *map) {
599
struct resource *resstarts;
602
if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
604
for ( i=0; sizes[i]!=0; ++i );
605
resstarts = gcalloc(i+1,sizeof(struct resource));
607
for ( i=0; sizes[i]!=0; ++i ) {
608
if ( (sizes[i]>>16)!=1 )
610
if ( (sizes[i]&0xffff)>=256 )
612
for ( bdf=sf->bitmaps; bdf!=NULL && (bdf->pixelsize!=(sizes[i]&0xffff) || BDFDepth(bdf)!=1); bdf=bdf->next );
615
resstarts[i].id = baseresid+(sizes[i]&0xffff);
616
resstarts[i].pos = DummyNFNT(res,bdf,map);
617
/* NFNTs seem to have resource flags of 0 */
622
static struct resource *BuildDummyNFNTfamilyList(FILE *res, struct sflist *sfs,
625
struct resource *resstarts;
631
for ( sfi=sfs; sfi!=NULL; sfi=sfi->next ) {
632
if ( sfi->sizes!=NULL ) {
633
for ( i=0; sfi->sizes[i]!=0; ++i );
635
sfi->ids = gcalloc(i+1,sizeof(int));
636
sfi->bdfs = gcalloc(i+1,sizeof(BDFFont *));
640
resstarts = gcalloc(cnt+1,sizeof(struct resource));
643
for ( sfi=sfs; sfi!=NULL; sfi=sfi->next ) {
646
if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
647
if ( sfi->sizes ) for ( i=0; sfi->sizes[i]!=0; ++i ) {
648
if ( (sfi->sizes[i]>>16)!=1 )
650
for ( bdf=sf->bitmaps; bdf!=NULL && (bdf->pixelsize!=(sfi->sizes[i]&0xffff) || BDFDepth(bdf)!=1); bdf=bdf->next );
653
sfi->ids[j] = baseresid;
655
resstarts[cnt+j].id = baseresid++;
656
resstarts[cnt+j++].pos = DummyNFNT(res,bdf,sfi->map);
657
/* NFNTs seem to have resource flags of 0 */
665
enum psstyle_flags { psf_bold = 1, psf_italic = 2, psf_outline = 4,
666
psf_shadow = 0x8, psf_condense = 0x10, psf_extend = 0x20 };
668
uint16 _MacStyleCode( char *styles, SplineFont *sf, uint16 *psstylecode ) {
669
unsigned short stylecode= 0, psstyle=0;
671
if ( strstrmatch( styles, "Bold" ) || strstrmatch(styles,"Demi") ||
672
strstrmatch( styles,"Heav") || strstrmatch(styles,"Blac") ||
673
/* A few fonts have German/French styles in their names */
674
strstrmatch( styles,"Fett") || strstrmatch(styles,"Gras") ) {
677
} else if ( sf!=NULL && sf->weight!=NULL &&
678
(strstrmatch( sf->weight, "Bold" ) || strstrmatch(sf->weight,"Demi") ||
679
strstrmatch( sf->weight,"Heav") || strstrmatch(sf->weight,"Blac") ||
680
strstrmatch( sf->weight,"Fett") || strstrmatch(sf->weight,"Gras")) ) {
684
/* URW uses four leter abbreviations of Italic and Oblique */
685
/* Somebody else uses two letter abbrevs */
686
if ( (sf!=NULL && sf->italicangle!=0) ||
687
strstrmatch( styles, "Ital" ) ||
688
strstrmatch( styles, "Obli" ) ||
689
strstrmatch(styles, "Slanted") ||
690
strstrmatch(styles, "Kurs") ||
691
strstr( styles,"It" ) ) {
692
stylecode |= sf_italic;
693
psstyle |= psf_italic;
695
if ( strstrmatch( styles, "Underline" ) ) {
696
stylecode |= sf_underline;
698
if ( strstrmatch( styles, "Outl" ) ) {
699
stylecode |= sf_outline;
700
psstyle |= psf_outline;
702
if ( strstr(styles,"Shadow")!=NULL ) {
703
stylecode |= sf_shadow;
704
psstyle |= psf_shadow;
706
if ( strstrmatch( styles, "Cond" ) || strstr( styles,"Cn") ||
707
strstrmatch( styles, "Narrow") ) {
708
stylecode |= sf_condense;
709
psstyle |= psf_condense;
711
if ( strstrmatch( styles, "Exte" ) || strstr( styles,"Ex") ) {
712
stylecode |= sf_extend;
713
psstyle |= psf_extend;
715
if ( (psstyle&psf_extend) && (psstyle&psf_condense) ) {
717
LogError( _("Warning: %s(%s) is both extended and condensed. That's impossible.\n"),
718
sf->fontname, sf->origname );
720
LogError( _("Warning: Both extended and condensed. That's impossible.\n") );
721
psstyle &= ~psf_extend;
722
stylecode &= ~sf_extend;
724
if ( psstylecode!=NULL )
725
*psstylecode = psstyle;
729
uint16 MacStyleCode( SplineFont *sf, uint16 *psstylecode ) {
732
if ( sf->cidmaster!=NULL )
735
if ( sf->macstyle!=-1 ) {
736
if ( psstylecode!=NULL )
737
*psstylecode = (sf->macstyle&0x3)|((sf->macstyle&0x6c)>>1);
738
return( sf->macstyle );
741
styles = SFGetModifiers(sf);
742
return( _MacStyleCode(styles,sf,psstylecode));
746
static uint32 SFToFOND(FILE *res,SplineFont *sf,uint32 id,int dottf,
747
int32 *sizes, EncMap *map) {
748
uint32 rlenpos = ftell(res), widoffpos, widoffloc, kernloc, styleloc, end;
749
int i,j,k,cnt, strcnt, fontclass, stylecode, glyphenc, geoffset, realstylecode;
754
/* Fonds are generally marked system heap and sometimes purgeable (resource flags) */
756
putlong(res,0); /* Fill in length later */
757
putshort(res,IsMacMonospaced(sf,map)?0x9000:0x1000);
759
putshort(res,0); /* First character */
760
putshort(res,255); /* Last character */
761
putshort(res,(short) ((sf->ascent*(1<<12))/(sf->ascent+sf->descent)));
762
putshort(res,-(short) ((sf->descent*(1<<12))/(sf->ascent+sf->descent)));
763
putshort(res,(short) ((sf->pfminfo.linegap*(1<<12))/(sf->ascent+sf->descent)));
764
putshort(res,(short) ((SFMacWidthMax(sf,map)*(1<<12))/(sf->ascent+sf->descent)));
765
widoffpos = ftell(res);
766
putlong(res,0); /* Fill in width offset later */
767
putlong(res,0); /* Fill in kern offset later */
768
putlong(res,0); /* Fill in style offset later */
769
for ( i=0; i<9; ++i )
770
putshort(res,0); /* Extra width values */
771
putlong(res,0); /* Script for international */
772
putshort(res,2); /* FOND version */
774
/* Font association table */
775
stylecode = realstylecode = MacStyleCode( sf, NULL );
776
stylecode = 0; /* Debug !!!! */
777
for ( i=j=0; sizes!=NULL && sizes[i]!=0; ++i )
778
if ( (sizes[i]>>16)==1 && (sizes[i]&0xffff)<256 )
781
putshort(res,j+1-1); /* Number of faces */
782
putshort(res,0); /* it's scaleable */
783
putshort(res,stylecode);
784
putshort(res,id); /* Give it the same ID as the fond */
786
putshort(res,j-1); /* Number of faces */
788
for ( i=0; sizes[i]!=0; ++i ) if (( sizes[i]>>16) == 1 ) {
789
putshort(res,sizes[i]&0xffff);
790
putshort(res,stylecode);
791
putshort(res,id+(sizes[i]&0xffff)); /* make up a unique ID */
796
putshort(res,1-1); /* One table */
797
putlong(res,6); /* Offset from start of otab to next byte */
799
/* bounding box table */
800
putshort(res,1-1); /* One bounding box */
801
SplineFontFindBounds(sf,&b);
802
putshort(res,stylecode);
803
putshort(res,b.minx*(1<<12)/(sf->ascent+sf->descent));
804
putshort(res,b.miny*(1<<12)/(sf->ascent+sf->descent));
805
putshort(res,b.maxx*(1<<12)/(sf->ascent+sf->descent));
806
putshort(res,b.maxy*(1<<12)/(sf->ascent+sf->descent));
808
widoffloc = ftell(res);
809
putshort(res,1-1); /* One style in the width table too */
810
putshort(res,stylecode);
811
for ( k=0; k<=256; ++k ) {
812
if ( k>=map->enccount || k==256 || (gid=map->map[k])==-1 || sf->glyphs[gid]==NULL )
813
putshort(res,1<<12); /* 1 em is default size */
815
putshort(res,sf->glyphs[gid]->width*(1<<12)/(sf->ascent+sf->descent));
819
if (( cnt = SFMacAnyKerns(sf,map))>0 ) {
820
kernloc = ftell(res);
821
putshort(res,1-1); /* One style in the width table too */
822
putshort(res,stylecode); /* style */
823
putshort(res,cnt); /* Count of kerning pairs */
824
for ( k=0; k<256 && k<map->enccount; ++k ) {
825
if ( (gid=map->map[k])!=-1 && sf->glyphs[gid]!=NULL ) {
826
for ( kp=sf->glyphs[gid]->kerns; kp!=NULL; kp=kp->next )
827
if ( map->backmap[kp->sc->orig_pos]<256 ) {
829
putc(map->backmap[kp->sc->orig_pos],res);
830
putshort(res,kp->off*(1<<12)/(sf->ascent+sf->descent));
836
/* Fontographer referenced a postscript font even in truetype FONDs */
837
styleloc = ftell(res);
838
fontclass = 0x1; /* font name needs coordinating? Font has its own encoding */
839
if ( !(realstylecode&sf_outline) ) fontclass |= 4;
840
if ( realstylecode&sf_bold ) fontclass |= 0x18;
841
if ( realstylecode&psf_italic ) fontclass |= 0x40;
842
if ( realstylecode&psf_condense ) fontclass |= 0x80;
843
if ( realstylecode&psf_extend ) fontclass |= 0x100;
844
putshort(res,fontclass); /* fontClass */
845
geoffset = ftell(res);
846
putlong(res,0); /* Offset to glyph encoding table */ /* Fill in later */
847
putlong(res,0); /* Reserved, MBZ */
848
if ( strnmatch(sf->familyname,sf->fontname,strlen(sf->familyname))!=0 )
850
else if ( strmatch(sf->familyname,sf->fontname)==0 )
852
else if ( sf->fontname[strlen(sf->familyname)]=='-' )
856
for ( k=0; k<48; ++k )
857
putc(strcnt==1?1:2,res); /* All indeces point to this font */
858
putshort(res,strcnt); /* strcnt strings */
859
pt = sf->fontname+strlen(sf->familyname);
861
putc(strlen(sf->fontname),res); /* basename is full name */
862
/* Mac expects this to be upper case */
863
if ( Islower(*sf->fontname)) putc(toupper(*sf->fontname),res);
864
else putc(*sf->fontname,res);
865
fwrite(sf->fontname+1,1,strlen(sf->fontname+1),res);
867
putc(strlen(sf->familyname),res);/* basename */
868
if ( Islower(*sf->familyname)) putc(toupper(*sf->familyname),res);
869
else putc(*sf->familyname,res);
870
fwrite(sf->familyname+1,1,strlen(sf->familyname+1),res);
872
putc(1,res); /* index string is one byte long */
873
putc(3,res); /* plain name is basename with string 2 */
874
putc(strlen(pt),res); /* length of... */
875
fwrite(pt,1,strlen(pt),res); /* everything else */
877
putc(2,res); /* index string is two bytes long */
878
putc(3,res); /* plain name is basename with hyphen */
879
putc(4,res); /* and everything else */
880
putc(1,res); /* Length of ... */
881
putc('-',res); /* String containing hyphen */
882
++pt; /* skip over hyphen */
883
putc(strlen(pt),res); /* length of ... */
884
fwrite(pt,1,strlen(pt),res); /* everything else */
887
/* Greg: record offset for glyph encoding table */
888
/* We assume that the bitmap and postscript fonts are encoded similarly */
889
/* and so a null vector will do. */
890
/* GWW: Hmm. ATM refuses to use postscript fonts that have */
891
/* glyph encoding tables. Printer drivers use them ok. ATM will only */
892
/* work on fonts with mac roman encodings */
893
if ( strmatch(map->enc->enc_name,"mac")!=0 &&
894
strmatch(map->enc->enc_name,"macintosh")!=0 &&
895
strmatch(map->enc->enc_name,"macroman")!=0 ) {
896
#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
897
if ( !dottf ) ff_post_notice(_("The generated font won't work with ATM"),_("ATM requires that fonts be encoded with the Macintosh Latin encoding. This postscript font will print fine, but only the bitmap versions will be displayed on the screen"));
899
glyphenc = ftell( res );
900
fseek(res,geoffset,SEEK_SET);
901
putlong(res,glyphenc-geoffset+2);
902
fseek(res,glyphenc,SEEK_SET);
906
putshort(res,sf->charcnt>256?128:sf->charcnt-128);
907
for ( i=0x80; i<sf->charcnt && i<256; ++i ) {
908
SplineChar *sc, dummy;
910
sc = SCBuildDummy(&dummy,sf,i);
911
putc(strlen(sc->name),res);
912
fwrite(sc->name,1,strlen(sc->name),res);
918
fseek(res,widoffpos,SEEK_SET);
919
putlong(res,widoffloc-rlenpos-4); /* Fill in width offset */
920
putlong(res,kernloc!=0?kernloc-rlenpos-4:0); /* Fill in kern offset */
921
putlong(res,styleloc!=0?styleloc-rlenpos-4:0); /* Fill in style offset */
923
fseek(res,rlenpos,SEEK_SET);
924
putlong(res,end-rlenpos-4); /* resource length */
925
fseek(res,end,SEEK_SET);
929
static void putpnsstring(FILE *res,char *fontname,int len) {
931
if ( *fontname && len>0 ) {
932
if ( Islower(*fontname))
933
putc(toupper(*fontname),res);
937
for ( ++fontname; *fontname && len>0; ++fontname, --len )
942
static void putpsstring(FILE *res,char *fontname) {
943
putc(strlen(fontname),res);
945
for ( ; *fontname; ++fontname )
952
struct sflistlist *next;
956
static struct sflistlist *FondSplitter(struct sflist *sfs,int *fondcnt) {
957
struct sflist *psfaces[48], *sfi, *last, *start;
958
struct sflistlist *sfsl=NULL, *lastl=NULL, *cur, *test;
963
if ( sfi->sf->fondname==NULL ) {
964
memset(psfaces,0,sizeof(psfaces));
965
MacStyleCode(sfi->sf,&psstyle);
967
while ( sfi->sf->fondname==NULL && psfaces[psstyle]==NULL ) {
968
psfaces[psstyle] = sfi;
973
MacStyleCode(sfi->sf,&psstyle);
975
cur = gcalloc(1,sizeof(struct sflistlist));
978
for ( last=sfi; last!=NULL; last=last->next )
979
if ( last->sf->fondname!=NULL && strcmp(last->sf->fondname,sfs->sf->familyname)==0 )
981
cur->fondname = copy( last==NULL ? sfs->sf->familyname : sfs->sf->fontname );
985
while ( sfi!=NULL ) {
987
if ( sfi->sf->fondname==NULL ) {
991
memset(psfaces,0,sizeof(psfaces));
992
MacStyleCode(sfi->sf,&psstyle);
993
while ( sfi!=NULL && sfi->sf->fondname!=NULL &&
994
strcmp(sfi->sf->fondname,start->sf->fondname)==0 &&
995
psfaces[psstyle]==NULL ) {
996
psfaces[psstyle] = sfi;
1001
MacStyleCode(sfi->sf,&psstyle);
1004
cur = gcalloc(1,sizeof(struct sflistlist));
1006
if ( start->sf->fondname!=NULL ) {
1007
for ( test = sfsl; test!=NULL; test=test->next )
1008
if ( strcmp(test->fondname,start->sf->fondname)==0 )
1011
cur->fondname = copy(start->sf->fondname);
1013
if ( cur->fondname==NULL )
1014
cur->fondname = copy(start->sf->fontname);
1015
if ( lastl!=NULL ) lastl->next = cur;
1027
static void SFListListFree(struct sflistlist *sfsl) {
1028
struct sflist *last = NULL;
1029
struct sflistlist *sfli, *sflnext;
1030
/* free the fond list and restore the sfs list */
1032
for ( sfli=sfsl; sfli!=NULL; sfli = sflnext ) {
1033
sflnext = sfli->next;
1035
last->next = sfli->sfs;
1036
for ( last = sfli->sfs; last->next!=NULL; last = last->next );
1037
free(sfli->fondname);
1042
static uint32 SFsToFOND(FILE *res,struct sflist *sfs,uint32 id,int format,int bf) {
1043
uint32 rlenpos = ftell(res), widoffpos, widoffloc, kernloc, styleloc, end;
1044
int i,j,k,cnt, scnt, kcnt, pscnt, strcnt, fontclass, glyphenc, geoffset;
1047
uint16 psstyle, stylecode;
1048
int exact, famlen, has_hyphen;
1052
/* Fonds are generally marked system heap and sometimes purgeable (resource flags) */
1053
struct sflist *faces[96];
1054
struct sflist *psfaces[48];
1059
memset(faces,0,sizeof(faces));
1060
memset(psfaces,0,sizeof(psfaces));
1061
for ( sfi = sfs ; sfi!=NULL; sfi = sfi->next ) {
1062
stylecode = MacStyleCode(sfi->sf,&psstyle);
1063
if ( sfs->next==NULL ) /* FONDs with a single entry should make that entry be "regular" no matter what we think it really is */
1064
stylecode = psstyle = 0;
1065
if ( faces[stylecode]==NULL )
1066
faces[stylecode] = sfi;
1067
if ( psfaces[psstyle]==NULL )
1068
psfaces[psstyle] = sfi;
1072
putlong(res,0); /* Fill in length later */
1073
putshort(res,IsMacMonospaced(sf,faces[0]->map)?0x9000:0x1000);
1075
putshort(res,0); /* First character */
1076
putshort(res,255); /* Last character */
1077
putshort(res,(short) ((sf->ascent*(1<<12))/(sf->ascent+sf->descent)));
1078
putshort(res,-(short) ((sf->descent*(1<<12))/(sf->ascent+sf->descent)));
1079
putshort(res,(short) ((sf->pfminfo.linegap*(1<<12))/(sf->ascent+sf->descent)));
1080
putshort(res,(short) ((SFMacWidthMax(sf,faces[0]->map)*(1<<12))/(sf->ascent+sf->descent)));
1081
widoffpos = ftell(res);
1082
putlong(res,0); /* Fill in width offset later */
1083
putlong(res,0); /* Fill in kern offset later */
1084
putlong(res,0); /* Fill in style offset later */
1085
for ( i=0; i<9; ++i )
1086
putshort(res,0); /* Extra width values */
1087
putlong(res,0); /* Script for international */
1088
putshort(res,2); /* FOND version */
1090
/* Font association table */
1091
for ( i=cnt=scnt=kcnt=0; i<96; ++i ) if ( faces[i]!=NULL ) {
1093
if ( faces[i]->id!=0 ) ++cnt;
1094
if ( faces[i]->ids!=NULL )
1095
for ( j=0; faces[i]->ids[j]!=0; ++j ) ++cnt;
1096
if ( SFMacAnyKerns(faces[i]->sf,faces[i]->map)>0 )
1099
putshort(res,cnt-1); /* Number of faces */
1100
/* do ttf faces (if any) first */
1101
for ( i=cnt=0; i<96; ++i ) if ( faces[i]!=NULL && faces[i]->id!=0 ) {
1102
putshort(res,0); /* it's scaleable */
1103
putshort(res,i); /* style */
1104
putshort(res,faces[i]->id);
1106
/* then do bitmap faces (if any) */ /* Ordered by size damn it */
1107
for ( size=1; size<256; ++size ) {
1108
for ( i=0; i<96; ++i ) if ( faces[i]!=NULL && faces[i]->ids!=NULL ) {
1109
for ( j=0; faces[i]->ids[j]!=0 ; ++j ) {
1110
int pointsize = rint( (faces[i]->bdfs[j]->pixelsize*72.0/mac_dpi) );
1111
if ( pointsize==size ) {
1113
putshort(res,i); /* style */
1114
putshort(res,faces[i]->ids[j]);
1121
putshort(res,1-1); /* One table */
1122
putlong(res,6); /* Offset from start of otab to next byte */
1124
/* bounding box table */
1125
putshort(res,scnt-1); /* One bounding box per style */
1126
for ( i=0; i<96; ++i ) if ( faces[i]!=NULL ) {
1127
SplineFontFindBounds(faces[i]->sf,&b);
1128
putshort(res,i); /* style */
1129
putshort(res,b.minx*(1<<12)/(faces[i]->sf->ascent+faces[i]->sf->descent));
1130
putshort(res,b.miny*(1<<12)/(faces[i]->sf->ascent+faces[i]->sf->descent));
1131
putshort(res,b.maxx*(1<<12)/(faces[i]->sf->ascent+faces[i]->sf->descent));
1132
putshort(res,b.maxy*(1<<12)/(faces[i]->sf->ascent+faces[i]->sf->descent));
1135
widoffloc = ftell(res);
1136
putshort(res,scnt-1); /* One set of width metrics per style */
1137
for ( i=0; i<96; ++i ) if ( faces[i]!=NULL ) {
1139
for ( k=0; k<=257; ++k ) {
1140
if ( k>=faces[i]->map->enccount || k>=256 ||
1141
(gid=faces[i]->map->map[k])==-1 || faces[i]->sf->glyphs[gid]==NULL )
1142
putshort(res,1<<12); /* 1 em is default size */
1144
putshort(res,faces[i]->sf->glyphs[gid]->width*(1<<12)/(faces[i]->sf->ascent+faces[i]->sf->descent));
1150
kernloc = ftell(res);
1151
putshort(res,kcnt-1); /* Number of styles with kern pairs */
1152
for ( i=0; i<96; ++i ) if ( faces[i]!=NULL && ( cnt = SFMacAnyKerns(faces[i]->sf,faces[i]->map))>0 ) {
1153
putshort(res,i); /* style */
1154
putshort(res,cnt); /* Count of kerning pairs */
1155
for ( k=0; k<256 && k<faces[i]->map->enccount; ++k ) {
1156
if ( (gid=faces[i]->map->map[k])!=-1 && faces[i]->sf->glyphs[gid]!=NULL ) {
1157
for ( kp=faces[i]->sf->glyphs[gid]->kerns; kp!=NULL; kp=kp->next )
1158
if ( faces[i]->map->backmap[kp->sc->orig_pos]<256 ) {
1160
putc(faces[i]->map->backmap[kp->sc->orig_pos],res);
1161
putshort(res,kp->off*(1<<12)/(sf->ascent+sf->descent));
1168
/* Fontographer referenced a postscript font even in truetype FONDs */
1169
styleloc = ftell(res);
1172
familyname = psfaces[0]->sf->fontname;
1173
famlen = strlen(familyname);
1174
if ( (pt=strchr(familyname,'-'))!=NULL )
1175
famlen = pt-familyname;
1176
else if ( strnmatch(psfaces[0]->sf->familyname,psfaces[0]->sf->fontname,
1177
strlen(psfaces[0]->sf->familyname))==0 )
1178
famlen = strlen(psfaces[0]->sf->familyname);
1179
has_hyphen = (familyname[famlen]=='-');
1180
for ( i=pscnt=0; i<48; ++i ) if ( psfaces[i]!=NULL ) {
1182
if ( strncmp(psfaces[i]->sf->fontname,familyname,famlen)!=0 ) {
1183
while ( famlen>0 ) {
1185
if ( strncmp(psfaces[i]->sf->fontname,familyname,famlen)==0 )
1190
if ( famlen!=0 ) for ( i=0; i<48; ++i ) if ( psfaces[i]!=NULL ) {
1191
if ( psfaces[i]->sf->fontname[famlen]==0 )
1195
if ( psfaces[psf_outline]==NULL ) fontclass |= 4;
1196
if ( psfaces[psf_bold]!=NULL ) fontclass |= 0x18;
1197
if ( psfaces[psf_italic]!=NULL ) fontclass |= 0x40;
1198
if ( psfaces[psf_condense]!=NULL ) fontclass |= 0x80;
1199
if ( psfaces[psf_extend]!=NULL ) fontclass |= 0x100;
1200
putshort(res,fontclass); /* fontClass */
1201
geoffset = ftell(res);
1202
putlong(res,0); /* Offset to glyph encoding table */ /* Fill in later */
1203
putlong(res,0); /* Reserved, MBZ */
1204
strcnt = 1/* Family Name */ + pscnt-exact /* count of format strings */ +
1206
pscnt-exact /* count of additional strings */;
1207
/* indeces to format strings */
1208
for ( i=0,pscnt=2; i<48; ++i )
1209
if ( psfaces[i]!=NULL && psfaces[i]->sf->fontname[famlen]!=0 )
1215
putshort(res,strcnt); /* strcnt strings */
1216
putpnsstring(res,familyname,famlen);
1217
if ( has_hyphen ) has_hyphen = pscnt++; /* Space for hyphen if present */
1218
/* Now the format strings */
1219
for ( i=0; i<48; ++i ) if ( psfaces[i]!=NULL ) {
1220
if ( psfaces[i]->sf->fontname[famlen]!=0 ) {
1221
if ( has_hyphen && psfaces[i]->sf->fontname[famlen]==' ' ) {
1223
putc(has_hyphen,res);
1226
putc(1,res); /* Familyname with the following */
1235
/* Now the additional names */
1236
for ( i=0; i<48; ++i ) if ( psfaces[i]!=NULL ) {
1237
if ( psfaces[i]->sf->fontname[famlen]!=0 )
1238
putpsstring(res,psfaces[i]->sf->fontname+famlen);
1240
/* Greg: record offset for glyph encoding table */
1241
/* We assume that the bitmap and postscript fonts are encoded similarly */
1242
/* and so a null vector will do. */
1243
/* GWW: Hmm. ATM refuses to use postscript fonts that have */
1244
/* glyph encoding tables. Printer drivers use them ok. ATM will only */
1245
/* work on fonts with mac roman encodings */
1246
if ( strmatch(psfaces[0]->map->enc->enc_name,"mac")!=0 &&
1247
strmatch(psfaces[0]->map->enc->enc_name,"macintosh")!=0 &&
1248
strmatch(psfaces[0]->map->enc->enc_name,"macroman")!=0 ) {
1249
if ( format==ff_pfbmacbin )
1250
#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
1251
ff_post_notice(_("The generated font won't work with ATM"),_("ATM requires that fonts be encoded with the Macintosh Latin encoding. This postscript font will print fine, but only the bitmap versions will be displayed on the screen"));
1253
glyphenc = ftell( res );
1254
fseek(res,geoffset,SEEK_SET);
1255
putlong(res,glyphenc-geoffset+2);
1256
fseek(res,glyphenc,SEEK_SET);
1257
putshort(res,0); /* Greg: an empty Glyph encoding table */
1261
fseek(res,widoffpos,SEEK_SET);
1262
putlong(res,widoffloc-rlenpos-4); /* Fill in width offset */
1263
putlong(res,kernloc!=0?kernloc-rlenpos-4:0); /* Fill in kern offset */
1264
putlong(res,styleloc!=0?styleloc-rlenpos-4:0); /* Fill in style offset */
1266
fseek(res,rlenpos,SEEK_SET);
1267
putlong(res,end-rlenpos-4); /* resource length */
1268
fseek(res,end,SEEK_SET);
1272
/* I presume this routine is called after all resources have been written */
1273
static void DumpResourceMap(FILE *res,struct resourcetype *rtypes,enum fontformat format) {
1274
uint32 rfork_base = format>=ff_ttfdfont?0:128; /* space for mac binary header */
1275
uint32 resource_base = rfork_base+0x100;
1276
uint32 rend, rtypesstart, mend, namestart;
1279
fseek(res,0,SEEK_END);
1282
if ( format<ff_ttfdfont ) {
1283
/* Duplicate resource header */
1284
putlong(res,0x100); /* start of resource data */
1285
putlong(res,rend-rfork_base); /* start of resource map */
1286
putlong(res,rend-rfork_base-0x100); /* length of resource data */
1287
putlong(res,0); /* don't know the length of the map section yet */
1289
for ( i=0; i<16; ++i ) /* 16 bytes of zeroes */
1293
putlong(res,0); /* Some mac specific thing I don't understand */
1294
putshort(res,0); /* another */
1295
putshort(res,0); /* another */
1297
putshort(res,4+ftell(res)-rend); /* Offset to resource types */
1298
putshort(res,0); /* Don't know where the names go yet */
1300
rtypesstart = ftell(res);
1301
for ( i=0; rtypes[i].tag!=0; ++i );
1302
putshort(res,i-1); /* Count of different types */
1303
for ( i=0; rtypes[i].tag!=0; ++i ) {
1304
putlong(res,rtypes[i].tag); /* Resource type */
1305
putshort(res,0); /* Number of resources of this type */
1306
putshort(res,0); /* Offset to the resource list */
1309
/* Now the resource lists... */
1310
for ( i=0; rtypes[i].tag!=0; ++i ) {
1311
rtypes[i].resloc = ftell(res);
1312
for ( j=0; rtypes[i].res[j].pos!=0; ++j ) {
1313
putshort(res,rtypes[i].res[j].id);
1314
rtypes[i].res[j].nameptloc = ftell(res);
1315
putshort(res,0xffff); /* assume no name at first */
1316
putc(rtypes[i].res[j].flags,res); /* resource flags */
1317
/* three byte resource offset */
1318
putc( ((rtypes[i].res[j].pos-resource_base)>>16)&0xff, res );
1319
putc( ((rtypes[i].res[j].pos-resource_base)>>8)&0xff, res );
1320
putc( ((rtypes[i].res[j].pos-resource_base)&0xff), res );
1324
namestart = ftell(res);
1325
/* Now the names, if any */
1326
for ( i=0; rtypes[i].tag!=0; ++i ) {
1327
for ( j=0; rtypes[i].res[j].pos!=0; ++j ) {
1328
if ( rtypes[i].res[j].name!=NULL ) {
1329
rtypes[i].res[j].nameloc = ftell(res);
1330
putc(strlen(rtypes[i].res[j].name),res); /* Length */
1331
fwrite(rtypes[i].res[j].name,1,strlen(rtypes[i].res[j].name),res);
1337
/* Repeat the rtypes list now we know where they go */
1338
fseek(res,rtypesstart+2,SEEK_SET); /* skip over the count */
1339
for ( i=0; rtypes[i].tag!=0; ++i ) {
1340
putlong(res,rtypes[i].tag); /* Resource type */
1341
for ( j=0; rtypes[i].res[j].pos!=0; ++j );
1342
putshort(res,j-1); /* Number of resources of this type */
1343
putshort(res,rtypes[i].resloc-rtypesstart);
1345
/* And go back and fixup any name pointers */
1346
for ( i=0; rtypes[i].tag!=0; ++i ) {
1347
for ( j=0; rtypes[i].res[j].pos!=0; ++j ) {
1348
if ( rtypes[i].res[j].name!=NULL ) {
1349
fseek(res,rtypes[i].res[j].nameptloc,SEEK_SET);
1350
putshort(res,rtypes[i].res[j].nameloc-namestart);
1355
fseek(res,rend,SEEK_SET);
1356
/* Fixup duplicate header (and offset to the name list) */
1357
if ( format<ff_ttfdfont ) {
1358
putlong(res,0x100); /* start of resource data */
1359
putlong(res,rend-rfork_base); /* start of resource map */
1360
putlong(res,rend-rfork_base-0x100); /* length of resource data */
1361
putlong(res,mend-rend); /* length of map section */
1363
for ( i=0; i<16; ++i )
1367
putlong(res,0); /* Some mac specific thing I don't understand */
1368
putshort(res,0); /* another */
1369
putshort(res,0); /* another */
1371
putshort(res,4+ftell(res)-rend); /* Offset to resource types */
1372
putshort(res,namestart-rend); /* name section */
1374
fseek(res,rfork_base,SEEK_SET);
1375
/* Fixup main resource header */
1376
putlong(res,0x100); /* start of resource data */
1377
putlong(res,rend-rfork_base); /* start of resource map */
1378
putlong(res,rend-rfork_base-0x100); /* length of resource data */
1379
putlong(res,mend-rend); /* length of map section */
1382
long mactime(void) {
1387
/* convert from 1970 based time to 1904 based time */
1388
now += (1970-1904)*365L*24*60*60;
1389
for ( i=1904; i<1970; i+=4 )
1391
/* Ignore any leap seconds -- Sorry Steve */
1395
static int DumpMacBinaryHeader(FILE *res,struct macbinaryheader *mb) {
1397
uint8 header[128], *hpt; char buffer[256], *pt, *dpt;
1402
if ( mb->macfilename==NULL ) {
1403
char *pt = strrchr(mb->binfilename,'/');
1404
if ( pt==NULL ) pt = mb->binfilename;
1407
dpt = strrchr(buffer,'.');
1410
strcpy(buffer+1,pt);
1413
mb->macfilename = buffer;
1417
memset(header,'\0',sizeof(header));
1419
*hpt++ = '\0'; /* version number */
1421
pt = mb->macfilename;
1422
*hpt++ = strlen( pt );
1425
while ( hpt<header+65 )
1428
*hpt++ = mb->type>>24; *hpt++ = mb->type>>16; *hpt++ = mb->type>>8; *hpt++ = mb->type;
1430
*hpt++ = mb->creator>>24; *hpt++ = mb->creator>>16; *hpt++ = mb->creator>>8; *hpt++ = mb->creator;
1431
*hpt++ = '\0'; /* No finder flags set */
1432
*hpt++ = '\0'; /* (byte 74) MBZ */
1433
*hpt++ = '\0'; *hpt++ = '\0'; /* Vert Position in folder */
1434
*hpt++ = '\0'; *hpt++ = '\0'; /* Hor Position in folder */
1435
*hpt++ = '\0'; *hpt++ = '\0'; /* window or folder id??? */
1436
*hpt++ = '\0'; /* protected bit ??? */
1437
*hpt++ = '\0'; /* (byte 82) MBZ */
1438
/* Data fork length */
1439
*hpt++ = '\0'; *hpt++ = '\0'; *hpt++ = '\0'; *hpt++ = '\0';
1440
/* Resource fork length */
1441
fseek(res,0,SEEK_END);
1442
len = ftell(res)-sizeof(header);
1443
*hpt++ = len>>24; *hpt++ = len>>16; *hpt++ = len>>8; *hpt++ = len;
1444
/* Pad resource fork to be a multiple of 128 bytes */
1445
while ( (len&127)!=0 )
1446
{ putc('\0',res); ++len; }
1448
/* Creation time, (seconds from 1/1/1904) */
1451
*hpt++ = now>>24; *hpt++ = now>>16; *hpt++ = now>>8; *hpt++ = now;
1452
/* Modification time, (seconds from 1/1/1904) */
1453
*hpt++ = now>>24; *hpt++ = now>>16; *hpt++ = now>>8; *hpt++ = now;
1455
*hpt++ = '\0'; *hpt++ = '\0'; /* Get Info comment length */
1456
*hpt++ = 0; /* More finder flags */
1459
memcpy(header+102,"mBIN",4);
1460
header[106] = 0; /* Script. I assume 0 is latin */
1461
header[107] = 0; /* extended finder flags */
1462
/* End of MacBinary 3 */
1463
header[122] = 130; /* MacBinary version 3, written in (129 is MB2) */
1464
header[123] = 129; /* MacBinary Version 2, needed to read */
1466
crc = binhex_crc(header,124);
1467
header[124] = crc>>8;
1470
fseek(res,0,SEEK_SET);
1471
fwrite(header,1,sizeof(header),res);
1475
FSRef ref, parentref;
1477
char *buf, *dirname, *pt, *fname;
1478
HFSUniStr255 resforkname;
1481
unichar_t *filename;
1483
/* When on the mac let's just create a real resource fork. We do this by */
1484
/* creating a mac file with a resource fork, opening that fork, and */
1485
/* dumping all the data in the temporary file after the macbinary header */
1487
/* The mac file routines are really lovely. I can't convert a pathspec to */
1488
/* an FSRef unless the file exists. That is incredibly stupid and annoying of them */
1489
/* But the directory should exist... */
1490
fname = mb->macfilename?mb->macfilename:mb->binfilename;
1491
dirname = copy(fname);
1492
pt = strrchr(dirname,'/');
1497
dirname = copy(".");
1499
ret=FSPathMakeRef( (uint8 *) dirname,&parentref,NULL);
1504
pt = strrchr(fname,'/');
1505
filename = def2u_copy(pt==NULL?fname:pt+1);
1506
((FInfo *) (info.finderInfo))->fdType = mb->type;
1507
((FInfo *) (info.finderInfo))->fdCreator = mb->creator;
1508
ret = FSCreateFileUnicode(&parentref,u_strlen(filename), (UniChar *) filename,
1509
kFSCatInfoFinderInfo, &info, &ref, NULL);
1511
if ( ret==dupFNErr ) {
1512
/* File already exists, create failed, didn't get an FSRef */
1513
ret=FSPathMakeRef( (uint8 *) fname,&ref,NULL);
1518
FSGetResourceForkName(&resforkname);
1519
FSCreateFork(&ref,resforkname.length,resforkname.unicode); /* I don't think this is needed, but it doesn't hurt... */
1520
ret = FSOpenFork(&ref,resforkname.length,resforkname.unicode,fsWrPerm,&macfile);
1523
FSSetForkSize(macfile,fsFromStart,0);/* Truncate it just in case it existed... */
1524
fseek(res,128,SEEK_SET); /* Everything after the mac binary header in */
1525
/* the temp file is resource fork */
1526
buf = galloc(8*1024);
1527
while ( (len=fread(buf,1,8*1024,res))>0 )
1528
FSWriteFork(macfile,fsAtMark,0,len,buf,&whocares);
1529
FSCloseFork(macfile);
1535
static void WriteDummyMacHeaders(FILE *res) {
1536
/* Leave space for the mac binary header (128bytes) and the mac resource */
1537
/* file header (256 bytes) */
1539
for ( i=0; i<128; ++i )
1541
for ( i=0; i<256; ++i )
1545
static void WriteDummyDFontHeaders(FILE *res) {
1546
/* Leave space for the mac resource file header (256 bytes) */
1547
/* dfonts have the format of a data fork resource file (which I've never */
1548
/* seen documented, but appears to be just like a resource fork except */
1549
/* the first 16 bytes are not duplicated at the map */
1551
for ( i=0; i<256; ++i )
1555
/* The mac has rules about what the filename should be for a postscript*/
1556
/* font. If you deviate from those rules the font will not be found */
1557
/* The font name must begin with a capital letter */
1558
/* The filename is designed by modifying the font name */
1559
/* After the initial capital there can be at most 4 lower case letters (or digits) */
1560
/* in the filename, any additional lc letters (or digits) in the fontname are ignored */
1561
/* Every subsequent capital will be followed by at most 2 lc letters */
1562
/* special characters ("-$", etc.) are removed entirely */
1563
/* So Times-Bold => TimesBol, HelveticaDemiBold => HelveDemBol */
1564
/* MacBinary limits the name to 63 characters, I dunno what happens if */
1565
/* we excede that */
1566
static void MakeMacPSName(char buffer[63],SplineFont *sf) {
1567
char *pt, *spt, *lcpt;
1569
for ( pt = buffer, spt = sf->fontname; *spt && pt<buffer+63-1; ++spt ) {
1570
if ( Isupper(*spt) || spt==sf->fontname ) {
1572
lcpt = (spt==sf->fontname?spt+5:spt+3);
1573
} else if ( (Islower(*spt) || Isdigit(*spt)) && spt<lcpt )
1579
int WriteMacPSFont(char *filename,SplineFont *sf,enum fontformat format,
1580
int flags,EncMap *map) {
1582
FILE *res, *temppfb;
1584
struct resourcetype resources[2];
1585
struct macbinaryheader header;
1586
int lcfn = false, lcfam = false;
1592
temppfb = tmpfile();
1593
if ( temppfb==NULL )
1596
/* The mac has rules about what the filename should be for a postscript*/
1597
/* font. If you deviate from those rules the font will not be found */
1598
/* The font name must begin with a capital letter */
1599
/* The filename is designed by modifying the font name */
1600
/* After the initial capital there can be at most 4 lower case letters (or digits) */
1601
/* in the filename, any additional lc letters (or digits) in the fontname are ignored */
1602
/* Every subsequent capital will be followed by at most 2 lc letters */
1603
/* special characters ("-$", etc.) are removed entirely */
1604
/* So Times-Bold => TimesBol, HelveticaDemiBold => HelveDemBol */
1605
/* MacBinary limits the name to 63 characters, I dunno what happens if */
1606
/* we excede that */
1607
if ( Islower(*sf->fontname)) { *sf->fontname = toupper(*sf->fontname); lcfn = true; }
1608
if ( Islower(*sf->familyname)) { *sf->familyname = toupper(*sf->familyname); lcfam = true; }
1609
MakeMacPSName(buffer,sf);
1611
ret = _WritePSFont(temppfb,sf,ff_pfb,flags,map,NULL);
1612
if ( lcfn ) *sf->fontname = Tolower(*sf->fontname);
1613
if ( lcfam ) *sf->familyname = Tolower(*sf->familyname);
1614
if ( ret==0 || ferror(temppfb) ) {
1619
if ( __Mac && format==ff_pfbmacbin )
1622
res = fopen(filename,"wb+");
1628
WriteDummyMacHeaders(res);
1629
memset(resources,'\0',sizeof(resources));
1632
resources[0].tag = CHR('P','O','S','T');
1633
resources[0].res = PSToResources(res,temppfb);
1635
DumpResourceMap(res,resources,format);
1636
free( resources[0].res );
1639
header.macfilename = galloc(strlen(filename)+strlen(buffer)+1);
1640
strcpy(header.macfilename,filename);
1641
pt = strrchr(header.macfilename,'/');
1642
if ( pt==NULL ) pt=header.macfilename-1;
1643
strcpy(pt+1,buffer);
1645
header.macfilename = buffer;
1647
/* Adobe uses a creator of ASPF (Adobe Systems Postscript Font I assume) */
1648
/* Fontographer uses ACp1 (Altsys Corp. Postscript type 1???) */
1649
/* Both include an FREF, BNDL, ICON* and comment */
1650
/* I shan't bother with that... It'll look ugly with no icon, but oh well */
1651
header.type = CHR('L','W','F','N');
1652
header.creator = CHR('G','W','p','1');
1653
ret = DumpMacBinaryHeader(res,&header);
1654
if ( ferror(res) ) ret = 0;
1655
if ( fclose(res)==-1 ) ret = 0;
1657
free(header.macfilename);
1665
int WriteMacTTFFont(char *filename,SplineFont *sf,enum fontformat format,
1666
int32 *bsizes, enum bitmapformat bf,int flags,EncMap *map) {
1667
FILE *res, *tempttf;
1669
struct resourcetype resources[4];
1670
struct resource rlist[3][2], *dummynfnts=NULL;
1671
struct macbinaryheader header;
1673
tempttf = tmpfile();
1674
if ( tempttf==NULL )
1677
if ( _WriteTTFFont(tempttf,sf,format==ff_none?ff_none:
1678
format==ff_ttfmacbin?ff_ttf:
1679
format-1,bsizes,bf,flags,map)==0 || ferror(tempttf) ) {
1683
if ( bf!=bf_ttf && bf!=bf_sfnt_dfont )
1684
bsizes = NULL; /* as far as the FOND for the truetype is concerned anyway */
1686
if ( __Mac && format==ff_ttfmacbin )
1689
res = fopen(filename,"wb+");
1695
if ( format!=ff_ttfmacbin )
1696
WriteDummyDFontHeaders(res);
1698
WriteDummyMacHeaders(res);
1699
memset(rlist,'\0',sizeof(rlist));
1700
memset(resources,'\0',sizeof(resources));
1704
resources[r].tag = CHR('s','f','n','t');
1705
resources[r++].res = rlist[0];
1706
rlist[0][0].pos = TTFToResource(res,tempttf);
1707
rlist[0][0].id = HashToId(sf->fontname,sf,map);
1708
rlist[0][0].flags = 0x00; /* sfnts generally have resource flags 0x20 */
1709
if ( bsizes!=NULL ) {
1710
resources[r].tag = CHR('N','F','N','T');
1711
resources[r++].res = dummynfnts = BuildDummyNFNTlist(res,sf,bsizes,rlist[0][0].id,map);
1713
resources[r].tag = CHR('F','O','N','D');
1714
resources[r].res = rlist[1];
1715
rlist[1][0].pos = SFToFOND(res,sf,rlist[0][0].id,true,bsizes,map);
1716
rlist[1][0].flags = 0x00; /* I've seen FONDs with resource flags 0, 0x20, 0x60 */
1717
rlist[1][0].id = rlist[0][0].id;
1718
rlist[1][0].name = sf->fondname ? sf->fondname : sf->familyname;
1720
DumpResourceMap(res,resources,format);
1724
if ( format==ff_ttfmacbin ) {
1725
header.macfilename = NULL;
1726
header.binfilename = filename;
1727
/* Fontographer uses the old suitcase format for both bitmaps and ttf */
1728
header.type = CHR('F','F','I','L');
1729
header.creator = CHR('D','M','O','V');
1730
ret = DumpMacBinaryHeader(res,&header);
1732
if ( ferror(res) ) ret = false;
1733
if ( fclose(res)==-1 ) ret = 0;
1737
int WriteMacBitmaps(char *filename,SplineFont *sf, int32 *sizes, int is_dfont,
1741
struct resourcetype resources[3];
1742
struct resource rlist[2][2];
1743
struct macbinaryheader header;
1744
char *binfilename, *pt, *dpt;
1746
/* The filename we've been given is for the outline font, which might or */
1747
/* might not be stuffed inside a bin file */
1748
binfilename = galloc(strlen(filename)+strlen(".bmap.dfont")+1);
1749
strcpy(binfilename,filename);
1750
pt = strrchr(binfilename,'/');
1751
if ( pt==NULL ) pt = binfilename; else ++pt;
1752
dpt = strrchr(pt,'.');
1754
dpt = pt+strlen(pt);
1755
else if ( strmatch(dpt,".bin")==0 || strmatch(dpt,".dfont")==0 ) {
1757
dpt = strrchr(pt,'.');
1759
dpt = pt+strlen(pt);
1761
strcpy(dpt,is_dfont?".bmap.dfont":__Mac?".bmap":".bmap.bin");
1763
if ( __Mac && !is_dfont )
1766
res = fopen(binfilename,"wb+");
1773
WriteDummyDFontHeaders(res);
1775
WriteDummyMacHeaders(res);
1776
memset(rlist,'\0',sizeof(rlist));
1777
memset(resources,'\0',sizeof(resources));
1779
resources[0].tag = CHR('N','F','N','T');
1780
resources[0].res = SFToNFNTs(res,sf,sizes,map);
1781
resources[1].tag = CHR('F','O','N','D');
1782
resources[1].res = rlist[1];
1783
rlist[1][0].id = HashToId(sf->fontname,sf,map);
1784
rlist[1][0].pos = SFToFOND(res,sf,rlist[1][0].id,false,sizes,map);
1785
rlist[1][0].name = sf->fondname ? sf->fondname : sf->familyname;
1786
DumpResourceMap(res,resources,is_dfont?ff_ttfdfont:ff_ttfmacbin);
1790
header.macfilename = NULL;
1791
header.binfilename = binfilename;
1792
/* Fontographer uses the old suitcase format for both bitmaps and ttf */
1793
header.type = CHR('F','F','I','L');
1794
header.creator = CHR('D','M','O','V');
1795
ret = DumpMacBinaryHeader(res,&header);
1797
if ( ferror(res)) ret = false;
1798
if ( fclose(res)==-1 ) ret = 0;
1799
free(resources[0].res);
1804
/* We have to worry about these font formats:
1805
ff_pfbmacbin, ff_ttfmacbin, ff_ttfdfont, ff_otfdfont, ff_otfciddfont, ff_none
1806
bf_ttf, bf_sfnt_dfont, bf_nfntmacbin,
1807
bf_nfntdfont I no long support this. OS/X doesn't support NFNTs so there's no point
1810
int WriteMacFamily(char *filename,struct sflist *sfs,enum fontformat format,
1811
enum bitmapformat bf,int flags, EncMap *map) {
1814
struct resourcetype resources[4];
1815
struct resource *rlist;
1816
struct macbinaryheader header;
1817
struct sflist *sfi, *sfsub;
1819
int freefilename = 0;
1822
struct sflistlist *sfsl, *sfli;
1824
if ( format==ff_pfbmacbin ) {
1825
for ( sfi=sfs; sfi!=NULL; sfi = sfi->next ) {
1827
MakeMacPSName(buffer,sfi->sf);
1829
strcat(buffer,".bin");
1831
tempname = galloc(strlen(filename)+strlen(buffer)+1);
1832
strcpy(tempname,filename);
1833
pt = strrchr(tempname,'/');
1834
if ( pt==NULL ) pt=tempname-1;
1835
strcpy(pt+1,buffer);
1836
if ( strcmp(tempname,filename)==0 ) {
1837
char *tf = galloc(strlen(filename)+20);
1838
strcpy(tf,filename);
1840
freefilename = true;
1841
pt = strrchr(filename,'.');
1842
if ( pt==NULL || pt<strrchr(filename,'/'))
1843
pt = filename+strlen(filename)+1;
1845
strcpy(pt-1,".fam");
1847
strcpy(pt-1,".fam.bin");
1850
if ( WriteMacPSFont(tempname,sfi->sf,format,flags,sfi->map)==0 )
1854
} else if ( format!=ff_none || bf==bf_sfnt_dfont ) {
1855
for ( sfi=sfs; sfi!=NULL; sfi = sfi->next ) {
1856
sfi->tempttf = tmpfile();
1857
if ( sfi->tempttf==NULL ||
1858
_WriteTTFFont(sfi->tempttf,sfi->sf,format==ff_none?ff_none:
1859
format==ff_ttfmacbin?ff_ttf:
1860
format-1,sfi->sizes,bf,flags,sfi->map)==0 ||
1861
ferror(sfi->tempttf) ) {
1862
for ( sfsub=sfs; sfsub!=sfi; sfsub=sfsub->next )
1863
fclose( sfsub->tempttf );
1866
rewind(sfi->tempttf);
1870
if ( __Mac && (format==ff_ttfmacbin || format==ff_pfbmacbin ||
1871
(format==ff_none && bf==bf_nfntmacbin)))
1874
res = fopen(filename,"wb+");
1876
for ( sfsub=sfs; sfsub!=NULL; sfsub=sfsub->next )
1877
fclose( sfsub->tempttf );
1881
if ( format==ff_ttfdfont || format==ff_otfdfont || format==ff_otfciddfont ||
1882
bf==bf_sfnt_dfont /*|| (format==ff_none && bf==bf_nfntdfont)*/)
1883
WriteDummyDFontHeaders(res);
1885
WriteDummyMacHeaders(res);
1886
memset(resources,'\0',sizeof(resources));
1888
id = HashToId(sfs->sf->fontname,sfs->sf,sfs->map);
1891
if ( format==ff_ttfmacbin || format==ff_ttfdfont || format==ff_otfdfont ||
1892
format==ff_otfciddfont || (format==ff_none && bf==bf_sfnt_dfont )) {
1893
resources[r].tag = CHR('s','f','n','t');
1894
for ( sfi=sfs, i=0; sfi!=NULL; sfi=sfi->next, ++i );
1895
resources[r].res = gcalloc(i+1,sizeof(struct resource));
1896
for ( sfi=sfs, i=0; sfi!=NULL; sfi=sfi->next, ++i ) {
1897
resources[r].res[i].pos = TTFToResource(res,sfi->tempttf);
1898
resources[r].res[i].id = sfi->id = id+i;
1899
resources[r].res[i].flags = 0x00; /* sfnts generally have resource flags 0x20 */
1900
fclose(sfi->tempttf);
1903
if ( bf==bf_ttf || bf==bf_sfnt_dfont ) {
1904
resources[r].tag = CHR('N','F','N','T');
1905
resources[r++].res = BuildDummyNFNTfamilyList(res,sfs,id);
1908
if ( bf==bf_nfntmacbin /*|| bf==bf_nfntdfont */) {
1909
resources[r].tag = CHR('N','F','N','T');
1910
resources[r++].res = SFsToNFNTs(res,sfs,id);
1913
sfsl = FondSplitter(sfs,&fondcnt);
1914
rlist = gcalloc(fondcnt+1,sizeof(struct resource));
1915
resources[r].tag = CHR('F','O','N','D');
1916
resources[r++].res = rlist;
1917
for ( i=0, sfli=sfsl; i<fondcnt && sfli!=NULL; ++i, sfli = sfli->next ) {
1918
rlist[i].pos = SFsToFOND(res,sfli->sfs,id,format,bf);
1919
rlist[i].flags = 0x00; /* I've seen FONDs with resource flags 0, 0x20, 0x60 */
1921
rlist[i].name = sfli->fondname;
1923
DumpResourceMap(res,resources,format!=ff_none?format:
1924
bf==bf_nfntmacbin?ff_ttfmacbin:ff_ttfdfont);
1925
SFListListFree(sfsl);
1926
for ( i=0; i<r; ++i )
1927
free(resources[i].res);
1930
if ( format==ff_ttfmacbin || format==ff_pfbmacbin ||
1931
(format==ff_none && bf==bf_nfntmacbin) ) {
1932
header.macfilename = NULL;
1933
header.binfilename = filename;
1934
/* Fontographer uses the old suitcase format for both bitmaps and ttf */
1935
header.type = CHR('F','F','I','L');
1936
header.creator = CHR('D','M','O','V');
1937
ret = DumpMacBinaryHeader(res,&header);
1939
if ( ferror(res) ) ret = false;
1940
if ( fclose(res)==-1 ) ret = 0;
1943
for ( sfi=sfs; sfi!=NULL; sfi=sfi->next ) {
1950
void SfListFree(struct sflist *sfs) {
1953
while ( sfs!=NULL ) {
1956
EncMapFree(sfs->map);
1957
chunkfree(sfs,sizeof(struct sflist));
1963
/* ******************************** Reading ********************************* */
1965
static SplineFont *SearchPostscriptResources(FILE *f,long rlistpos,int subcnt,long rdata_pos,
1966
long name_list, int flags) {
1967
long here = ftell(f);
1968
long *offsets, lenpos;
1969
int rname = -1, tmp;
1971
int len, type, i, j, rlen;
1972
unsigned short id, *rsrcids;
1973
/* I don't pretend to understand the rational behind the format of a */
1974
/* postscript font. It appears to be split up into chunks where the */
1975
/* maximum chunk size is 0x800, each section (ascii, binary, ascii, eof) */
1976
/* has its own set of chunks (ie chunks don't cross sections) */
1983
fseek(f,rlistpos,SEEK_SET);
1984
rsrcids = gcalloc(subcnt,sizeof(short));
1985
offsets = gcalloc(subcnt,sizeof(long));
1986
for ( i=0; i<subcnt; ++i ) {
1987
rsrcids[i] = getushort(f);
1988
tmp = (short) getushort(f);
1989
if ( rname==-1 ) rname = tmp;
1990
/* flags = */ getc(f);
1991
ch1 = getc(f); ch2 = getc(f);
1992
offsets[i] = rdata_pos+((ch1<<16)|(ch2<<8)|getc(f));
1993
/* mbz = */ getlong(f);
1998
LogError( _("Can't open temporary file for postscript output\n") );
1999
fseek(f,here,SEEK_SET );
2006
lenpos = ftell(pfb);
2013
for ( i=0; i<subcnt; ++i ) {
2014
for ( j=0; j<subcnt; ++j )
2015
if ( rsrcids[j]==id )
2017
if ( j == subcnt ) {
2018
LogError( _("Missing POST resource %u\n"), id );
2022
fseek(f,offsets[j],SEEK_SET);
2024
ch1 = getc(f); ch2 = getc(f);
2025
rlen -= 2; /* those two bytes don't count as real data */
2029
long hold = ftell(pfb);
2030
fseek(pfb,lenpos,SEEK_SET);
2032
putc((len>>16)&0xff,pfb);
2033
putc((len>>8)&0xff,pfb);
2035
fseek(pfb,hold,SEEK_SET);
2036
if ( ch1==5 ) /* end of font mark */
2040
lenpos = ftell(pfb);
2051
if ( max<0x800 ) max = 0x800;
2053
if ( buffer==NULL ) {
2054
LogError( _("Out of memory\n") );
2058
fread(buffer,1,rlen,f);
2059
fwrite(buffer,1,rlen,pfb);
2066
fseek(pfb,lenpos,SEEK_SET);
2068
putc((len>>16)&0xff,pfb);
2069
putc((len>>8)&0xff,pfb);
2071
fseek(f,here,SEEK_SET);
2073
if ( flags&ttf_onlynames )
2074
return( (SplineFont *) _NamesReadPostscript(pfb) ); /* This closes the font for us */
2076
fd = _ReadPSFont(pfb);
2079
sf = SplineFontFromPSFont(fd);
2081
/* There is no FOND in a postscript file, so we can't read any kerning*/
2087
static SplineFont *SearchTtfResources(FILE *f,long rlistpos,int subcnt,long rdata_pos,
2088
long name_list,char *filename,int flags,enum openflags openflags) {
2089
long here, start = ftell(f);
2093
int len, i, rlen, ilen;
2094
/* The sfnt resource is just a copy of the ttf file */
2102
char *chosenname=NULL;
2104
fseek(f,rlistpos,SEEK_SET);
2105
if ( subcnt>1 || (flags&ttf_onlynames) ) {
2106
names = gcalloc(subcnt+1,sizeof(char *));
2107
for ( i=0; i<subcnt; ++i ) {
2108
/* resource id = */ getushort(f);
2109
/* rname = (short) */ getushort(f);
2110
/* flags = */ getc(f);
2111
ch1 = getc(f); ch2 = getc(f);
2112
roff = rdata_pos+((ch1<<16)|(ch2<<8)|getc(f));
2113
/* mbz = */ getlong(f);
2115
names[i] = TTFGetFontName(f,roff+4,roff+4);
2116
if ( names[i]==NULL ) {
2118
sprintf( buffer, "Nameless%d", i );
2119
names[i] = copy(buffer);
2121
fseek(f,here,SEEK_SET);
2123
if ( flags&ttf_onlynames ) {
2124
return( (SplineFont *) names );
2126
if ((pt = strrchr(filename,'/'))==NULL ) pt = filename;
2127
if ( (lparen = strchr(pt,'('))!=NULL && strchr(lparen,')')!=NULL ) {
2128
char *find = copy(lparen+1);
2129
pt = strchr(find,')');
2130
if ( pt!=NULL ) *pt='\0';
2131
for ( which=subcnt-1; which>=0; --which )
2132
if ( strcmp(names[which],find)==0 )
2135
char *fn = copy(filename);
2136
fn[lparen-filename] = '\0';
2137
#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
2138
gwwv_post_error(_("Not in Collection"),_("%s is not in %.100s"),find,fn);
2143
#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
2144
} else if ( no_windowing_ui )
2147
which = gwwv_choose(_("Pick a font, any font..."),(const char **) names,subcnt,0,_("There are multiple fonts in this file, pick one"));
2151
#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
2152
if ( lparen==NULL && which!=-1 )
2153
chosenname = copy(names[which]);
2154
for ( i=0; i<subcnt; ++i )
2157
fseek(f,rlistpos,SEEK_SET);
2160
for ( i=0; i<subcnt; ++i ) {
2161
/* resource id = */ getushort(f);
2162
rname = (short) getushort(f);
2163
/* flags = */ getc(f);
2164
ch1 = getc(f); ch2 = getc(f);
2165
roff = rdata_pos+((ch1<<16)|(ch2<<8)|getc(f));
2166
/* mbz = */ getlong(f);
2173
LogError( _("Can't open temporary file for truetype output.\n") );
2177
fseek(f,roff,SEEK_SET);
2178
ilen = rlen = getlong(f);
2184
if ( max<0x800 ) max = 0x800;
2187
for ( len=0; len<rlen; ) {
2189
if ( rlen-len<ilen ) temp = rlen-len;
2190
temp = fread(buffer,1,temp,f);
2193
fwrite(buffer,1,temp,ttf);
2197
sf = _SFReadTTF(ttf,flags,openflags,NULL,NULL);
2201
fseek(f,start,SEEK_SET);
2202
if ( sf->chosenname==NULL ) sf->chosenname = chosenname;
2205
fseek(f,here,SEEK_SET);
2209
fseek(f,start,SEEK_SET);
2213
typedef struct fond {
2218
short size, style, id;
2220
/* size==0 => scalable */
2221
/* style>>8 is the bit depth (0=>1, 1=>2, 2=>4, 3=>8) */
2222
/* search order for ID is sfnt, NFNT, FONT */
2224
struct stylewidths {
2226
short *widthtab; /* 4.12 fixed number with the width specified as a fraction of an em */
2233
unsigned char ch1, ch2;
2234
short offset; /* 4.12 */
2246
short kernMax; /* bb learing */
2247
short Descent; /* maximum negative distance below baseline*/
2248
short fRectWidth; /* bounding box width */
2249
short fRectHeight; /* bounding box height */
2250
unsigned short *offsetWidths;/* offset to start of offset/width table */
2251
/* 0xffff => undefined, else high byte is offset in locTable, */
2252
/* low byte is width */
2256
short rowWords; /* shorts per row */
2257
unsigned short *fontImage; /* rowWords*fRectHeight */
2258
/* Images for all characters plus one extra for undefined */
2259
unsigned short *locs; /* lastchar-firstchar+3 words */
2260
/* Horizontal offset to start of n'th character. Note: applies */
2261
/* to each row. Missing characters have same loc as following */
2264
static void FondListFree(FOND *list) {
2268
while ( list!=NULL ) {
2271
for ( i=0; i<list->stylewidthcnt; ++i )
2272
free(list->stylewidths[i].widthtab);
2273
free(list->stylewidths);
2274
for ( i=0; i<list->stylekerncnt; ++i )
2275
free(list->stylekerns[i].kerns);
2276
free(list->stylekerns);
2277
for ( i=0; i<48; ++i )
2278
free(list->psnames[i]);
2284
/* There's probably only one fond in the file, but there could be more so be */
2286
/* I want the fond: */
2287
/* to get the fractional widths for the SWIDTH entry on bdf */
2288
/* to get the font name */
2289
/* to get the font association tables */
2290
/* to get the style flags */
2291
/* http://developer.apple.com/techpubs/mac/Text/Text-269.html */
2292
static FOND *BuildFondList(FILE *f,long rlistpos,int subcnt,long rdata_pos,
2293
long name_list,int flags) {
2294
long here, start = ftell(f);
2299
int i, j, k, cnt, isfixed;
2300
FOND *head=NULL, *cur;
2301
long widoff, kernoff, styleoff;
2303
fseek(f,rlistpos,SEEK_SET);
2304
for ( i=0; i<subcnt; ++i ) {
2305
/* resource id = */ getushort(f);
2306
rname = (short) getushort(f);
2307
/* flags = */ getc(f);
2308
ch1 = getc(f); ch2 = getc(f);
2309
offset = rdata_pos+((ch1<<16)|(ch2<<8)|getc(f));
2310
/* mbz = */ getlong(f);
2313
cur = gcalloc(1,sizeof(FOND));
2318
fseek(f,name_list+rname,SEEK_SET);
2320
fread(name,1,ch1,f);
2322
cur->fondname = copy(name);
2326
fseek(f,offset,SEEK_SET);
2327
isfixed = getushort(f)&0x8000?1:0;
2328
/* family id = */ getushort(f);
2329
cur->first = getushort(f);
2330
cur->last = getushort(f);
2331
/* on a 1 point font... */
2332
/* ascent = */ getushort(f);
2333
/* descent = */ getushort(f);
2334
/* leading = */ getushort(f);
2335
/* widmax = */ getushort(f);
2336
if ( (widoff = getlong(f))!=0 ) widoff += offset;
2337
if ( (kernoff = getlong(f))!=0 ) kernoff += offset;
2338
if ( (styleoff = getlong(f))!=0 ) styleoff += offset;
2339
for ( j=0; j<9; ++j )
2341
/* internal & undefined, for international scripts = */ getlong(f);
2342
/* version = */ getushort(f);
2343
cur->assoc_cnt = getushort(f)+1;
2344
cur->assoc = gcalloc(cur->assoc_cnt,sizeof(struct assoc));
2345
for ( j=0; j<cur->assoc_cnt; ++j ) {
2346
cur->assoc[j].size = getushort(f);
2347
cur->assoc[j].style = getushort(f);
2348
cur->assoc[j].id = getushort(f);
2351
fseek(f,widoff,SEEK_SET);
2352
cnt = getushort(f)+1;
2353
cur->stylewidthcnt = cnt;
2354
cur->stylewidths = gcalloc(cnt,sizeof(struct stylewidths));
2355
for ( j=0; j<cnt; ++j ) {
2356
cur->stylewidths[j].style = getushort(f);
2357
cur->stylewidths[j].widthtab = galloc((cur->last-cur->first+3)*sizeof(short));
2358
for ( k=cur->first; k<=cur->last+2; ++k )
2359
cur->stylewidths[j].widthtab[k] = getushort(f);
2362
if ( kernoff!=0 && (flags&ttf_onlykerns) ) {
2363
fseek(f,kernoff,SEEK_SET);
2364
cnt = getushort(f)+1;
2365
cur->stylekerncnt = cnt;
2366
cur->stylekerns = gcalloc(cnt,sizeof(struct stylekerns));
2367
for ( j=0; j<cnt; ++j ) {
2368
cur->stylekerns[j].style = getushort(f);
2369
cur->stylekerns[j].kernpairs = getushort(f);
2370
cur->stylekerns[j].kerns = galloc(cur->stylekerns[j].kernpairs*sizeof(struct kerns));
2371
for ( k=0; k<cur->stylekerns[j].kernpairs; ++k ) {
2372
cur->stylekerns[j].kerns[k].ch1 = getc(f);
2373
cur->stylekerns[j].kerns[k].ch2 = getc(f);
2374
cur->stylekerns[j].kerns[k].offset = getushort(f);
2378
if ( styleoff!=0 ) {
2379
uint8 stringoffsets[48];
2380
int strcnt, stringlen, format;
2381
char **strings, *pt;
2382
fseek(f,styleoff,SEEK_SET);
2383
/* class = */ getushort(f);
2384
/* glyph encoding offset = */ getlong(f);
2385
/* reserved = */ getlong(f);
2386
for ( j=0; j<48; ++j )
2387
stringoffsets[j] = getc(f);
2388
strcnt = getushort(f);
2389
strings = galloc(strcnt*sizeof(char *));
2390
for ( j=0; j<strcnt; ++j ) {
2391
stringlen = getc(f);
2392
strings[j] = galloc(stringlen+2);
2393
strings[j][0] = stringlen;
2394
strings[j][stringlen+1] = '\0';
2395
for ( k=0; k<stringlen; ++k )
2396
strings[j][k+1] = getc(f);
2398
for ( j=0; j<48; ++j ) {
2399
for ( k=j-1; k>=0; --k )
2400
if ( stringoffsets[j]==stringoffsets[k] )
2403
continue; /* this style doesn't exist */
2404
format = stringoffsets[j]-1;
2405
stringlen = strings[0][0];
2407
for ( k=0; k<strings[format][0]; ++k )
2408
stringlen += strings[ strings[format][k+1]-1 ][0];
2409
pt = cur->psnames[j] = galloc(stringlen+1);
2410
strcpy(pt,strings[ 0 ]+1);
2411
pt += strings[ 0 ][0];
2413
for ( k=0; k<strings[format][0]; ++k ) {
2414
strcpy(pt,strings[ strings[format][k+1]-1 ]+1);
2415
pt += strings[ strings[format][k+1]-1 ][0];
2419
for ( j=0; j<strcnt; ++j )
2423
fseek(f,here,SEEK_SET);
2425
fseek(f,start,SEEK_SET);
2429
static BDFChar *NFNTCvtBitmap(struct MacFontRec *font,int index,SplineFont *sf,int gid) {
2431
int i,j, bits, bite, bit;
2433
bdfc = chunkalloc(sizeof(BDFChar));
2434
bdfc->xmin = (font->offsetWidths[index]>>8)+font->kernMax;
2435
bdfc->xmax = bdfc->xmin + font->locs[index+1]-font->locs[index]-1;
2436
if ( bdfc->xmax<bdfc->xmin )
2437
bdfc->xmax = bdfc->xmin; /* Empty glyph mark */
2438
bdfc->ymin = -font->descent;
2439
bdfc->ymax = font->ascent-1;
2440
bdfc->width = font->offsetWidths[index]&0xff;
2441
bdfc->vwidth = font->ascent + font->descent;
2442
bdfc->bytes_per_line = ((bdfc->xmax-bdfc->xmin)>>3) + 1;
2443
bdfc->bitmap = gcalloc(bdfc->bytes_per_line*font->fRectHeight,sizeof(uint8));
2444
bdfc->orig_pos = gid;
2445
bdfc->sc = sf->glyphs[gid];
2447
bits = font->locs[index]; bite = font->locs[index+1];
2448
for ( i=0; i<font->fRectHeight; ++i ) {
2449
uint16 *test = font->fontImage + i*font->rowWords;
2450
uint8 *bpt = bdfc->bitmap + i*bdfc->bytes_per_line;
2451
for ( bit=bits, j=0; bit<bite; ++bit, ++j ) {
2452
if ( test[bit>>4]&(0x8000>>(bit&0xf)) )
2453
bpt[j>>3] |= (0x80>>(j&7));
2456
BCCompressBitmap(bdfc);
2460
static void LoadNFNT(FILE *f,long offset, SplineFont *sf, int size) {
2461
long here = ftell(f);
2465
struct MacFontRec font;
2469
offset += 4; /* skip over the length */
2470
fseek(f,offset,SEEK_SET);
2471
memset(&font,'\0',sizeof(struct MacFontRec));
2472
font.fontType = getushort(f);
2473
font.firstChar = getushort(f);
2474
font.lastChar = getushort(f);
2475
font.widthMax = getushort(f);
2476
font.kernMax = (short) getushort(f);
2477
font.Descent = (short) getushort(f);
2478
font.fRectWidth = getushort(f);
2479
font.fRectHeight = getushort(f);
2482
font.ascent = getushort(f);
2483
font.descent = getushort(f);
2484
if ( font.Descent>=0 ) {
2485
ow |= (font.Descent<<16);
2486
font.Descent = -font.descent; /* Possibly overkill, but should be safe */
2488
font.leading = getushort(f);
2489
font.rowWords = getushort(f);
2490
if ( font.rowWords!=0 ) {
2491
font.fontImage = gcalloc(font.rowWords*font.fRectHeight,sizeof(short));
2492
font.locs = gcalloc(font.lastChar-font.firstChar+3,sizeof(short));
2493
font.offsetWidths = gcalloc(font.lastChar-font.firstChar+3,sizeof(short));
2494
for ( i=0; i<font.rowWords*font.fRectHeight; ++i )
2495
font.fontImage[i] = getushort(f);
2496
for ( i=0; i<font.lastChar-font.firstChar+3; ++i )
2497
font.locs[i] = getushort(f);
2498
fseek(f,baseow+2*ow,SEEK_SET);
2499
for ( i=0; i<font.lastChar-font.firstChar+3; ++i )
2500
font.offsetWidths[i] = getushort(f);
2502
fseek(f,here,SEEK_SET);
2503
if ( font.rowWords==0 )
2506
/* Now convert the FONT record to one of my BDF structs */
2507
bdf = gcalloc(1,sizeof(BDFFont));
2509
bdf->next = sf->bitmaps;
2511
bdf->glyphcnt = bdf->glyphmax = sf->glyphcnt;
2512
bdf->pixelsize = font.ascent+font.descent;
2513
bdf->glyphs = gcalloc(sf->glyphcnt,sizeof(BDFChar *));
2514
bdf->ascent = font.ascent;
2515
bdf->descent = font.descent;
2517
for ( i=font.firstChar; i<=font.lastChar+1; ++i ) {
2518
if ( i!=font.lastChar+1 )
2519
sc = SFMakeChar(sf,sf->map,i);
2521
sc = SFGetChar(sf,-1,".notdef");
2526
bdf->glyphs[gid] = NFNTCvtBitmap(&font,i-font.firstChar,sf,gid);
2527
if ( !sf->glyphs[gid]->widthset ) {
2528
sf->glyphs[gid]->width = bdf->glyphs[gid]->width*(sf->ascent+sf->descent)/bdf->pixelsize;
2529
sf->glyphs[gid]->widthset = true;
2533
free(font.fontImage);
2535
free(font.offsetWidths);
2538
static char *BuildName(char *family,int style) {
2541
strncpy(buffer,family,200);
2544
if ( style&sf_bold )
2545
strcat(buffer,"Bold");
2546
if ( style&sf_italic )
2547
strcat(buffer,"Italic");
2548
if ( style&sf_underline )
2549
strcat(buffer,"Underline");
2550
if ( style&sf_outline )
2551
strcat(buffer,"Outline");
2552
if ( style&sf_shadow )
2553
strcat(buffer,"Shadow");
2554
if ( style&sf_condense )
2555
strcat(buffer,"Condensed");
2556
if ( style&sf_extend )
2557
strcat(buffer,"Extended");
2558
return( copy(buffer));
2561
static int GuessStyle(char *fontname,int *styles,int style_cnt) {
2563
char *stylenames = _GetModifiers(fontname,NULL,NULL);
2565
style = _MacStyleCode(stylenames,NULL,NULL);
2566
for ( which = style_cnt; which>=0; --which )
2567
if ( styles[which] == style )
2573
static FOND *PickFOND(FOND *fondlist,char *filename,char **name, int *style) {
2576
uint8 stylesused[96];
2580
FOND **fonds = NULL, *fond = NULL;
2584
if ((pt = strrchr(filename,'/'))!=NULL ) pt = filename;
2585
if ( (lparen = strchr(filename,'('))!=NULL && strchr(lparen,')')!=NULL ) {
2586
find = copy(lparen+1);
2587
pt = strchr(find,')');
2588
if ( pt!=NULL ) *pt='\0';
2589
for ( test=fondlist; test!=NULL; test=test->next ) {
2590
for ( i=0; i<48; ++i )
2591
if ( test->psnames[i]!=NULL && strcmp(find,test->psnames[i])==0 ) {
2592
*style = (i&3) | ((i&~3)<<1); /* PS styles skip underline bit */
2593
*name = copy(test->psnames[i]);
2599
/* The file may contain multiple families, and each family may contain */
2600
/* multiple styles (and each style may contain multiple sizes, but that's */
2601
/* not an issue for us here) */
2603
for ( i=0; i<2; ++i ) {
2605
for ( test=fondlist; test!=NULL; test=test->next ) if ( test->fondname!=NULL ) {
2606
memset(stylesused,0,sizeof(stylesused));
2607
for ( j=0; j<test->assoc_cnt; ++j ) {
2608
if ( test->assoc[j].size!=0 && !stylesused[test->assoc[j].style]) {
2609
stylesused[test->assoc[j].style]=true;
2610
if ( names!=NULL ) {
2611
names[cnt] = BuildName(test->fondname,test->assoc[j].style);
2612
styles[cnt] = test->assoc[j].style;
2619
if ( names==NULL ) {
2620
names = gcalloc(cnt+1,sizeof(char *));
2621
fonds = galloc(cnt*sizeof(FOND *));
2622
styles = galloc(cnt*sizeof(int));
2627
for ( which=cnt-1; which>=0; --which )
2628
if ( strcmp(names[which],find)==0 )
2630
if ( which==-1 && strstrmatch(find,test->fondname)!=NULL )
2631
which = GuessStyle(find,styles,cnt);
2633
char *fn = copy(filename);
2634
fn[lparen-filename] = '\0';
2635
#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
2636
gwwv_post_error(_("Not in Collection"),_("%s is not in %.100s"),find,fn);
2641
} else if ( cnt==1 )
2643
#if !defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
2644
else if ( no_windowing_ui )
2647
which = gwwv_choose(_("Pick a font, any font..."),(const char **) names,cnt,0,
2648
_("There are multiple fonts in this file, pick one"));
2649
#elif defined(FONTFORGE_CONFIG_NO_WINDOWING_UI)
2652
#endif /* FONTFORGE_CONFIG_NO_WINDOWING_UI */
2655
fond = fonds[which];
2656
*name = copy(names[which]);
2657
*style = styles[which];
2659
for ( i=0; i<cnt; ++i )
2661
free(names); free(fonds); free(styles);
2668
static SplineFont *SearchBitmapResources(FILE *f,long rlistpos,int subcnt,long rdata_pos,
2669
long name_list,char *filename,FOND *fondlist,int flags) {
2670
long start = ftell(f);
2683
fond = PickFOND(fondlist,filename,&name,&style);
2688
if ( flags&ttf_onlyonestrike ) {
2690
for ( i=0; i<fond->assoc_cnt; ++i ) {
2691
if ( fond->assoc[i].style==style && fond->assoc[i].size>biggest ) {
2692
biggest = fond->assoc[i].size;
2693
find_id = fond->assoc[i].id;
2698
sf = SplineFontBlank(257);
2699
free(sf->fontname); sf->fontname = name;
2700
free(sf->familyname); sf->familyname = copy(fond->fondname);
2701
sf->fondname = copy(fond->fondname);
2702
free(sf->fullname); sf->fullname = copy(name);
2703
free(sf->origname); sf->origname = NULL;
2704
if ( style & sf_bold ) {
2705
free(sf->weight); sf->weight = copy("Bold");
2707
free(sf->copyright); sf->copyright = NULL;
2708
free(sf->comments); sf->comments = NULL;
2710
sf->map = EncMapNew(257,257,FindOrMakeEncoding("mac"));
2712
for ( i=0; i<fond->stylewidthcnt; ++i ) {
2713
if ( fond->stylewidths[i].style == style ) {
2714
short *widths = fond->stylewidths[i].widthtab;
2715
for ( j=fond->first; j<=fond->last; ++j ) {
2716
sc = SFMakeChar(sf,sf->map,j);
2717
sc->width = ((widths[j-fond->first]*1000L+(1<<11))>>12);
2718
sc->widthset = true;
2720
sc = SplineCharCreate();
2722
sc->orig_pos = sf->glyphcnt;
2723
sf->glyphs[sf->glyphcnt++] = sc;
2724
sc->name = copy(".notdef");
2725
sc->width = (widths[fond->last+1-fond->first]*1000L+(1<<11))>>12;
2726
sc->widthset = true;
2730
fseek(f,rlistpos,SEEK_SET);
2731
for ( i=0; i<subcnt; ++i ) {
2732
res_id = getushort(f);
2733
rname = (short) getushort(f);
2734
/* flags = */ getc(f);
2735
ch1 = getc(f); ch2 = getc(f);
2736
roff = rdata_pos+((ch1<<16)|(ch2<<8)|getc(f));
2737
/* mbz = */ getlong(f);
2738
for ( j=fond->assoc_cnt-1; j>=0; --j )
2739
if ( (find_id!=-1 && res_id==find_id) ||
2740
( fond->assoc[j].style==style && fond->assoc[j].id==res_id &&
2741
fond->assoc[j].size!=0 ) )
2742
LoadNFNT(f,roff,sf,fond->assoc[j].size);
2744
fseek(f,start,SEEK_SET);
2746
sf->onlybitmaps = true;
2747
SFOrderBitmapList(sf);
2751
/* Look for kerning info and merge it into the currently existing font "into" */
2752
static SplineFont *FindFamilyStyleKerns(SplineFont *into,EncMap *map,FOND *fondlist,char *filename) {
2757
int ch1, ch2, offset;
2759
SplineChar *sc1, *sc2;
2761
fond = PickFOND(fondlist,filename,&name,&style);
2762
if ( fond==NULL || into==NULL )
2764
for ( i=0; i<fond->stylekerncnt; ++i )
2765
if ( fond->stylekerns[i].style==style )
2767
if ( i==fond->stylekerncnt ) {
2768
LogError(_("No kerning table for %s\n"), name );
2772
for ( j=0; j<fond->stylekerns[i].kernpairs; ++j ) {
2773
ch1 = fond->stylekerns[i].kerns[j].ch1;
2774
ch2 = fond->stylekerns[i].kerns[j].ch2;
2775
offset = (fond->stylekerns[i].kerns[j].offset*(into->ascent+into->descent)+(1<<11))>>12;
2776
sc1 = SFMakeChar(into,map,ch1);
2777
sc2 = SFMakeChar(into,map,ch2);
2778
for ( kp=sc1->kerns; kp!=NULL; kp=kp->next )
2783
kp = chunkalloc(sizeof(KernPair));
2785
kp->next = sc1->kerns;
2787
script = SCScriptFromUnicode(sc1);
2788
if ( script==DEFAULT_SCRIPT )
2789
script = SCScriptFromUnicode(sc2);
2790
kp->subtable = SFSubTableFindOrMake(sc1->parent,CHR('k','e','r','n'),
2798
/* Look for a bare truetype font in a binhex/macbinary wrapper */
2799
static SplineFont *MightBeTrueType(FILE *binary,int32 pos,int32 dlen,int flags,
2800
enum openflags openflags) {
2801
FILE *temp = tmpfile();
2802
char *buffer = galloc(8192);
2806
if ( flags&ttf_onlynames ) {
2808
char *temp = TTFGetFontName(binary,pos,pos);
2811
ret = galloc(2*sizeof(char *));
2814
return( (SplineFont *) ret );
2817
fseek(binary,pos,SEEK_SET);
2819
len = dlen > 8192 ? 8192 : dlen;
2820
len = fread(buffer,1,dlen > 8192 ? 8192 : dlen,binary);
2823
fwrite(buffer,1,len,temp);
2827
sf = _SFReadTTF(temp,flags,openflags,NULL,NULL);
2833
static SplineFont *IsResourceFork(FILE *f, long offset,char *filename,int flags,
2834
enum openflags openflags, SplineFont *into,EncMap *map) {
2835
/* If it is a good resource fork then the first 16 bytes are repeated */
2836
/* at the location specified in bytes 4-7 */
2837
/* We include an offset because if we are looking at a mac binary file */
2838
/* the resource fork will actually start somewhere in the middle of the */
2839
/* file, not at the beginning */
2840
unsigned char buffer[16], buffer2[16];
2841
long rdata_pos, map_pos, type_list, name_list, rpos;
2842
int32 rdata_len, map_len;
2844
int i, cnt, subcnt, nfnt_subcnt=0, font_subcnt=0, fond_subcnt=0;
2846
uint32 nfnt_pos=0, font_pos=0, fond_pos=0;
2847
FOND *fondlist=NULL;
2849
fseek(f,offset,SEEK_SET);
2850
if ( fread(buffer,1,16,f)!=16 )
2852
rdata_pos = offset + ((buffer[0]<<24)|(buffer[1]<<16)|(buffer[2]<<8)|buffer[3]);
2853
map_pos = offset + ((buffer[4]<<24)|(buffer[5]<<16)|(buffer[6]<<8)|buffer[7]);
2854
rdata_len = ((buffer[8]<<24)|(buffer[9]<<16)|(buffer[10]<<8)|buffer[11]);
2855
map_len = ((buffer[12]<<24)|(buffer[13]<<16)|(buffer[14]<<8)|buffer[15]);
2856
if ( rdata_pos+rdata_len!=map_pos || rdata_len==0 )
2858
fseek(f,map_pos,SEEK_SET);
2859
buffer2[15] = buffer[15]+1; /* make it be different */
2860
if ( fread(buffer2,1,16,f)!=16 )
2863
/* Apple's data fork resources appear to have a bunch of zeroes here instead */
2864
/* of a copy of the first 16 bytes */
2865
for ( i=0; i<16; ++i )
2866
if ( buffer2[i]!=0 )
2869
for ( i=0; i<16; ++i )
2870
if ( buffer[i]!=buffer2[i] )
2873
getlong(f); /* skip the handle to the next resource map */
2874
getushort(f); /* skip the file resource number */
2875
getushort(f); /* skip the attributes */
2876
type_list = map_pos + getushort(f);
2877
name_list = map_pos + getushort(f);
2879
fseek(f,type_list,SEEK_SET);
2880
cnt = getushort(f)+1;
2881
for ( i=0; i<cnt; ++i ) {
2883
/* printf( "%c%c%c%c\n", tag>>24, (tag>>16)&0xff, (tag>>8)&0xff, tag&0xff );*/
2884
subcnt = getushort(f)+1;
2885
rpos = type_list+getushort(f);
2887
if ( tag==CHR('P','O','S','T') && !(flags&(ttf_onlystrikes|ttf_onlykerns))) /* No FOND */
2888
sf = SearchPostscriptResources(f,rpos,subcnt,rdata_pos,name_list,flags);
2889
else if ( tag==CHR('s','f','n','t') && !(flags&ttf_onlykerns))
2890
sf = SearchTtfResources(f,rpos,subcnt,rdata_pos,name_list,filename,flags,openflags);
2891
else if ( tag==CHR('N','F','N','T') ) {
2893
nfnt_subcnt = subcnt;
2894
} else if ( tag==CHR('F','O','N','T') ) {
2896
font_subcnt = subcnt;
2897
} else if ( tag==CHR('F','O','N','D') ) {
2899
fond_subcnt = subcnt;
2904
if ( flags&ttf_onlynames ) /* Not interested in bitmap resources here */
2907
if ( flags&ttf_onlykerns ) { /* For kerns */
2908
if ( fond_subcnt!=0 )
2909
fondlist = BuildFondList(f,fond_pos,fond_subcnt,rdata_pos,name_list,flags);
2910
into = FindFamilyStyleKerns(into,map,fondlist,filename);
2911
FondListFree(fondlist);
2914
/* Ok. If no outline font, try for a bitmap */
2915
if ( nfnt_subcnt==0 ) {
2916
nfnt_pos = font_pos;
2917
nfnt_subcnt = font_subcnt;
2919
if ( nfnt_subcnt!=0 ) {
2920
if ( fond_subcnt!=0 )
2921
fondlist = BuildFondList(f,fond_pos,fond_subcnt,rdata_pos,name_list,flags);
2922
sf = SearchBitmapResources(f,nfnt_pos,nfnt_subcnt,rdata_pos,name_list,
2923
filename,fondlist,flags);
2924
FondListFree(fondlist);
2928
return( (SplineFont *) -1 ); /* It's a valid resource file, but just has no fonts */
2932
static SplineFont *HasResourceFork(char *filename,int flags,enum openflags openflags,
2933
SplineFont *into,EncMap *map) {
2934
/* If we're on a mac, we can try to see if we've got a real resource fork */
2935
/* (if we do, copy it into a temporary data file and then manipulate that)*/
2938
char *tempfn=filename, *pt, *lparen, *respath;
2940
if (( pt=strrchr(filename,'/'))==NULL ) pt = filename;
2941
if ( (lparen = strchr(pt,'('))!=NULL && strchr(lparen,')')!=NULL ) {
2942
tempfn = copy(filename);
2943
tempfn[lparen-filename] = '\0';
2945
respath = galloc(strlen(tempfn)+strlen("/rsrc")+1);
2946
strcpy(respath,tempfn);
2947
strcat(respath,"/rsrc");
2948
resfork = fopen(respath,"r");
2950
if ( tempfn!=filename )
2952
if ( resfork==NULL )
2954
ret = IsResourceFork(resfork,0,filename,flags,openflags,into,map);
2960
static SplineFont *IsResourceInBinary(FILE *f,char *filename,int flags,
2961
enum openflags openflags, SplineFont *into,EncMap *map) {
2962
unsigned char header[128];
2963
unsigned long offset, dlen, rlen;
2965
if ( fread(header,1,128,f)!=128 )
2967
if ( header[0]!=0 || header[74]!=0 || header[82]!=0 || header[1]<=0 ||
2968
header[1]>33 || header[63]!=0 || header[2+header[1]]!=0 )
2970
dlen = ((header[0x53]<<24)|(header[0x54]<<16)|(header[0x55]<<8)|header[0x56]);
2971
rlen = ((header[0x57]<<24)|(header[0x58]<<16)|(header[0x59]<<8)|header[0x5a]);
2972
/* 128 bytes for header, then the dlen is padded to a 128 byte boundary */
2973
offset = 128 + ((dlen+127)&~127);
2974
/* Look for a bare truetype font in a binhex/macbinary wrapper */
2975
if ( dlen!=0 && rlen<=dlen) {
2977
fread(header,1,4,f);
2979
if ( strcmp((char *) header,"OTTO")==0 || strcmp((char *) header,"true")==0 ||
2980
strcmp((char *) header,"ttcf")==0 ||
2981
(header[0]==0 && header[1]==1 && header[2]==0 && header[3]==0))
2982
return( MightBeTrueType(f,pos,dlen,flags,openflags));
2984
return( IsResourceFork(f,offset,filename,flags,openflags,into,map));
2987
static int lastch=0, repeat = 0;
2988
static void outchr(FILE *binary, int ch) {
2993
/* no repeat, output a literal 0x90 (the repeat flag) */
2995
putc(lastch,binary);
2997
for ( i=1; i<ch; ++i )
2998
putc(lastch,binary);
3001
} else if ( ch==0x90 ) {
3009
static SplineFont *IsResourceInHex(FILE *f,char *filename,int flags,enum openflags openflags,
3010
SplineFont *into,EncMap *map) {
3011
/* convert file from 6bit to 8bit */
3012
/* interesting data is enclosed between two colons */
3013
FILE *binary = tmpfile();
3014
char *sixbit = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
3015
int ch, val, cnt, i, dlen, rlen;
3016
unsigned char header[20]; char *pt;
3019
if ( binary==NULL ) {
3020
LogError( _("can't create temporary file\n") );
3024
lastch = repeat = 0;
3025
while ( (ch=getc(f))!=':' ); /* There may be comments before file start */
3027
while ( (ch=getc(f))!=':' ) {
3030
for ( pt=sixbit; *pt!=ch && *pt!='\0'; ++pt );
3035
val = (val<<6) | (pt-sixbit);
3037
outchr(binary,(val>>16)&0xff);
3038
outchr(binary,(val>>8)&0xff);
3039
outchr(binary,val&0xff);
3045
outchr(binary,val<<2);
3046
else if ( cnt==2 ) {
3048
outchr(binary,(val>>8)&0xff);
3049
outchr(binary,val&0xff);
3050
} else if ( cnt==3 ) {
3052
outchr(binary,(val>>16)&0xff);
3053
outchr(binary,(val>>8)&0xff);
3054
outchr(binary,val&0xff);
3059
ch = getc(binary); /* Name length */
3061
for ( i=0; i<ch; ++i )
3063
if ( getc(binary)!='\0' ) {
3067
fread(header,1,20,binary);
3068
dlen = (header[10]<<24)|(header[11]<<16)|(header[12]<<8)|header[13];
3069
rlen = (header[14]<<24)|(header[15]<<16)|(header[16]<<8)|header[17];
3070
/* Look for a bare truetype font in a binhex/macbinary wrapper */
3071
if ( dlen!=0 && rlen<dlen ) {
3072
int pos = ftell(binary);
3073
fread(header,1,4,binary);
3075
if ( strcmp((char *) header,"OTTO")==0 || strcmp((char *) header,"true")==0 ||
3076
strcmp((char *) header,"ttcf")==0 ||
3077
(header[0]==0 && header[1]==1 && header[2]==0 && header[3]==0)) {
3078
ret = MightBeTrueType(binary,pos,dlen,flags,openflags);
3088
ret = IsResourceFork(binary,ftell(binary)+dlen+2,filename,flags,openflags,into,map);
3094
static SplineFont *IsResourceInFile(char *filename,int flags,enum openflags openflags,
3095
SplineFont *into, EncMap *map) {
3099
char *temp=filename, *lparen;
3101
if (( pt=strrchr(filename,'/'))==NULL ) pt = filename;
3102
if ( (lparen = strchr(pt,'('))!=NULL && strchr(lparen,')')!=NULL ) {
3103
temp = copy(filename);
3104
temp[lparen-filename] = '\0';
3106
f = fopen(temp,"rb");
3107
if ( temp!=filename ) free(temp);
3110
spt = strrchr(filename,'/');
3111
if ( spt==NULL ) spt = filename;
3112
pt = strrchr(spt,'.');
3113
if ( pt!=NULL && (pt[1]=='b' || pt[1]=='B') && (pt[2]=='i' || pt[2]=='I') &&
3114
(pt[3]=='n' || pt[3]=='N') && (pt[4]=='\0' || pt[4]=='(') ) {
3115
if ( (sf = IsResourceInBinary(f,filename,flags,openflags,into,map))) {
3119
} else if ( pt!=NULL && (pt[1]=='h' || pt[1]=='H') && (pt[2]=='q' || pt[2]=='Q') &&
3120
(pt[3]=='x' || pt[3]=='X') && (pt[4]=='\0' || pt[4]=='(')) {
3121
if ( (sf = IsResourceInHex(f,filename,flags,openflags,into,map))) {
3127
sf = IsResourceFork(f,0,filename,flags,openflags,into,map);
3131
sf = HasResourceFork(filename,flags,openflags,into,map);
3136
static SplineFont *FindResourceFile(char *filename,int flags,enum openflags openflags,
3137
SplineFont *into,EncMap *map) {
3138
char *spt, *pt, *dpt;
3142
if ( (sf = IsResourceInFile(filename,flags,openflags,into,map)))
3145
/* Well, look in the resource fork directory (if it exists), the resource */
3146
/* fork is placed there in a seperate file on (some) non-Mac disks */
3147
strcpy(buffer,filename);
3148
spt = strrchr(buffer,'/');
3149
if ( spt==NULL ) { spt = buffer; pt = filename; }
3150
else { ++spt; pt = filename + (spt-buffer); }
3151
strcpy(spt,"resource.frk/");
3153
if ( (sf=IsResourceInFile(buffer,flags,openflags,into,map)))
3156
/* however the resource fork does not appear to do long names properly */
3157
/* names are always lower case 8.3, do some simple things to check */
3158
spt = strrchr(buffer,'/')+1;
3159
for ( pt=spt; *pt; ++pt )
3160
if ( Isupper( *pt ))
3161
*pt = Tolower( *pt );
3162
dpt = strchr(spt,'.');
3163
if ( dpt==NULL ) dpt = spt+strlen(spt);
3164
if ( dpt-spt>8 || strlen(dpt)>4 ) {
3166
strncpy(exten,dpt,7);
3167
exten[4] = '\0'; /* it includes the dot */
3174
return( IsResourceInFile(buffer,flags,openflags,into,map));
3177
SplineFont *SFReadMacBinary(char *filename,int flags,enum openflags openflags) {
3178
SplineFont *sf = FindResourceFile(filename,flags,openflags,NULL,NULL);
3181
LogError( _("Couldn't find a font file named %s\n"), filename );
3182
else if ( sf==(SplineFont *) (-1) ) {
3183
LogError( _("%s is a mac resource file but contains no postscript or truetype fonts\n"), filename );
3190
SplineFont *SFReadMacBinaryInfo(char *filename,int flags,enum openflags openflags) {
3191
SplineFont *sf = FindResourceFile(filename,flags,openflags,NULL,NULL);
3194
LogError( _("Couldn't find a font file named %s\n"), filename );
3195
else if ( sf==(SplineFont *) (-1) ) {
3196
LogError( _("%s is a mac resource file but contains no postscript or truetype fonts\n"), filename );
3203
int LoadKerningDataFromMacFOND(SplineFont *sf, char *filename,EncMap *map) {
3204
if ( FindResourceFile(filename,ttf_onlykerns,0,sf,map)==NULL )
3210
char **NamesReadMacBinary(char *filename) {
3211
return( (char **) FindResourceFile(filename,ttf_onlynames,0,NULL,NULL));