1 /* Copyright (C) 2000-2012 by George Williams */
2 /*
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions are met:
5 
6  * Redistributions of source code must retain the above copyright notice, this
7  * list of conditions and the following disclaimer.
8 
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.
12 
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.
15 
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.
26  */
27 
28 #include <fontforge-config.h>
29 
30 #include "fvimportbdf.h"
31 
32 #include "bitmapchar.h"
33 #include "bvedit.h"
34 #include "chardata.h"
35 #include "cvimages.h"
36 #include "encoding.h"
37 #include "fontforgevw.h"
38 #include "fvfonts.h"
39 #include "gfile.h"
40 #include "macbinary.h"
41 #include "mem.h"
42 #include "namelist.h"
43 #include "palmfonts.h"
44 #include "parsettf.h"
45 #include "splinefill.h"
46 #include "splineutil.h"
47 #include "splineutil2.h"
48 #include "ustring.h"
49 #include "utype.h"
50 #include "winfonts.h"
51 
52 #include <math.h>
53 #include <unistd.h>
54 
cleancopy(const char * name)55 static char *cleancopy(const char *name) {
56     const char *fpt;
57     char *temp, *tpt;
58     char buf[200];
59 
60     fpt=name;
61     /* Look for some common cases */
62     /* Often bdf fonts name their glyphs things like "%" or "90". Neither is */
63     /*  a good postscript name, so do something reasonable here */
64     if ( !isalpha(*(unsigned char *) fpt) && fpt[0]>=' ' && /* fpt[0]<=0x7f &&*/
65 	    fpt[1]=='\0' )
66 return( copy( StdGlyphName(buf,*(unsigned char *) fpt,ui_none,(NameList *) -1)) );
67     tpt = temp = malloc(strlen(name)+2);
68     if ( isdigit(*fpt))
69 	*tpt++ = '$';
70     for ( ; *fpt; ++fpt ) {
71 	if ( *fpt>' ' && *fpt<127 &&
72 		*fpt!='(' &&
73 		*fpt!=')' &&
74 		*fpt!='[' &&
75 		*fpt!=']' &&
76 		*fpt!='{' &&
77 		*fpt!='}' &&
78 		*fpt!='<' &&
79 		*fpt!='>' &&
80 		*fpt!='/' &&
81 		*fpt!='%' )
82 	    *tpt++ = *fpt;
83     }
84     *tpt = '\0';
85 
86     if ( *name=='\0' ) {
87 	char buffer[20];
88 	static int unique = 0;
89 	sprintf( buffer, "$u%d", ++unique );
90 	free(temp);
91 return( copy( buffer ));
92     }
93 
94     if ( temp!=NULL )
95 return( temp );
96 
97 return( copy(name));
98 }
99 
100 /* The pcf code is adapted from... */
101 /*
102 
103 Copyright 1991, 1998  The Open Group
104 
105 All Rights Reserved.
106 
107 The above copyright notice and this permission notice shall be included
108 in all copies or substantial portions of the Software.
109 
110 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
111 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
112 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
113 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
114 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
115 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
116 OTHER DEALINGS IN THE SOFTWARE.
117 
118 Except as contained in this notice, the name of The Open Group shall
119 not be used in advertising or otherwise to promote the sale, use or
120 other dealings in this Software without prior written authorization
121 from The Open Group.
122 
123 */
124 
125 /*
126  * Author:  Keith Packard, MIT X Consortium
127  */
128 
129 /* ************************************************************************** */
SFDefaultAscent(SplineFont * sf)130 void SFDefaultAscent(SplineFont *sf) {
131     if ( sf->onlybitmaps ) {
132 	double scaled_sum=0, cnt=0;
133 	int em = sf->ascent+sf->descent;
134 	BDFFont *b;
135 
136 	for ( b=sf->bitmaps; b!=NULL; b=b->next ) {
137 	    scaled_sum += (double) (em*b->ascent)/b->pixelsize;
138 	    ++cnt;
139 	}
140 	if ( cnt!=0 )
141 	sf->ascent = scaled_sum/cnt;
142 	sf->descent = em - sf->ascent;
143     }
144 }
145 
146 /* ******************************** BDF ************************************* */
147 
gettoken(FILE * bdf,char * tokbuf,int size)148 static int gettoken(FILE *bdf, char *tokbuf, int size) {
149     char *pt=tokbuf, *end = tokbuf+size-2; int ch;
150 
151     while ( isspace(ch = getc(bdf)));
152     while ( ch!=EOF && !isspace(ch) /* && ch!='[' && ch!=']' && ch!='{' && ch!='}' && ch!='<' && ch!='%' */ ) {
153 	if ( pt<end ) *pt++ = ch;
154 	ch = getc(bdf);
155     }
156     if ( pt==tokbuf && ch!=EOF )
157 	*pt++ = ch;
158     else
159 	ungetc(ch,bdf);
160     *pt='\0';
161 return( pt!=tokbuf?1:ch==EOF?-1: 0 );
162 }
163 
ExtendSF(SplineFont * sf,EncMap * map,int enc)164 static void ExtendSF(SplineFont *sf, EncMap *map, int enc) {
165     FontViewBase *fvs;
166 
167     if ( enc>=map->enccount ) {
168 	int n = enc;
169 	if ( enc>=map->encmax )
170 	    map->map = realloc(map->map,(map->encmax = n+100)*sizeof(int));
171 	memset(map->map+map->enccount,-1,(enc-map->enccount+1)*sizeof(int));
172 	map->enccount = n+1;
173 	if ( sf->fv!=NULL ) {
174 	    for ( fvs=sf->fv; fvs!=NULL; fvs=fvs->nextsame ) {
175 		free(fvs->selected);
176 		fvs->selected = calloc(map->enccount,1);
177 	    }
178 	    FontViewReformatAll(sf);
179 	}
180     }
181 }
182 
MakeEncChar(SplineFont * sf,EncMap * map,int enc,const char * name)183 static SplineChar *MakeEncChar(SplineFont *sf,EncMap *map, int enc,const char *name) {
184     int uni;
185     SplineChar *sc;
186 
187     ExtendSF(sf,map,enc);
188 
189     sc = SFMakeChar(sf,map,enc);
190     free(sc->name);
191     sc->name = cleancopy(name);
192 
193     uni = UniFromName(name,sf->uni_interp,map->enc);
194     if ( uni!=-1 )
195 	sc->unicodeenc = uni;
196 return( sc );
197 }
198 
figureProperEncoding(SplineFont * sf,EncMap * map,BDFFont * b,int enc,const char * name,int swidth,int swidth1,Encoding * encname)199 static int figureProperEncoding(SplineFont *sf,EncMap *map, BDFFont *b, int enc,
200 	const char *name, int swidth, int swidth1, Encoding *encname) {
201     int i = -1, gid;
202 
203     if ( strcmp(name,".notdef")==0 ) {
204 	gid = ( enc>=map->enccount || enc<0 ) ? -1 : map->map[enc];
205 	if ( gid==-1 || sf->glyphs[gid]==NULL || strcmp(sf->glyphs[gid]->name,name)!=0 ) {
206 	    SplineChar *sc;
207 	    if ( enc==-1 ) {
208 		if ( (enc = SFFindSlot(sf,map,-1,name))==-1 )
209 		    enc = map->enccount;
210 	    }
211 	    MakeEncChar(sf,map,enc,name);
212 	    sc = SFMakeChar(sf,map,enc);
213 	    if ( sf->onlybitmaps || !sc->widthset ) {
214 		sc->width = swidth;
215 		sc->widthset = true;
216 		if ( swidth1!=-1 )
217 		    sc->vwidth = swidth1;
218 	    }
219 	}
220     } else if ( map->enc==encname ||
221 	    (map->enc==&custom && sf->onlybitmaps)) {
222 	i = enc;
223 	if ( i==-1 ) {
224 	    if ( (i = SFFindSlot(sf,map,-1,name))==-1 )
225 		i = map->enccount;
226 	}
227 	if ( i>=map->enccount || map->map[i]==-1 )
228 	    MakeEncChar(sf,map,i,name);
229     } else {
230 	int32 uni = UniFromEnc(enc,encname);
231 	if ( uni==-1 )
232 	    uni = UniFromName(name,sf->uni_interp,map->enc);
233 	i = EncFromUni(uni,map->enc);
234 	if ( i==-1 ) {
235 	    i = SFFindSlot(sf,map,uni,name);
236 	    if ( i==-1 && sf->onlybitmaps && enc!=-1 &&
237 		    ((sf->bitmaps==b && b->next==NULL) || sf->bitmaps==NULL) ) {
238 		MakeEncChar(sf,map,enc,name);
239 		i = enc;
240 	    }
241 	}
242     }
243     if ( i==-1 || i>=map->enccount ) {
244 	/* try adding it to the end of the font */
245 	int j;
246 	int encmax = map->enc->char_cnt;
247 	for ( j=map->enccount-1; j>=encmax &&
248 		((gid=map->map[j])==-1 || sf->glyphs[gid]==NULL); --j );
249 	++j;
250 	if ( i<j )
251 	    i = j;
252 	MakeEncChar(sf,map,i,name);
253     }
254 
255     if ( i!=-1 && i<map->enccount && ((gid=map->map[i])==-1 || sf->glyphs[gid]==NULL )) {
256 	SplineChar *sc = SFMakeChar(sf,map,i);
257 	if ( sf->onlybitmaps && ((sf->bitmaps==b && b->next==NULL) || sf->bitmaps==NULL) ) {
258 	    free(sc->name);
259 	    sc->name = cleancopy(name);
260 	}
261     }
262     if ( i!=-1 && swidth!=-1 && (gid=map->map[i])!=-1 &&
263 	    ((sf->onlybitmaps && ((sf->bitmaps==b && b->next==NULL) || sf->bitmaps==NULL) ) ||
264 	     (sf->glyphs[gid]!=NULL && sf->glyphs[gid]->layers[ly_fore].splines==NULL && sf->glyphs[gid]->layers[ly_fore].refs==NULL &&
265 	       !sf->glyphs[gid]->widthset)) ) {
266 	sf->glyphs[gid]->width = swidth;
267 	sf->glyphs[gid]->widthset = true;
268 	if ( swidth1!=-1 )
269 	    sf->glyphs[gid]->vwidth = swidth1;
270     }
271     if ( i!=-1 && (gid=map->map[i])!=-1 ) {
272 	if ( gid>=b->glyphcnt ) {
273 	    if ( gid>=b->glyphmax )
274 		b->glyphs = realloc(b->glyphs,(b->glyphmax = sf->glyphmax)*sizeof(BDFChar *));
275 	    memset(b->glyphs+b->glyphcnt,0,(gid+1-b->glyphcnt)*sizeof(BDFChar *));
276 	    b->glyphcnt = gid+1;
277 	}
278     }
279 return( i );
280 }
281 
282 struct metrics {
283     int swidth, dwidth, swidth1, dwidth1;	/* Font wide width defaults */
284     int metricsset, vertical_origin;
285     int res;
286 };
287 
AddBDFChar(FILE * bdf,SplineFont * sf,BDFFont * b,EncMap * map,int depth,struct metrics * defs,Encoding * encname)288 static void AddBDFChar(FILE *bdf, SplineFont *sf, BDFFont *b,EncMap *map,int depth,
289 	struct metrics *defs, Encoding *encname) {
290     BDFChar *bc;
291     char name[40], tok[100];
292     int enc=-1, width=defs->dwidth, xmin=0, xmax=0, ymin=0, ymax=0, hsz, vsz;
293     int swidth= defs->swidth, swidth1=defs->swidth1;
294     int vwidth = defs->dwidth1;
295     int i,ch;
296     uint8 *pt, *end, *eol;
297 
298     gettoken(bdf,name,sizeof(tok));
299     while ( gettoken(bdf,tok,sizeof(tok))!=-1 ) {
300 	if ( strcmp(tok,"ENCODING")==0 ) {
301 	    fscanf(bdf,"%d",&enc);
302 	    /* Adobe says that enc is value for Adobe Standard */
303 	    /* But people don't use it that way. Adobe also says that if */
304 	    /* there is no mapping in adobe standard the -1 may be followed */
305 	    /* by another value, the local encoding. */
306 	    if ( enc==-1 ) {
307 		ch = getc(bdf);
308 		if ( ch==' ' || ch=='\t' )
309 		    fscanf(bdf,"%d",&enc);
310 		else
311 		    ungetc(ch,bdf);
312 	    }
313 	    if ( enc<-1 ) enc = -1;
314 	} else if ( strcmp(tok,"DWIDTH")==0 )
315 	    fscanf(bdf,"%d %*d",&width);
316 	else if ( strcmp(tok,"DWIDTH1")==0 )
317 	    fscanf(bdf,"%d %*d",&vwidth);
318 	else if ( strcmp(tok,"SWIDTH")==0 )
319 	    fscanf(bdf,"%d %*d",&swidth);
320 	else if ( strcmp(tok,"SWIDTH1")==0 )
321 	    fscanf(bdf,"%d %*d",&swidth1);
322 	else if ( strcmp(tok,"BBX")==0 ) {
323 	    fscanf(bdf,"%d %d %d %d",&hsz, &vsz, &xmin, &ymin );
324 	    xmax = hsz+xmin-1;
325 	    ymax = vsz+ymin-1;
326 	} else if ( strcmp(tok,"BITMAP")==0 )
327     break;
328     }
329     if (( xmax+1==xmin && (ymax+1==ymin || ymax==ymin)) ||
330 	    (( xmax+1==xmin || xmax==xmin) && ymax+1==ymin ))
331 	/* Empty glyph */;
332     else if ( xmax<xmin || ymax<ymin ) {
333 	LogError( _("Bad bounding box for %s.\n"), name );
334 return;
335     }
336     i = figureProperEncoding(sf,map,b,enc,name,swidth,swidth1,encname);
337     if ( i!=-1 ) {
338 	int gid = map->map[i];
339 	if ( (bc=b->glyphs[gid])!=NULL ) {
340 	    free(bc->bitmap);
341 	    BDFFloatFree(bc->selection);
342 	} else {
343 	    b->glyphs[gid] = bc = chunkalloc(sizeof(BDFChar));
344 	    memset( bc,'\0',sizeof( BDFChar ));
345 	    bc->sc = sf->glyphs[gid];
346 	    bc->orig_pos = gid;
347 	}
348 	bc->xmin = xmin;
349 	bc->ymin = ymin;
350 	bc->xmax = xmax;
351 	bc->ymax = ymax;
352 	bc->width = width;
353 	bc->vwidth = vwidth;
354 	if ( depth==1 ) {
355 	    bc->bytes_per_line = ((xmax-xmin)>>3) + 1;
356 	    bc->byte_data = false;
357 	} else {
358 	    bc->bytes_per_line = xmax-xmin + 1;
359 	    bc->byte_data = true;
360 	}
361 	bc->depth = depth;
362 	bc->bitmap = malloc(bc->bytes_per_line*(ymax-ymin+1));
363 
364 	pt = bc->bitmap; end = pt + bc->bytes_per_line*(ymax-ymin+1);
365 	eol = pt + bc->bytes_per_line;
366 	while ( pt<end ) {
367 	    int ch1, ch2, val;
368 	    while ( isspace(ch1=getc(bdf)) );
369 	    ch2 = getc(bdf);
370 	    val = 0;
371 	    if ( ch1>='0' && ch1<='9' ) val = (ch1-'0')<<4;
372 	    else if ( ch1>='a' && ch1<='f' ) val = (ch1-'a'+10)<<4;
373 	    else if ( ch1>='A' && ch1<='F' ) val = (ch1-'A'+10)<<4;
374 	    if ( ch2>='0' && ch2<='9' ) val |= (ch2-'0');
375 	    else if ( ch2>='a' && ch2<='f' ) val |= (ch2-'a'+10);
376 	    else if ( ch2>='A' && ch2<='F' ) val |= (ch2-'A'+10);
377 	    if ( depth==1 || depth==8 )
378 		*pt++ = val;
379 	    else if ( depth==2 ) {		/* Internal representation is unpacked, one byte per pixel */
380 		*pt++ = (val>>6);
381 		if ( pt<eol ) *pt++ = (val>>4)&3;
382 		if ( pt<eol ) *pt++ = (val>>2)&3;
383 		if ( pt<eol ) *pt++ = val&3;
384 	    } else if ( depth==4 ) {
385 		*pt++ = (val>>4);
386 		if ( pt<eol ) *pt++ = val&0xf;
387 	    } else if ( depth==16 || depth==32 ) {
388 		int i,j;
389 		*pt++ = val;
390 		/* I only deal with 8 bit pixels, so if they give me more */
391 		/*  just ignore the low order bits */
392 		j = depth==16?2:6;
393 		for ( i=0; i<j; ++j )
394 		    ch2 = getc(bdf);
395 	    }
396 	    if ( pt>=eol ) {
397 		eol += bc->bytes_per_line;
398 		while ( (ch1 = getc(bdf)) != '\n')
399 		    /* empty loop body */ ;
400 	    }
401 	    if ( ch2==EOF )
402 	break;
403 	}
404     } else {
405 	int cnt;
406 	if ( depth==1 )
407 	    cnt = 2*(((xmax-xmin)>>3) + 1) * (ymax-ymin+1);
408 	else if ( depth==2 )
409 	    cnt = 2*(((xmax-xmin)>>2) + 1) * (ymax-ymin+1);
410 	else if ( depth==4 )
411 	    cnt = (xmax-xmin + 1) * (ymax-ymin+1);
412 	else if ( depth==8 )
413 	    cnt = 2*(xmax-xmin + 1) * (ymax-ymin+1);
414 	else if ( depth==16 )
415 	    cnt = 4*(xmax-xmin + 1) * (ymax-ymin+1);
416 	else
417 	    cnt = 8*(xmax-xmin + 1) * (ymax-ymin+1);
418 	for ( i=0; i<cnt; ++i ) {
419 	    while ( isspace(getc(bdf)) );
420 	    getc(bdf);
421 	}
422     }
423 }
424 
BDFParseEnc(char * encname,int encoff)425 static Encoding *BDFParseEnc(char *encname, int encoff) {
426     Encoding *enc;
427     char buffer[200];
428 
429     enc = NULL;
430     if ( strmatch(encname,"ISO10646")==0 || strmatch(encname,"ISO-10646")==0 || strmatch(encname,"ISO_10646")==0 ||
431 	    strmatch(encname,"Unicode")==0 )
432 	enc = FindOrMakeEncoding("Unicode");
433     if ( enc==NULL ) {
434 	sprintf( buffer, "%.150s-%d", encname, encoff );
435 	enc = FindOrMakeEncoding(buffer);
436     }
437     if ( enc==NULL && strmatch(encname,"ISOLatin1Encoding")==0 )
438 	enc = FindOrMakeEncoding("ISO8859-1");
439     if ( enc==NULL )
440 	enc = FindOrMakeEncoding(encname);
441     if ( enc==NULL )
442 	enc = &custom;
443 return( enc );
444 }
445 
default_ascent_descent(int * _as,int * _ds,int ascent,int descent,int pixelsize,int pixel_size2,int point_size,int res,char * filename)446 static int default_ascent_descent(int *_as, int *_ds, int ascent, int descent,
447 	int pixelsize, int pixel_size2, int point_size, int res,
448 	char *filename) {
449 
450     if ( pixelsize!=-1 && pixel_size2!=-1 && ascent!=-1 && descent!=-1 ) {
451 	if ( pixelsize!=pixel_size2 || pixelsize!=ascent+descent ) {
452 	    if ( pixelsize==pixel_size2 )
453 		descent = pixelsize - ascent;
454 	    else if ( pixel_size2==ascent+descent )
455 		pixelsize = pixel_size2;
456 	    else if ( pixelsize==ascent+descent )
457 		;
458 	    else {
459 		pixelsize = rint( (pixelsize+pixel_size2+ascent+descent)/3.0 );
460 		descent = pixelsize-ascent;
461 	    }
462 	    LogError(_("Various specifications of PIXEL_SIZE do not match in %s"), filename );
463 	}
464     } else if ( pixelsize!=-1 && ascent!=-1 && descent!=-1 ) {
465 	if ( pixelsize!=ascent+descent ) {
466 	    ascent = 8*pixelsize/10;
467 	    descent = pixelsize-ascent;
468 	}
469     } else {
470 	if ( pixelsize==-1 )
471 	    pixelsize = pixel_size2;
472 	if ( (ascent==-1) + (descent==-1) + (pixelsize==-1)>=2 &&
473 		res!=-1 && point_size!=-1 )
474 	    pixelsize = rint( point_size*res/720.0 );
475 	if ( pixelsize==-1 && ascent!=-1 && descent!=-1 )
476 	    pixelsize = ascent+descent;
477 	else if ( pixelsize!=-1 ) {
478 	    if ( ascent==-1 && descent!=-1 )
479 		ascent = pixelsize - descent;
480 	    else if ( ascent!=-1 )
481 		descent = pixelsize -ascent;
482 	}
483 	if ( ascent!=-1 && descent!=-1 && pixelsize!=-1 ) {
484 	    if ( pixelsize!=ascent+descent )
485 		LogError(_("Pixel size does not match sum of Font ascent+descent in %s"), filename );
486 	} else if ( pixelsize!=-1 ) {
487 	    ascent = rint( (8*pixelsize)/10.0 );
488 	    descent = pixelsize - ascent;
489 	} else if ( ascent!=-1 ) {
490 	    LogError(_("Guessing pixel size based on font ascent in %s"), filename );
491 	    descent = ascent/4;
492 	    pixelsize = ascent+descent;
493 	} else if ( descent!=-1 ) {
494 	    LogError(_("Guessing pixel size based on font descent in %s"), filename );
495 	    ascent = 4*descent;
496 	    pixelsize = ascent+descent;
497 	} else {
498 	    /* No info at all. We'll ask the user later */
499 	}
500     }
501     *_as = ascent; *_ds=descent;
502 return( pixelsize );
503 }
504 
slurp_header(FILE * bdf,int * _as,int * _ds,Encoding ** _enc,char * family,char * mods,char * full,int * depth,char * foundry,char * fontname,char * comments,struct metrics * defs,int * upos,int * uwidth,BDFFont * dummy,char * filename)505 static int slurp_header(FILE *bdf, int *_as, int *_ds, Encoding **_enc,
506 	char *family, char *mods, char *full, int *depth, char *foundry,
507 	char *fontname, char *comments, struct metrics *defs,
508 	int *upos, int *uwidth, BDFFont *dummy,
509 	char *filename) {
510     int pixelsize = -1, pixel_size2= -1, point_size = -1;
511     int ascent= -1, descent= -1, enc, cnt;
512     char tok[100], encname[100], weight[100], italic[100], buffer[300], *buf;
513     int found_copyright=0;
514     int inprops=false;
515     int pcnt=0, pmax=0;
516 
517     *depth = 1;
518     encname[0]= '\0'; family[0] = '\0'; weight[0]='\0'; italic[0]='\0'; full[0]='\0';
519     foundry[0]= '\0'; comments[0] = '\0';
520     while ( gettoken(bdf,tok,sizeof(tok))!=-1 ) {
521 	if ( strcmp(tok,"CHARS")==0 ) {
522 	    cnt=0;
523 	    fscanf(bdf,"%d",&cnt);
524 	    ff_progress_change_total(cnt);
525     break;
526 	}
527 	if ( strcmp(tok,"STARTPROPERTIES")==0 ) {
528 	    int cnt;
529 	    inprops = true;
530 	    fscanf(bdf, "%d", &cnt );
531 	    if ( pcnt+cnt>=pmax )
532 		dummy->props = realloc(dummy->props,(pmax=pcnt+cnt)*sizeof(BDFProperties));
533 	    /* But it isn't a property itself */
534     continue;
535 	} else if ( strcmp(tok,"ENDPROPERTIES")==0 ) {
536 	    inprops = false;
537     continue;
538 	}
539 	fgets(buffer,sizeof(buffer),bdf );
540 	buf = buffer;
541 	{
542 	    int val;
543 	    char *end, *eol;
544 
545 	    if ( pcnt>=pmax )
546 		dummy->props = realloc(dummy->props,(pmax=pcnt+10)*sizeof(BDFProperties));
547 	    dummy->props[pcnt].name = copy(tok);
548 	    while ( *buf==' ' || *buf=='\t' ) ++buf;
549 	    for ( eol=buf+strlen(buf)-1; eol>=buf && isspace(*eol); --eol);
550 	    eol[1] ='\0';
551 	    val = strtol(buf,&end,10);
552 	    if ( *end=='\0' && buf<=eol ) {
553 		dummy->props[pcnt].u.val = val;
554 		dummy->props[pcnt].type = IsUnsignedBDFKey(tok)?prt_uint:prt_int;
555 	    } else if ( *buf=='"' ) {
556 		++buf;
557 		if ( *eol=='"' ) *eol = '\0';
558 		dummy->props[pcnt].u.str = copy(buf);
559 		dummy->props[pcnt].type = prt_string;
560 	    } else {
561 		dummy->props[pcnt].u.atom = copy(buf);
562 		dummy->props[pcnt].type = prt_atom;
563 	    }
564 	    if ( inprops )
565 		dummy->props[pcnt].type |= prt_property;
566 	    ++pcnt;
567 	}
568 
569 	if ( strcmp(tok,"FONT")==0 ) {
570 	    if ( sscanf(buf,"-%*[^-]-%99[^-]-%99[^-]-%99[^-]-%*[^-]-", family, weight, italic )!=0 ) {
571 		char *pt=buf;
572 		int dcnt=0;
573 		while ( *pt=='-' && dcnt<7 ) { ++pt; ++dcnt; }
574 		while ( *pt!='-' && *pt!='\n' && *pt!='\0' && dcnt<7 ) {
575 		    while ( *pt!='-' && *pt!='\n' && *pt!='\0' ) ++pt;
576 		    while ( *pt=='-' && dcnt<7 ) { ++pt; ++dcnt; }
577 		}
578 		sscanf(pt,"%d", &pixelsize );
579 		if ( pixelsize<0 ) pixelsize = -pixelsize;	/* An extra - screwed things up once... */
580 		while ( *pt!='-' && *pt!='\n' && *pt!='\0' ) ++pt;
581 		if ( *pt=='-' ) {
582 		    sscanf(++pt,"%d", &point_size );
583 		    if ( point_size<0 ) point_size = -point_size;
584 		}
585 	    } else {
586 		if ( *buf!='\0' && !isdigit(*buf))
587 		    strcpy(family,buf);
588 	    }
589 	} else if ( strcmp(tok,"SIZE")==0 ) {
590 	    int junk;
591 	    sscanf(buf, "%d %d %d %d", &point_size, &junk, &defs->res, depth );
592 	    if ( pixelsize==-1 )
593 		pixelsize = rint( point_size*defs->res/72.0 );
594 	} else if ( strcmp(tok,"BITSPERPIXEL")==0 ||
595 		strcmp(tok,"BITS_PER_PIXEL")==0 ) {
596 	    sscanf(buf, "%d", depth);
597 	} else if ( strcmp(tok,"QUAD_WIDTH")==0 && pixelsize==-1 )
598 	    sscanf(buf, "%d", &pixelsize );
599 	    /* For Courier the quad is not an em */
600 	else if ( strcmp(tok,"RESOLUTION_Y")==0 )	/* y value defines pointsize */
601 	    sscanf(buf, "%d", &defs->res );
602 	else if ( strcmp(tok,"POINT_SIZE")==0 )
603 	    sscanf(buf, "%d", &point_size );
604 	else if ( strcmp(tok,"PIXEL_SIZE")==0 )
605 	    sscanf(buf, "%d", &pixel_size2 );
606 	else if ( strcmp(tok,"FONT_ASCENT")==0 )
607 	    sscanf(buf, "%d", &ascent );
608 	else if ( strcmp(tok,"FONT_DESCENT")==0 )
609 	    sscanf(buf, "%d", &descent );
610 	else if ( strcmp(tok,"UNDERLINE_POSITION")==0 )
611 	    sscanf(buf, "%d", upos );
612 	else if ( strcmp(tok,"UNDERLINE_THICKNESS")==0 )
613 	    sscanf(buf, "%d", uwidth );
614 	else if ( strcmp(tok,"SWIDTH")==0 )
615 	    sscanf(buf, "%d", &defs->swidth );
616 	else if ( strcmp(tok,"SWIDTH1")==0 )
617 	    sscanf(buf, "%d", &defs->swidth1 );
618 	else if ( strcmp(tok,"DWIDTH")==0 )
619 	    sscanf(buf, "%d", &defs->dwidth );
620 	else if ( strcmp(tok,"DWIDTH1")==0 )
621 	    sscanf(buf, "%d", &defs->dwidth1 );
622 	else if ( strcmp(tok,"METRICSSET")==0 )
623 	    sscanf(buf, "%d", &defs->metricsset );
624 	else if ( strcmp(tok,"VVECTOR")==0 )
625 	    sscanf(buf, "%*d %d", &defs->vertical_origin );
626 	/* For foundry, fontname and encname, only copy up to the buffer size */
627 	else if ( strcmp(tok,"FOUNDRY")==0 )
628 	    sscanf(buf, "%99[^\"]", foundry );
629 	else if ( strcmp(tok,"FONT_NAME")==0 )
630 	    sscanf(buf, "%99[^\"]", fontname );
631 	else if ( strcmp(tok,"CHARSET_REGISTRY")==0 )
632 	    sscanf(buf, "%99[^\"]", encname );
633 	else if ( strcmp(tok,"CHARSET_ENCODING")==0 ) {
634 	    enc = 0;
635 	    if ( sscanf(buf, " %d", &enc )!=1 )
636 		sscanf(buf, "%d", &enc );
637 	/* These properties should be copied up to the buffer length too */
638 	} else if ( strcmp(tok,"FAMILY_NAME")==0 ) {
639 	    strncpy(family,buf,99);
640 	    family[99]='\0';
641 	} else if ( strcmp(tok,"FULL_NAME")==0 || strcmp(tok,"FACE_NAME")==0 ) {
642 	    strncpy(full,buf,99);
643 	    full[99]='\0';
644 	} else if ( strcmp(tok,"WEIGHT_NAME")==0 ) {
645 	    strncpy(weight,buf,99);
646 	    weight[99]='\0';
647 	} else if ( strcmp(tok,"SLANT")==0 ) {
648 	    strncpy(italic,buf,99);
649 	    italic[99]='\0';
650 	} else if ( strcmp(tok,"COPYRIGHT")==0 ) {
651 		/* LS: Assume the size of the passed-in buffer is 1000, see below in
652 		 * COMMENT... */
653 	    strncpy(comments,buf,999);
654 	    comments[999]='\0';
655 	    found_copyright = true;
656 	} else if ( strcmp(tok,"COMMENT")==0 && !found_copyright ) {
657 	    char *pt = comments+strlen(comments);
658 	    char *eoc = comments+1000-1; /* ...here */
659 	    strncpy(pt,buf,eoc-pt);
660 	    *eoc ='\0';
661 	}
662     }
663     dummy->prop_cnt = pcnt;
664 
665     pixelsize = default_ascent_descent(_as, _ds, ascent, descent, pixelsize,
666 	    pixel_size2, point_size, defs->res, filename );
667 
668     *_enc = BDFParseEnc(encname,enc);
669 
670     if ( strmatch(italic,"I")==0 )
671 	strcpy(italic,"Italic");
672     else if ( strmatch(italic,"O")==0 )
673 	strcpy(italic,"Oblique");
674     else if ( strmatch(italic,"R")==0 )
675 	strcpy(italic,"");		/* Ignore roman */
676     sprintf(mods,"%s%s", weight, italic );
677     if ( comments[0]!='\0' && comments[strlen(comments)-1]=='\n' )
678 	comments[strlen(comments)-1] = '\0';
679 
680     if ( *depth!=1 && *depth!=2 && *depth!=4 && *depth!=8 && *depth!=16 && *depth!=32 )
681 	LogError( _("FontForge does not support this bit depth %d (must be 1,2,4,8,16,32)\n"), *depth);
682 
683 return( pixelsize );
684 }
685 
686 /* ******************************** GF (TeX) ******************************** */
687 enum gf_cmd { gf_paint_0=0, gf_paint_1=1, gf_paint_63=63,
688 	gf_paint1b=64, gf_paint2b, gf_paint3b,	/* followed by 1,2,or3 bytes saying how far to paint */
689 	gf_boc=67, /* 4bytes of character code, 4bytes of -1, min_col 4, min_row 4, max_col 4, max_row 4 */
690 	    /* set row=max_row, col=min_col, paint=white */
691 	gf_boc1=68, /* 1 byte quantities, and no -1 field, cc, width, max_col, height, max_row */
692 	gf_eoc=69,
693 	gf_skip0=70,	/* start next row (don't need to complete current) as white*/
694 	gf_skip1=71, gf_skip2=72, gf_skip3=73, /* followed by 1,2,3 bytes saying number rows to skip (leave white) */
695 	gf_newrow_0=74,	/* Same as skip, start drawing with black */
696 	gf_newrow_1=75, gf_newrow_164=238,
697 	gf_xxx1=239, /* followed by a 1 byte count, and then that many bytes of ignored data */
698 	gf_xxx2, gf_xxx3, gf_xxx4,
699 	gf_yyy=243, /* followed by 4 bytes of numeric data */
700 	gf_no_op=244,
701 	gf_char_loc=245, /* 1?byte encoding, 4byte dx, 4byte dy (<<16), 4byte advance width/design size <<24, 4byte offset to character's boc */
702 	gf_char_loc0=246, /* 1?byte encoding, 1byte dx, 4byte advance width/design size <<24, 4byte offset to character's boc */
703 	gf_pre=247, /* one byte containing gf_version_number, one byte count, that many bytes data */
704 	gf_post=248,	/* start of post amble */
705 	gf_post_post=249,	/* End of postamble, 4byte offset to start of preamble, 1byte gf_version_number, 4 or more bytes of 0xdf */
706 	/* rest 250..255 are undefined */
707 	gf_version_number=131 };
708 /* The postamble command is followed by 9 4byte quantities */
709 /*  the first is an offset to a list of xxx commands which I'm ignoring */
710 /*  the second is the design size */
711 /*  the third is a check sum */
712 /*  the fourth is horizontal pixels per point<<16 */
713 /*  the fifth is vertical pixels per point<<16 */
714 /*  the sixth..ninth give the font bounding box */
715 /* Then a bunch of char_locs (with back pointers to the characters and advance width info) */
716 /* Then a post_post with a back pointer to start of postamble + gf_version */
717 /* Then 4-7 bytes of 0xdf */
718 
SFGrowTo(SplineFont * sf,BDFFont * b,int cc,EncMap * map)719 static BDFChar *SFGrowTo(SplineFont *sf,BDFFont *b, int cc, EncMap *map) {
720     char buf[20];
721     int gid;
722     BDFChar *bc;
723 
724     if ( cc >= map->enccount ) {
725 	if ( cc>=map->encmax ) {
726 	    int new = ((map->enccount+256)>>8)<<8;
727 	    if ( new<cc+1 ) new = cc+1;
728 	    map->map = realloc(map->map,new*sizeof(int));
729 	    map->encmax = new;
730 	}
731 	memset(map->map+map->enccount,-1,(cc+1-map->enccount)*sizeof(int));
732 	map->enccount = cc+1;
733     }
734     if ( (gid = map->map[cc])==-1 || sf->glyphs[gid]==NULL )
735 	gid = SFMakeChar(sf,map,cc)->orig_pos;
736     if ( sf->onlybitmaps && ((sf->bitmaps==b && b->next==NULL) || sf->bitmaps==NULL) ) {
737 	free(sf->glyphs[gid]->name);
738 	sprintf( buf, "enc-%d", cc);
739 	sf->glyphs[gid]->name = cleancopy( buf );
740 	sf->glyphs[gid]->unicodeenc = -1;
741     }
742     if ( b->glyphcnt<sf->glyphcnt ) {
743 	if ( b->glyphmax<sf->glyphcnt )
744 	    b->glyphs = realloc(b->glyphs,(b->glyphmax = sf->glyphmax)*sizeof(BDFChar *));
745 	memset(b->glyphs+b->glyphcnt,0,(sf->glyphcnt-b->glyphcnt)*sizeof(BDFChar *));
746 	b->glyphcnt = sf->glyphcnt;
747     }
748     if ( (bc=b->glyphs[gid])!=NULL ) {
749 	free(bc->bitmap);
750 	BDFFloatFree(bc->selection);
751     } else {
752 	b->glyphs[gid] = bc = chunkalloc(sizeof(BDFChar));
753 	memset( bc,'\0',sizeof( BDFChar ));
754 	bc->sc = sf->glyphs[gid];
755 	bc->orig_pos = gid;
756     }
757 return(bc);
758 }
759 
gf_skip_noops(FILE * gf,char * char_name)760 static void gf_skip_noops(FILE *gf,char *char_name) {
761     uint8 cmd;
762     int32 val;
763     int i;
764     char buffer[257];
765 
766     if ( char_name ) *char_name = '\0';
767 
768     while ( 1 ) {
769 	cmd = getc(gf);
770 	switch( cmd ) {
771 	  case gf_no_op:		/* One byte no-op */
772 	  break;
773 	  case gf_yyy:			/* followed by a 4 byte value */
774 	    getc(gf); getc(gf); getc(gf); getc(gf);
775 	  break;
776 	  case gf_xxx1:
777 	    val = getc(gf);
778 	    for ( i=0; i<val; ++i ) buffer[i] = getc(gf);
779 	    buffer[i] = 0;
780 	    if (strncmp(buffer,"title",5)==0 && char_name!=NULL ) {
781 		char *pt = buffer+6, *to = char_name;
782 		while ( *pt ) {
783 		    if ( *pt=='(' ) {
784 			while ( *pt!=')' && *pt!='\0' ) ++pt;
785 		    } else if ( *pt==' ' || *pt==')' ) {
786 			if ( to==char_name || to[-1]!='-' )
787 			    *to++ = '-';
788 			++pt;
789 		    } else
790 			*to++ = *pt++;
791 		}
792 		if ( to!=char_name && to[-1]=='-' )
793 		    --to;
794 		*to = '\0';
795 	    }
796 	  break;
797 	  case gf_xxx2:
798 	    val = getc(gf);
799 	    val = (val<<8) | getc(gf);
800 	    for ( i=0; i<val; ++i ) getc(gf);
801 	  break;
802 	  case gf_xxx3:
803 	    val = getc(gf);
804 	    val = (val<<8) | getc(gf);
805 	    val = (val<<8) | getc(gf);
806 	    for ( i=0; i<val; ++i ) getc(gf);
807 	  break;
808 	  case gf_xxx4:
809 	    val = getlong(gf);
810 	    for ( i=0; i<val; ++i ) getc(gf);
811 	  break;
812 	  default:
813 	    ungetc(cmd,gf);
814 return;
815 	}
816     }
817 }
818 
gf_postamble(FILE * gf,int * _as,int * _ds,Encoding ** _enc,char * family,char * mods,char * full,char * filename)819 static int gf_postamble(FILE *gf, int *_as, int *_ds, Encoding **_enc, char *family,
820 	char *mods, char *full, char *filename) {
821     int pixelsize=-1;
822     int ch;
823     int design_size, pixels_per_point;
824     double size;
825     char *pt, *fpt;
826     int32 pos, off;
827 
828     fseek(gf,-4,SEEK_END);
829     pos = ftell(gf);
830     ch = getc(gf);
831     if ( ch!=0xdf )
832 return( -2 );
833     while ( ch==0xdf ) {
834 	--pos;
835 	fseek(gf,-2,SEEK_CUR);
836 	ch = getc(gf);
837     }
838     if ( ch!=gf_version_number )
839 return( -2 );
840     pos -= 4;
841     fseek(gf,pos,SEEK_SET);
842     off = getlong(gf);
843     fseek(gf,off,SEEK_SET);
844     ch = getc(gf);
845     if ( ch!=gf_post )
846 return( -2 );
847     /* offset to comments */ getlong(gf);
848     design_size = getlong(gf);
849     /* checksum = */ getlong(gf);
850     pixels_per_point = getlong(gf);
851     /* vert pixels per point = */ getlong(gf);
852     /* min_col = */ getlong(gf);
853     /* min_row = */ getlong(gf);
854     /* max_col = */ getlong(gf);
855     /* max_row = */ getlong(gf);
856 
857     size = (pixels_per_point / (double) (0x10000)) * (design_size / (double) (0x100000));
858     pixelsize = size+.5;
859     *_enc = &custom;
860     *_as = *_ds = -1;
861     *mods = '\0';
862     pt = strrchr(filename, '/');
863     if ( pt==NULL ) pt = filename; else ++pt;
864     for ( fpt=family; isalpha(*pt);)
865 	*fpt++ = *pt++;
866     *fpt = '\0';
867     strcpy(full,family);
868 
869 return( pixelsize );
870 }
871 
gf_char(FILE * gf,SplineFont * sf,BDFFont * b,EncMap * map)872 static int gf_char(FILE *gf, SplineFont *sf, BDFFont *b,EncMap *map) {
873     int32 pos, to;
874     int ch, enc, dx, aw;
875     int min_c, max_c, min_r, max_r, w;
876     int r,c, col,cnt,i;
877     int gid;
878     BDFChar *bc;
879     char charname[256];
880 
881     /* We assume we are positioned within the postamble. we read one char_loc */
882     /*  then read the char it points to, then return to postamble */
883     ch = getc(gf);
884     if ( ch== gf_char_loc ) {
885 	enc = getc(gf);
886 	dx = getlong(gf)>>16;
887 	/* dy */ (void)(getlong(gf)>>16);
888 	aw = (getlong(gf)*(sf->ascent+sf->descent))>>20;
889 	to = getlong(gf);
890     } else if ( ch==gf_char_loc0 ) {
891 	enc = getc(gf);
892 	dx = getc(gf);
893 	aw = (getlong(gf)*(sf->ascent+sf->descent))>>20;
894 	to = getlong(gf);
895     } else
896 return( false );
897     pos = ftell(gf);
898     fseek(gf,to,SEEK_SET);
899 
900     gf_skip_noops(gf,charname);
901     ch = getc(gf);
902     if ( ch==gf_boc ) {
903 	/* encoding = */ getlong(gf);
904 	/* backpointer = */ getlong(gf);
905 	min_c = getlong(gf);
906 	max_c = getlong(gf);
907 	min_r = getlong(gf);
908 	max_r = getlong(gf);
909     } else if ( ch==gf_boc1 ) {
910 	/* encoding = */ getc(gf);
911 	w = getc(gf);
912 	max_c = getc(gf);
913 	min_c = max_c-w+1;
914 	w = getc(gf);
915 	max_r = getc(gf);
916 	min_r = max_r-w+1;
917     } else
918 return( false );
919 
920     bc = SFGrowTo(sf,b,enc,map);
921     gid = map->map[enc];
922     if ( charname[0]!='\0' && sf->onlybitmaps && (sf->bitmaps==NULL ||
923 	    (sf->bitmaps==b && b->next==NULL )) ) {
924 	free(sf->glyphs[gid]->name);
925 	sf->glyphs[gid]->name = cleancopy(charname);
926 	sf->glyphs[gid]->unicodeenc = -1;
927     }
928     bc->xmin = min_c;
929     bc->xmax = max_c>min_c? max_c : min_c;
930     bc->ymin = min_r;
931     bc->ymax = max_r>min_r? max_r : min_r;
932     bc->width = dx;
933     bc->vwidth = b->pixelsize;
934     bc->bytes_per_line = ((bc->xmax-bc->xmin+8)>>3);
935     bc->bitmap = calloc(bc->bytes_per_line*(bc->ymax-bc->ymin+1),1);
936 
937     if ( sf->glyphs[gid]->layers[ly_fore].splines==NULL && sf->glyphs[gid]->layers[ly_fore].refs==NULL &&
938 	    !sf->glyphs[gid]->widthset ) {
939 	sf->glyphs[gid]->width = aw;
940 	sf->glyphs[gid]->widthset = true;
941     }
942 
943     for ( r=min_r, c=min_c, col=0; r<=max_r; ) {
944 	gf_skip_noops(gf,NULL);
945 	ch = getc(gf);
946 	if ( ch==gf_eoc )
947     break;
948 	if ( ch>=gf_paint_0 && ch<=gf_paint3b ) {
949 	    if ( ch>=gf_paint_0 && ch<=gf_paint_63 )
950 		cnt = ch-gf_paint_0;
951 	    else if ( ch==gf_paint1b )
952 		cnt = getc(gf);
953 	    else if ( ch==gf_paint2b )
954 		cnt = getushort(gf);
955 	    else
956 		cnt = get3byte(gf);
957 	    if ( col ) {
958 		for ( i=0; i<cnt && c<=max_c; ++i ) {
959 		    bc->bitmap[(r-min_r)*bc->bytes_per_line+((c-min_c)>>3)]
960 			    |= (0x80>>((c-min_c)&7));
961 		    ++c;
962 		    /*if ( c>max_c ) { c-=max_c-min_c; ++r; }*/
963 		}
964 	    } else {
965 		c+=cnt;
966 		/*while ( c>max_c ) { c-=max_c-min_c; ++r; }*/
967 	    }
968 	    col = !col;
969 	} else if ( ch>=gf_newrow_0 && ch<=gf_newrow_164 ) {
970 	    ++r;
971 	    c = min_c + ch-gf_newrow_0;
972 	    col = 1;
973 	} else if ( ch>=gf_skip0 && ch<=gf_skip3 ) {
974 	    col = 0;
975 	    c = min_c;
976 	    if ( ch==gf_skip0 )
977 		++r;
978 	    else if ( ch==gf_skip1 )
979 		r += getc(gf)+1;
980 	    else if ( ch==gf_skip2 )
981 		r += getushort(gf)+1;
982 	    else
983 		r += get3byte(gf)+1;
984 	} else if ( ch==EOF ) {
985 	    LogError( _("Unexpected EOF in gf\n") );
986     break;
987 	} else
988 	    LogError( _("Uninterpreted code in gf: %d\n"), ch);
989     }
990     fseek(gf,pos,SEEK_SET);
991 return( true );
992 }
993 
994 /* ******************************** PK (TeX) ******************************** */
995 
996 enum pk_cmd { pk_rrr1=240, pk_rrr2, pk_rrr3, pk_rrr4, pk_yyy, pk_post, pk_no_op,
997 	pk_pre, pk_version_number=89 };
pk_skip_noops(FILE * pk)998 static void pk_skip_noops(FILE *pk) {
999     uint8 cmd;
1000     int32 val;
1001     int i;
1002 
1003     while ( 1 ) {
1004 	cmd = getc(pk);
1005 	switch( cmd ) {
1006 	  case pk_no_op:		/* One byte no-op */
1007 	  break;
1008 	  case pk_post:			/* Signals start of noop section */
1009 	  break;
1010 	  case pk_yyy:			/* followed by a 4 byte value */
1011 	    getc(pk); getc(pk); getc(pk); getc(pk);
1012 	  break;
1013 	  case pk_rrr1:
1014 	    val = getc(pk);
1015 	    for ( i=0; i<val; ++i ) getc(pk);
1016 	  break;
1017 	  case pk_rrr2:
1018 	    val = getc(pk);
1019 	    val = (val<<8) | getc(pk);
1020 	    for ( i=0; i<val; ++i ) getc(pk);
1021 	  break;
1022 	  case pk_rrr3:
1023 	    val = getc(pk);
1024 	    val = (val<<8) | getc(pk);
1025 	    val = (val<<8) | getc(pk);
1026 	    for ( i=0; i<val; ++i ) getc(pk);
1027 	  break;
1028 	  case pk_rrr4:
1029 	    val = getc(pk);
1030 	    val = (val<<8) | getc(pk);
1031 	    val = (val<<8) | getc(pk);
1032 	    val = (val<<8) | getc(pk);
1033 	    for ( i=0; i<val; ++i ) getc(pk);
1034 	  break;
1035 	  default:
1036 	    ungetc(cmd,pk);
1037 return;
1038 	}
1039     }
1040 }
1041 
pk_header(FILE * pk,int * _as,int * _ds,Encoding ** _enc,char * family,char * mods,char * full,char * filename)1042 static int pk_header(FILE *pk, int *_as, int *_ds, Encoding **_enc, char *family,
1043 	char *mods, char *full, char *filename) {
1044     int pixelsize=-1;
1045     int ch,i;
1046     int design_size, pixels_per_point;
1047     double size;
1048     char *pt, *fpt;
1049 
1050     pk_skip_noops(pk);
1051     ch = getc(pk);
1052     if ( ch!=pk_pre )
1053 return( -2 );
1054     ch = getc(pk);
1055     if ( ch!=pk_version_number )
1056 return( -2 );
1057     ch = getc(pk);
1058     for ( i=0; i<ch; ++i ) getc(pk);		/* Skip comment. Perhaps that should be the family? */
1059     design_size = getlong(pk);
1060     /* checksum = */ getlong(pk);
1061     pixels_per_point = getlong(pk);
1062     /* vert pixels per point = */ getlong(pk);
1063 
1064     size = (pixels_per_point / 65536.0) * (design_size / (double) (0x100000));
1065     pixelsize = size+.5;
1066     *_enc = &custom;
1067     *_as = *_ds = -1;
1068     *mods = '\0';
1069     pt = strrchr(filename, '/');
1070     if ( pt==NULL ) pt = filename; else ++pt;
1071     for ( fpt=family; isalpha(*pt);)
1072 	*fpt++ = *pt++;
1073     *fpt = '\0';
1074     strcpy(full,family);
1075 
1076 return( pixelsize );
1077 }
1078 
1079 struct pkstate {
1080     int byte, hold;
1081     int rpt;
1082     int dyn_f;
1083     int cc;		/* for debug purposes */
1084 };
1085 
pkgetcount(FILE * pk,struct pkstate * st)1086 static int pkgetcount(FILE *pk, struct pkstate *st) {
1087     int i,j;
1088 #define getnibble(pk,st) (st->hold==1?(st->hold=0,(st->byte&0xf)):(st->hold=1,(((st->byte=getc(pk))>>4))) )
1089 
1090     while ( 1 ) {
1091 	i = getnibble(pk,st);
1092 	if ( i==0 ) {
1093 	    j=0;
1094 	    while ( i==0 ) { ++j; i=getnibble(pk,st); }
1095 	    while ( j>0 ) { --j; i = (i<<4) + getnibble(pk,st); }
1096 return( i-15 + (13-st->dyn_f)*16 + st->dyn_f );
1097 	} else if ( i<=st->dyn_f ) {
1098 return( i );
1099 	} else if ( i<14 ) {
1100 return( (i-st->dyn_f-1)*16 + getnibble(pk,st) + st->dyn_f + 1 );
1101 	} else {
1102 	    if ( st->rpt!=0 )
1103 		LogError( _("Duplicate repeat row count in char %d of pk file\n"), st->cc );
1104 	    if ( i==15 ) st->rpt = 1;
1105 	    else st->rpt = pkgetcount(pk,st);
1106  /*printf( "[%d]", st->rpt );*/
1107 	}
1108     }
1109 }
1110 
pk_char(FILE * pk,SplineFont * sf,BDFFont * b,EncMap * map)1111 static int pk_char(FILE *pk, SplineFont *sf, BDFFont *b, EncMap *map) {
1112     int flag = getc(pk);
1113     int black;
1114     int pl, cc, tfm, w, h, hoff, voff, dm, dx;
1115     int i, ch, j,r,c,cnt;
1116     int gid;
1117     BDFChar *bc;
1118     struct pkstate st;
1119     int32 char_end;
1120 
1121     memset(&st,'\0', sizeof(st));
1122 
1123     /* flag byte */
1124     st.dyn_f = (flag>>4);
1125     if ( st.dyn_f==15 ) {
1126 	ungetc(flag,pk);
1127 return( 0 );
1128     }
1129     black = flag&8 ? 1 : 0;
1130 
1131     if ( (flag&7)==7 ) {		/* long preamble, 4 byte sizes */
1132 	pl = getlong(pk);
1133 	cc = getlong(pk);
1134 	char_end = ftell(pk) + pl;
1135 	tfm = getlong(pk);
1136 	dx = getlong(pk)>>16;
1137         /* dy */ (void)(getlong(pk)>>16);
1138 	w = getlong(pk);
1139 	h = getlong(pk);
1140 	hoff = getlong(pk);
1141 	voff = getlong(pk);
1142     } else if ( flag & 4 ) {		/* extended preamble, 2 byte sizes */
1143 	pl = getushort(pk) + ((flag&3)<<16);
1144 	cc = getc(pk);
1145 	char_end = ftell(pk) + pl;
1146 	tfm = get3byte(pk);
1147 	dm = getushort(pk);
1148 	dx = dm;
1149 	w = getushort(pk);
1150 	h = getushort(pk);
1151 	hoff = (short) getushort(pk);
1152 	voff = (short) getushort(pk);
1153     } else {				/* short, 1 byte sizes */
1154 	pl = getc(pk) + ((flag&3)<<8);
1155 	cc = getc(pk);
1156 	char_end = ftell(pk) + pl;
1157 	tfm = get3byte(pk);
1158 	dm = getc(pk);
1159 	dx = dm;
1160 	w = getc(pk);
1161 	h = getc(pk);
1162 	hoff = (signed char) getc(pk);
1163 	voff = (signed char) getc(pk);
1164     }
1165     st.cc = cc;			/* We can give better errors with this in st */
1166     /* hoff is -xmin, voff is ymax */
1167     /* w,h is the width,height of the bounding box */
1168     /* dx is the advance width? */
1169     /* cc is the character code */
1170     /* tfm is the advance width as a fraction of an em/2^20 so multiply by 1000/2^20 to get postscript values */
1171     /* dy is the advance height for vertical text? */
1172 
1173     bc = SFGrowTo(sf,b,cc,map);
1174     gid = map->map[cc];
1175 
1176     bc->xmin = -hoff;
1177     bc->ymax = voff;
1178     bc->xmax = w-1-hoff;
1179     bc->ymin = voff-h+1;
1180     bc->width = dx;
1181     bc->vwidth = b->pixelsize;
1182     bc->bytes_per_line = ((w+7)>>3);
1183     bc->bitmap = calloc(bc->bytes_per_line*h,1);
1184 
1185     if ( sf->glyphs[gid]->layers[ly_fore].splines==NULL && sf->glyphs[gid]->layers[ly_fore].refs==NULL &&
1186 	    !sf->glyphs[gid]->widthset ) {
1187 	sf->glyphs[gid]->width = (sf->ascent+sf->descent)*(double) tfm/(0x100000);
1188 	sf->glyphs[gid]->widthset = true;
1189     }
1190 
1191     if ( w==0 && h==0 )
1192 	/* Nothing */;
1193     else if ( st.dyn_f==14 ) {
1194 	/* We've got raster data in the file */
1195 	for ( i=0; i<((w*h+7)>>3); ++i ) {
1196 	    ch = getc(pk);
1197 	    for ( j=0; j<8; ++j ) {
1198 		r = ((i<<3)+j)/w;
1199 		c = ((i<<3)+j)%w;
1200 		if ( r<h && (ch&(1<<(7-j))) )
1201 		    bc->bitmap[r*bc->bytes_per_line+(c>>3)] |= (1<<(7-(c&7)));
1202 	    }
1203 	    if ( ftell(pk)>char_end )
1204 	break;
1205 	}
1206     } else {
1207 	/* We've got run-length encoded data */
1208 	r = c = 0;
1209 	while ( r<h ) {
1210 	    cnt = pkgetcount(pk,&st);
1211   /* if ( black ) printf( "%d", cnt ); else printf( "(%d)", cnt );*/
1212 	    if ( c+cnt>=w && st.rpt!=0 ) {
1213 		if ( black ) {
1214 		    while ( c<w ) {
1215 			bc->bitmap[r*bc->bytes_per_line+(c>>3)] |= (1<<(7-(c&7)));
1216 			--cnt;
1217 			++c;
1218 		    }
1219 		} else
1220 		    cnt -= (w-c);
1221 		for ( i=0; i<st.rpt && r+i+1<h; ++i )
1222 		    memcpy(bc->bitmap+(r+i+1)*bc->bytes_per_line,
1223 			    bc->bitmap+r*bc->bytes_per_line,
1224 			    bc->bytes_per_line );
1225 		r += st.rpt+1;
1226 		c = 0;
1227 		st.rpt = 0;
1228 	    }
1229 	    while ( cnt>0 && r<h ) {
1230 		while ( c<w && cnt>0) {
1231 		    if ( black )
1232 			bc->bitmap[r*bc->bytes_per_line+(c>>3)] |= (1<<(7-(c&7)));
1233 		    --cnt;
1234 		    ++c;
1235 		}
1236 		if ( c==w ) {
1237 		    c = 0;
1238 		    ++r;
1239 		}
1240 	    }
1241 	    black = !black;
1242 	    if ( ftell(pk)>char_end )
1243 	break;
1244 	}
1245     }
1246     if ( ftell(pk)!=char_end ) {
1247 	LogError(_("The character, %d, was not read properly (or pk file is in bad format)\n At %ld should be %d, off by %ld\n"), cc, ftell(pk), char_end, ftell(pk)-char_end );
1248 	fseek(pk,char_end,SEEK_SET);
1249     }
1250  /* printf( "\n" ); */
1251 return( 1 );
1252 }
1253 
1254 /* ****************************** PCF *************************************** */
1255 
1256 struct toc {
1257     int type;
1258     int format;
1259     int size;		/* in 32bit words */
1260     int offset;
1261 };
1262 
1263 #define PCF_FILE_VERSION	(('p'<<24)|('c'<<16)|('f'<<8)|1)
1264 
1265     /* table types */
1266 #define PCF_PROPERTIES		    (1<<0)
1267 #define PCF_ACCELERATORS	    (1<<1)
1268 #define PCF_METRICS		    (1<<2)
1269 #define PCF_BITMAPS		    (1<<3)
1270 #define PCF_INK_METRICS		    (1<<4)
1271 #define	PCF_BDF_ENCODINGS	    (1<<5)
1272 #define PCF_SWIDTHS		    (1<<6)
1273 #define PCF_GLYPH_NAMES		    (1<<7)
1274 #define PCF_BDF_ACCELERATORS	    (1<<8)
1275 
1276     /* formats */
1277 #define PCF_DEFAULT_FORMAT	0x00000000
1278 #define PCF_INKBOUNDS		0x00000200
1279 #define PCF_ACCEL_W_INKBOUNDS	0x00000100
1280 #define PCF_COMPRESSED_METRICS	0x00000100
1281 
1282 #define PCF_GLYPH_PAD_MASK	(3<<0)
1283 #define PCF_BYTE_MASK		(1<<2)
1284 #define PCF_BIT_MASK		(1<<3)
1285 #define PCF_SCAN_UNIT_MASK	(3<<4)
1286 
1287 #define	PCF_FORMAT_MASK		0xffffff00
1288 #define PCF_FORMAT_MATCH(a,b) (((a)&PCF_FORMAT_MASK) == ((b)&PCF_FORMAT_MASK))
1289 
1290 #define MSBFirst	1
1291 #define LSBFirst	0
1292 
1293 #define PCF_BYTE_ORDER(f)	(((f) & PCF_BYTE_MASK)?MSBFirst:LSBFirst)
1294 #define PCF_BIT_ORDER(f)	(((f) & PCF_BIT_MASK)?MSBFirst:LSBFirst)
1295 #define PCF_GLYPH_PAD_INDEX(f)	((f) & PCF_GLYPH_PAD_MASK)
1296 #define PCF_GLYPH_PAD(f)	(1<<PCF_GLYPH_PAD_INDEX(f))
1297 #define PCF_SCAN_UNIT_INDEX(f)	(((f) & PCF_SCAN_UNIT_MASK) >> 4)
1298 #define PCF_SCAN_UNIT(f)	(1<<PCF_SCAN_UNIT_INDEX(f))
1299 
1300 #define GLYPHPADOPTIONS	4
1301 
1302 struct pcfmetrics {
1303     short lsb;
1304     short rsb;
1305     short width;
1306     short ascent;
1307     short descent;
1308     short attrs;
1309 };
1310 
1311 struct pcfaccel {
1312     unsigned int noOverlap:1;
1313     unsigned int constantMetrics:1;
1314     unsigned int terminalFont:1;
1315     unsigned int constantWidth:1;
1316     unsigned int inkInside:1;
1317     unsigned int inkMetrics:1;
1318     unsigned int drawDirection:1;
1319     int ascent;
1320     int descent;
1321     int maxOverlap;
1322     struct pcfmetrics minbounds;
1323     struct pcfmetrics maxbounds;
1324     struct pcfmetrics ink_minbounds;
1325     struct pcfmetrics ink_maxbounds;
1326 };
1327 /* End declarations */
1328 
1329 /* Code based on Keith Packard's pcfread.c in the X11 distribution */
1330 
getint32(FILE * file)1331 static int getint32(FILE *file) {
1332     int val = getc(file);
1333     val |= (getc(file)<<8);
1334     val |= (getc(file)<<16);
1335     val |= (getc(file)<<24);
1336 return( val );
1337 }
1338 
getformint32(FILE * file,int format)1339 static int getformint32(FILE *file,int format) {
1340     int val;
1341     if ( format&PCF_BYTE_MASK ) {
1342 	val = getc(file);
1343 	val = (val<<8) | getc(file);
1344 	val = (val<<8) | getc(file);
1345 	val = (val<<8) | getc(file);
1346     } else {
1347 	val = getc(file);
1348 	val |= (getc(file)<<8);
1349 	val |= (getc(file)<<16);
1350 	val |= (getc(file)<<24);
1351     }
1352 return( val );
1353 }
1354 
getformint16(FILE * file,int format)1355 static int getformint16(FILE *file,int format) {
1356     int val;
1357     if ( format&PCF_BYTE_MASK ) {
1358 	val = getc(file);
1359 	val = (val<<8) | getc(file);
1360     } else {
1361 	val = getc(file);
1362 	val |= (getc(file)<<8);
1363     }
1364 return( val );
1365 }
1366 
pcfReadTOC(FILE * file)1367 static struct toc *pcfReadTOC(FILE *file) {
1368     int cnt, i;
1369     struct toc *toc;
1370 
1371     if ( getint32(file)!=PCF_FILE_VERSION )
1372 return( NULL );
1373     cnt = getint32(file);
1374     toc = calloc(cnt+1,sizeof(struct toc));
1375     for ( i=0; i<cnt; ++i ) {
1376 	toc[i].type = getint32(file);
1377 	toc[i].format = getint32(file);
1378 	toc[i].size = getint32(file);
1379 	toc[i].offset = getint32(file);
1380     }
1381 
1382 return( toc );
1383 }
1384 
pcfSeekToType(FILE * file,struct toc * toc,int type)1385 static int pcfSeekToType(FILE *file, struct toc *toc, int type) {
1386     int i;
1387 
1388     for ( i=0; toc[i].type!=0 && toc[i].type!=type; ++i );
1389     if ( toc[i].type==0 )
1390 return( false );
1391     fseek(file,toc[i].offset,SEEK_SET);
1392 return( true );
1393 }
1394 
pcfGetMetrics(FILE * file,int compressed,int format,struct pcfmetrics * metric)1395 static void pcfGetMetrics(FILE *file,int compressed,int format,struct pcfmetrics *metric) {
1396     if ( compressed ) {
1397 	metric->lsb = getc(file)-0x80;
1398 	metric->rsb = getc(file)-0x80;
1399 	metric->width = getc(file)-0x80;
1400 	metric->ascent = getc(file)-0x80;
1401 	metric->descent = getc(file)-0x80;
1402 	metric->attrs = 0;
1403     } else {
1404 	metric->lsb = getformint16(file,format);
1405 	metric->rsb = getformint16(file,format);
1406 	metric->width = getformint16(file,format);
1407 	metric->ascent = getformint16(file,format);
1408 	metric->descent = getformint16(file,format);
1409 	metric->attrs = getformint16(file,format);
1410     }
1411 }
1412 
pcfGetAccel(FILE * file,struct toc * toc,int which,struct pcfaccel * accel)1413 static int pcfGetAccel(FILE *file, struct toc *toc,int which, struct pcfaccel *accel) {
1414     int format;
1415 
1416     if ( !pcfSeekToType(file,toc,which))
1417 return(false);
1418     format = getint32(file);
1419     if ( (format&PCF_FORMAT_MASK)!=PCF_DEFAULT_FORMAT &&
1420 	    (format&PCF_FORMAT_MASK)!=PCF_ACCEL_W_INKBOUNDS )
1421 return(false);
1422     accel->noOverlap = getc(file);
1423     accel->constantMetrics = getc(file);
1424     accel->terminalFont = getc(file);
1425     accel->constantWidth = getc(file);
1426     accel->inkInside = getc(file);
1427     accel->inkMetrics = getc(file);
1428     accel->drawDirection = getc(file);
1429     /* padding = */ getc(file);
1430     accel->ascent = getformint32(file,format);
1431     accel->descent = getformint32(file,format);
1432     accel->maxOverlap = getformint32(file,format);
1433     pcfGetMetrics(file,false,format,&accel->minbounds);
1434     pcfGetMetrics(file,false,format,&accel->maxbounds);
1435     if ( (format&PCF_FORMAT_MASK)==PCF_ACCEL_W_INKBOUNDS ) {
1436 	pcfGetMetrics(file,false,format,&accel->ink_minbounds);
1437 	pcfGetMetrics(file,false,format,&accel->ink_maxbounds);
1438     } else {
1439 	accel->ink_minbounds = accel->minbounds;
1440 	accel->ink_maxbounds = accel->maxbounds;
1441     }
1442 return( true );
1443 }
1444 
pcf_properties(FILE * file,struct toc * toc,int * _as,int * _ds,Encoding ** _enc,char * family,char * mods,char * full,BDFFont * dummy,char * filename)1445 static int pcf_properties(FILE *file,struct toc *toc, int *_as, int *_ds,
1446 	Encoding **_enc, char *family, char *mods, char *full, BDFFont *dummy,
1447 	char *filename) {
1448     int pixelsize = -1, point_size = -1, res = -1;
1449     int ascent= -1, descent= -1, enc=0;
1450     char encname[101], weight[101], italic[101];
1451     int cnt, i, format, strl, dash_cnt;
1452     struct props { int name_offset; int isStr; int val; char *name; char *value; } *props;
1453     char *strs, *pt;
1454 
1455     family[0] = '\0'; full[0] = '\0';
1456     encname[0] = encname[100] = '\0';
1457     weight[0] = weight[100] = '\0';
1458     italic[0] = italic[100] = '\0';
1459     if ( !pcfSeekToType(file,toc,PCF_PROPERTIES))
1460 return(-2);
1461     format = getint32(file);
1462     if ( (format&PCF_FORMAT_MASK)!=PCF_DEFAULT_FORMAT )
1463 return(-2);
1464     cnt = getformint32(file,format);
1465     props = malloc(cnt*sizeof(struct props));
1466     for ( i=0; i<cnt; ++i ) {
1467 	props[i].name_offset = getformint32(file,format);
1468 	props[i].isStr = getc(file);
1469 	props[i].val = getformint32(file,format);
1470     }
1471     if ( cnt&3 )
1472 	fseek(file,4-(cnt&3),SEEK_CUR);
1473     strl = getformint32(file,format);
1474     strs = malloc(strl+1);
1475     strs[strl]=0;
1476     fread(strs,1,strl,file);
1477     for ( i=0; i<cnt; ++i ) {
1478 	props[i].name = strs+props[i].name_offset;
1479 	if ( props[i].isStr )
1480 	    props[i].value = strs+props[i].val;
1481 	else
1482 	    props[i].value = NULL;
1483     }
1484 
1485     /* the properties here are almost exactly the same as the bdf ones */
1486     /* except that FONT is a pcf property, and SIZE etc. aren't mentioned */
1487 
1488     dummy->prop_cnt = cnt;
1489     dummy->props = malloc(cnt*sizeof(BDFProperties));
1490 
1491     for ( i=0; i<cnt; ++i ) {
1492 	dummy->props[i].name = copy(props[i].name);
1493 	if ( props[i].isStr ) {
1494 	    dummy->props[i].u.str = copy(props[i].value);
1495 	    dummy->props[i].type  = prt_string | prt_property;
1496 	    if ( strcmp(props[i].name,"FAMILY_NAME")==0 )
1497 		strcpy(family,props[i].value);
1498 	    else if ( strcmp(props[i].name,"WEIGHT_NAME")==0 )
1499 		strncpy(weight,props[i].value,sizeof(weight)-1);
1500 	    else if ( strcmp(props[i].name,"FULL_NAME")==0 )
1501 		strcpy(full,props[i].value);
1502 	    else if ( strcmp(props[i].name,"SLANT")==0 )
1503 		strncpy(italic,props[i].value,sizeof(italic)-1);
1504 	    else if ( strcmp(props[i].name,"CHARSET_REGISTRY")==0 )
1505 		strncpy(encname,props[i].value,sizeof(encname)-1);
1506 	    else if ( strcmp(props[i].name,"CHARSET_ENCODING")==0 )
1507 		enc = strtol(props[i].value,NULL,10);
1508 	    else if ( strcmp(props[i].name,"FONT")==0 ) {
1509 		dummy->props[i].type = prt_atom;
1510 		if ( sscanf(props[i].value,"-%*[^-]-%[^-]-%[^-]-%[^-]-%*[^-]-",
1511 			family, weight, italic )!=0 ) {
1512 		    for ( pt = props[i].value, dash_cnt=0; *pt && dash_cnt<7; ++pt )
1513 			if ( *pt=='-' ) ++dash_cnt;
1514 		    if ( dash_cnt==7 && isdigit(*pt) )
1515 			pixelsize = strtol(pt,NULL,10);
1516 		}
1517 	    }
1518 	} else {
1519 	    dummy->props[i].u.val = props[i].val;
1520 	    dummy->props[i].type  = (IsUnsignedBDFKey(dummy->props[i].name)?prt_uint:prt_int) | prt_property;
1521 	    if ( strcmp(props[i].name,"PIXEL_SIZE")==0 ||
1522 		    ( pixelsize==-1 && strcmp(props[i].name,"QUAD_WIDTH")==0 ))
1523 		pixelsize = props[i].val;
1524 	    else if ( strcmp(props[i].name,"FONT_ASCENT")==0 )
1525 		ascent = props[i].val;
1526 	    else if ( strcmp(props[i].name,"FONT_DESCENT")==0 )
1527 		descent = props[i].val;
1528 	    else if ( strcmp(props[i].name,"POINT_SIZE")==0 )
1529 		point_size = props[i].val;
1530 	    else if ( strcmp(props[i].name,"RESOLUTION_Y")==0 )
1531 		res = props[i].val;
1532 	    else if ( strcmp(props[i].name,"CHARSET_ENCODING")==0 )
1533 		enc = props[i].val;
1534 	}
1535     }
1536     if ( ascent==-1 || descent==-1 ) {
1537 	struct pcfaccel accel;
1538 	if ( pcfGetAccel(file,toc,PCF_BDF_ACCELERATORS,&accel) ||
1539 		pcfGetAccel(file,toc,PCF_ACCELERATORS,&accel)) {
1540 	    ascent = accel.ascent;
1541 	    descent = accel.descent;
1542 	    if ( pixelsize==-1 )
1543 		pixelsize = ascent+descent;
1544 	}
1545     }
1546     pixelsize = default_ascent_descent(_as, _ds, ascent, descent, pixelsize,
1547 	    -1, point_size, res, filename );
1548 
1549     *_enc = BDFParseEnc(encname,enc);
1550 
1551     if ( strmatch(italic,"I")==0 )
1552 	strcpy(italic,"Italic");
1553     else if ( strmatch(italic,"O")==0 )
1554 	strcpy(italic,"Oblique");
1555     else if ( strmatch(italic,"R")==0 )
1556 	strcpy(italic,"");		/* Ignore roman */
1557     sprintf(mods,"%s%s", weight, italic );
1558     if ( full[0]=='\0' ) {
1559 	if ( *mods )
1560 	    sprintf(full,"%s-%s", family, mods );
1561 	else
1562 	    strcpy(full,family);
1563     }
1564 
1565     free(strs);
1566     free(props);
1567 
1568 return( pixelsize );
1569 }
1570 
pcfGetMetricsTable(FILE * file,struct toc * toc,int which,int * metrics_cnt)1571 static struct pcfmetrics *pcfGetMetricsTable(FILE *file, struct toc *toc,int which, int *metrics_cnt) {
1572     int format, cnt, i;
1573     struct pcfmetrics *metrics;
1574 
1575     if ( !pcfSeekToType(file,toc,which))
1576 return(NULL);
1577     format = getint32(file);
1578     if ( (format&PCF_FORMAT_MASK)!=PCF_DEFAULT_FORMAT &&
1579 	    (format&PCF_FORMAT_MASK)!=PCF_COMPRESSED_METRICS )
1580 return(NULL);
1581     if ( (format&PCF_FORMAT_MASK)==PCF_COMPRESSED_METRICS ) {
1582 	cnt = getformint16(file,format);
1583 	metrics = malloc(cnt*sizeof(struct pcfmetrics));
1584 	for ( i=0; i<cnt; ++i )
1585 	    pcfGetMetrics(file,true,format,&metrics[i]);
1586     } else {
1587 	cnt = getformint32(file,format);
1588 	metrics = malloc(cnt*sizeof(struct pcfmetrics));
1589 	for ( i=0; i<cnt; ++i )
1590 	    pcfGetMetrics(file,false,format,&metrics[i]);
1591     }
1592     *metrics_cnt = cnt;
1593 return( metrics );
1594 }
1595 
1596 static uint8 bitinvert[] = {
1597 	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
1598 	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1599 	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1600 	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1601 	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
1602 	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1603 	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
1604 	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1605 	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1606 	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1607 	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1608 	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1609 	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1610 	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1611 	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1612 	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1613 	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1614 	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1615 	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1616 	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1617 	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1618 	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1619 	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1620 	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1621 	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1622 	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1623 	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1624 	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1625 	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1626 	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1627 	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1628 	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
1629 };
1630 
BitOrderInvert(uint8 * bitmap,int sizebitmaps)1631 static void BitOrderInvert(uint8 *bitmap,int sizebitmaps) {
1632     int i;
1633 
1634     for ( i=0; i<sizebitmaps; ++i )
1635 	bitmap[i] = bitinvert[bitmap[i]];
1636 }
1637 
TwoByteSwap(uint8 * bitmap,int sizebitmaps)1638 static void TwoByteSwap(uint8 *bitmap,int sizebitmaps) {
1639     int i, t;
1640 
1641     for ( i=0; i<sizebitmaps-1; i+=2 ) {
1642 	t = bitmap[i];
1643 	bitmap[i] = bitmap[i+1];
1644 	bitmap[i+1] = t;
1645     }
1646 }
1647 
FourByteSwap(uint8 * bitmap,int sizebitmaps)1648 static void FourByteSwap(uint8 *bitmap,int sizebitmaps) {
1649     int i, t;
1650 
1651     for ( i=0; i<sizebitmaps-1; i+=4 ) {
1652 	t = bitmap[i];
1653 	bitmap[i] = bitmap[i+3];
1654 	bitmap[i+3] = t;
1655 	t = bitmap[i+1];
1656 	bitmap[i+1] = bitmap[i+2];
1657 	bitmap[i+2] = t;
1658     }
1659 }
1660 
PcfReadBitmaps(FILE * file,struct toc * toc,BDFFont * b)1661 static int PcfReadBitmaps(FILE *file,struct toc *toc,BDFFont *b) {
1662     int format, cnt, i, sizebitmaps, j;
1663     int *offsets;
1664     uint8 *bitmap;
1665     int bitmapSizes[GLYPHPADOPTIONS];
1666 
1667     if ( !pcfSeekToType(file,toc,PCF_BITMAPS))
1668 return(false);
1669     format = getint32(file);
1670     if ( (format&PCF_FORMAT_MASK)!=PCF_DEFAULT_FORMAT )
1671 return(false);
1672 
1673     cnt = getformint32(file,format);
1674     if ( cnt!=b->glyphcnt )
1675 return( false );
1676     offsets = malloc(cnt*sizeof(int));
1677     for ( i=0; i<cnt; ++i )
1678 	offsets[i] = getformint32(file,format);
1679     for ( i=0; i<GLYPHPADOPTIONS; ++i )
1680 	bitmapSizes[i] = getformint32(file, format);
1681     sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX(format)];
1682     bitmap = malloc(sizebitmaps==0 ? 1 : sizebitmaps );
1683     fread(bitmap,1,sizebitmaps,file);
1684     if (PCF_BIT_ORDER(format) != MSBFirst )
1685 	BitOrderInvert(bitmap,sizebitmaps);
1686     if ( PCF_SCAN_UNIT(format)==1 )
1687 	/* Nothing to do */;
1688     else if ( PCF_BYTE_ORDER(format)==MSBFirst )
1689 	/* Nothing to do */;
1690     else if ( PCF_SCAN_UNIT(format)==2 )
1691 	TwoByteSwap(bitmap, sizebitmaps);
1692     else if ( PCF_SCAN_UNIT(format)==4 )
1693 	FourByteSwap(bitmap, sizebitmaps);
1694     if ( PCF_GLYPH_PAD(format)==1 ) {
1695 	for ( i=0; i<cnt; ++i ) {
1696 	    BDFChar *bc = b->glyphs[i];
1697 	    if ( i<cnt-1 && offsets[i+1]-offsets[i]!=bc->bytes_per_line * (bc->ymax-bc->ymin+1))
1698 		IError("Bad PCF glyph bitmap size");
1699 	    memcpy(bc->bitmap,bitmap+offsets[i],
1700 		    bc->bytes_per_line * (bc->ymax-bc->ymin+1));
1701 	    ff_progress_next();
1702 	}
1703     } else {
1704 	int pad = PCF_GLYPH_PAD(format);
1705 	for ( i=0; i<cnt; ++i ) {
1706 	    BDFChar *bc = b->glyphs[i];
1707 	    int bpl = ((bc->bytes_per_line+pad-1)/pad)*pad;
1708 	    for ( j=bc->ymin; j<=bc->ymax; ++j )
1709 		memcpy(bc->bitmap+(j-bc->ymin)*bc->bytes_per_line,
1710 			bitmap+offsets[i]+(j-bc->ymin)*bpl,
1711 			bc->bytes_per_line);
1712 	    ff_progress_next();
1713 	}
1714     }
1715     free(bitmap);
1716     free(offsets);
1717 return( true );
1718 }
1719 
PcfReadEncodingsNames(FILE * file,struct toc * toc,SplineFont * sf,EncMap * map,BDFFont * b,Encoding * encname)1720 static void PcfReadEncodingsNames(FILE *file,struct toc *toc,SplineFont *sf,
1721 	EncMap *map, BDFFont *b, Encoding *encname) {
1722     int format, cnt, i, stringsize;
1723     int *offsets=NULL;
1724     char *string=NULL;
1725     int *encs;
1726 
1727     encs = malloc(b->glyphcnt*sizeof(int));
1728     memset(encs,-1,b->glyphcnt*sizeof(int));
1729 
1730     if ( pcfSeekToType(file,toc,PCF_GLYPH_NAMES) &&
1731 	    ((format = getint32(file))&PCF_FORMAT_MASK)==PCF_DEFAULT_FORMAT &&
1732 	    (cnt = getformint32(file,format))==b->glyphcnt ) {
1733 	offsets = malloc(cnt*sizeof(int));
1734 	for ( i=0; i<cnt; ++i )
1735 	    offsets[i] = getformint32(file,format);
1736 	stringsize = getformint32(file,format);
1737 	string = malloc(stringsize);
1738 	fread(string,1,stringsize,file);
1739     }
1740     if ( pcfSeekToType(file,toc,PCF_BDF_ENCODINGS) &&
1741 	    ((format = getint32(file))&PCF_FORMAT_MASK)==PCF_DEFAULT_FORMAT ) {
1742 	int min2, max2, min1, max1, tot, glyph;
1743 	min2 = getformint16(file,format);
1744 	max2 = getformint16(file,format);
1745 	min1 = getformint16(file,format);
1746 	max1 = getformint16(file,format);
1747 	/* def */(void)getformint16(file,format);
1748 	tot = (max2-min2+1)*(max1-min1+1);
1749 	for ( i=0; i<tot; ++i ) {
1750 	    glyph = getformint16(file,format);
1751 	    if ( glyph!=0xffff && glyph<b->glyphcnt ) {
1752 		encs[glyph] = (i/(max2-min2+1) + min2)*256 +
1753 					(i%(max2-min2+1) + min1);
1754 	    }
1755 	}
1756     }
1757     cnt = b->glyphcnt;
1758     for ( i=0; i<cnt; ++i ) {
1759 	const char *name;
1760 	if ( string!=NULL ) name = string+offsets[i];
1761 	else name = ".notdef";
1762 	encs[i] = figureProperEncoding(sf,map,b,encs[i],name,-1,-1,encname);
1763 	if ( encs[i]!=-1 ) {
1764 	    int gid = map->map[encs[i]];
1765 	    if ( gid!=-1 ) {
1766 		b->glyphs[i]->sc = sf->glyphs[gid];
1767 		b->glyphs[i]->orig_pos = gid;
1768 	    }
1769 	}
1770     }
1771     free(string); free(offsets); free(encs);
1772 }
1773 
PcfReadSWidths(FILE * file,struct toc * toc,BDFFont * b)1774 static int PcfReadSWidths(FILE *file,struct toc *toc,BDFFont *b) {
1775     int format, cnt, i;
1776 
1777     if ( !pcfSeekToType(file,toc,PCF_SWIDTHS))
1778 return(false);
1779     format = getint32(file);
1780     if ( (format&PCF_FORMAT_MASK)!=PCF_DEFAULT_FORMAT )
1781 return(false);
1782 
1783     cnt = getformint32(file,format);
1784     if ( cnt>b->glyphcnt )
1785 return( false );
1786     for ( i=0; i<cnt; ++i ) {
1787 	int swidth = getformint32(file,format);
1788 	if ( b->glyphs[i]->sc!=NULL ) {
1789 	    b->glyphs[i]->sc->width = swidth;
1790 	    b->glyphs[i]->sc->widthset = true;
1791 	}
1792     }
1793 return( true );
1794 }
1795 
PcfParse(FILE * file,struct toc * toc,SplineFont * sf,EncMap * map,BDFFont * b,Encoding * encname)1796 static int PcfParse(FILE *file,struct toc *toc,SplineFont *sf,EncMap *map, BDFFont *b,
1797 	Encoding *encname) {
1798     int metrics_cnt;
1799     struct pcfmetrics *metrics = pcfGetMetricsTable(file,toc,PCF_METRICS,&metrics_cnt);
1800     int mcnt = metrics_cnt;
1801     BDFChar **new, **mult;
1802     int i, multcnt;
1803 
1804     if ( metrics==NULL )
1805 return( false );
1806     b->glyphcnt = b->glyphmax = mcnt;
1807     free(b->glyphs);
1808     b->glyphs = calloc(mcnt,sizeof(BDFChar *));
1809     for ( i=0; i<mcnt; ++i ) {
1810 	BDFChar *bc = b->glyphs[i] = chunkalloc(sizeof(BDFChar));
1811 	memset( bc,'\0',sizeof( BDFChar ));
1812 	bc->xmin = metrics[i].lsb;
1813 	bc->xmax = metrics[i].rsb-1;
1814 	if ( metrics[i].rsb==0 ) bc->xmax = 0;
1815 	bc->ymin = -metrics[i].descent;
1816 	bc->ymax = metrics[i].ascent-1;
1817 	if ( bc->ymax<bc->ymin || bc->xmax<bc->xmin ) {
1818 	    bc->ymax = bc->ymin-1;
1819 	    bc->xmax = bc->xmin-1;
1820 	}
1821 	/*if ( metrics[i].ascent==0 ) bc->ymax = 0;*/ /*??*/
1822 	bc->width = metrics[i].width;
1823 	bc->vwidth = b->pixelsize;	/* pcf doesn't support vmetrics */
1824 	bc->bytes_per_line = ((bc->xmax-bc->xmin)>>3) + 1;
1825 	bc->bitmap = malloc(bc->bytes_per_line*(bc->ymax-bc->ymin+1));
1826 	bc->orig_pos = -1;
1827     }
1828     free(metrics);
1829 
1830     if ( !PcfReadBitmaps(file,toc,b))
1831 return( false );
1832     PcfReadEncodingsNames(file,toc,sf,map,b,encname);
1833     if ( sf->onlybitmaps )
1834 	PcfReadSWidths(file,toc,b);
1835     new = calloc(sf->glyphcnt,sizeof(BDFChar *));
1836     mult = calloc(mcnt+1,sizeof(BDFChar *)); multcnt=0;
1837     for ( i=0; i<mcnt; ++i ) {
1838 	BDFChar *bc = b->glyphs[i];
1839 	if ( bc->orig_pos==-1 || bc->orig_pos>=sf->glyphcnt )
1840 	    BDFCharFree(bc);
1841 	else if ( new[bc->orig_pos]==NULL )
1842 	    new[bc->orig_pos] = bc;
1843 	else
1844 	    mult[multcnt++] = bc;
1845     }
1846     if ( multcnt!=0 ) {
1847 	for ( multcnt=0; mult[multcnt]!=NULL; multcnt++ ) {
1848 	    for ( i=0; i<sf->glyphcnt; ++i )
1849 		if ( new[i]==NULL ) {
1850 		    new[i] = mult[multcnt];
1851 	    break;
1852 		}
1853 	}
1854     }
1855     free( b->glyphs );
1856     free( mult );
1857     b->glyphs = new;
1858     b->glyphcnt = b->glyphmax = sf->glyphcnt;
1859 return( true );
1860 }
1861 
1862 /* ************************* End Bitmap Formats ***************************** */
1863 
askusersize(char * filename)1864 static int askusersize(char *filename) {
1865     char *pt;
1866     int guess;
1867     char *ret, *end;
1868     char def[10];
1869 
1870     for ( pt=filename; *pt && !isdigit(*pt); ++pt );
1871     guess = strtol(pt,NULL,10);
1872     if ( guess!=0 )
1873 	sprintf(def,"%d",guess);
1874     else
1875 	*def = '\0';
1876   retry:
1877     ret = ff_ask_string(_("Pixel size:"),def,_("What is the pixel size of the font in this file?"));
1878     if ( ret==NULL )
1879 	guess = -1;
1880     else {
1881 	guess = strtol(ret,&end,10);
1882 	free(ret);
1883 	if ( guess<=0 || *end!='\0' ) {
1884 	    ff_post_error(_("Bad Number"),_("Bad Number"));
1885   goto retry;
1886 	}
1887     }
1888 return( guess );
1889 }
1890 
alreadyexists(int pixelsize)1891 static int alreadyexists(int pixelsize) {
1892     int ret;
1893     char *buts[3];
1894     buts[0] = _("_OK");
1895     buts[1] = _("_Cancel");
1896     buts[2] = NULL;
1897 
1898     ret = ff_ask(_("Duplicate pixelsize"),(const char **) buts,0,1,
1899 	_("The font database already contains a bitmap\012font with this pixelsize (%d)\012Do you want to overwrite it?"),
1900 	pixelsize);
1901 
1902 return( ret==0 );
1903 }
1904 
BDFForceEnc(SplineFont * sf,EncMap * map)1905 static void BDFForceEnc(SplineFont *sf, EncMap *map) {
1906 /* jisx0208, jisx0212, ISO10646, ISO8859 */
1907     int i;
1908     BDFFont *bdf = sf->bitmaps;
1909     static struct bdf_2_ff_enc { const char *bdf, *ff; } bdf_2_ff_enc[] = {
1910 	/* A map between bdf encoding names and my internal ones */
1911 	{ "iso10646", "unicode" },
1912 	{ "unicode", "unicode" },
1913 	{ "jisx0208", "jis208" },
1914 	{ "jisx0212", "jis212" },
1915 	{ "jisx0201", "jis201" },
1916 	{ NULL, NULL }
1917     };
1918     char *fn, *pt;
1919     Encoding *enc;
1920 
1921     for ( i=0; i<bdf->prop_cnt; ++i )
1922 	if ( strcmp("FONT",bdf->props[i].name)==0 )
1923     break;
1924     if ( i==bdf->prop_cnt || (bdf->props[i].type&~prt_property)==prt_int ||
1925 	    (bdf->props[i].type&~prt_property)==prt_uint )
1926 return;
1927     fn = bdf->props[i].u.str;
1928     for ( pt = fn+strlen(fn)-1; pt>fn && *pt!='-'; --pt );
1929     for ( --pt; pt>fn && *pt!='-'; --pt );
1930     enc = NULL;
1931     if ( pt>fn )
1932 	enc = FindOrMakeEncoding(pt+1);
1933     if ( enc==NULL ) {
1934 	for ( i=0; bdf_2_ff_enc[i].bdf!=NULL; ++i )
1935 	    if ( strstrmatch(fn,bdf_2_ff_enc[i].bdf)!=NULL ) {
1936 		enc = FindOrMakeEncoding(bdf_2_ff_enc[i].ff);
1937 	break;
1938 	    }
1939     }
1940     if ( enc!=NULL )
1941 	SFForceEncoding(sf,map,enc);
1942 }
1943 
SFSetFontName(SplineFont * sf,char * family,char * mods,char * fullname)1944 void SFSetFontName(SplineFont *sf, char *family, char *mods,char *fullname) {
1945     char *full;
1946     char *n;
1947     char *pt, *tpt;
1948 
1949     n = malloc(strlen(family)+strlen(mods)+2);
1950     strcpy(n,family); strcat(n," "); strcat(n,mods);
1951     if ( fullname==NULL || *fullname == '\0' )
1952 	full = copy(n);
1953     else
1954 	full = copy(fullname);
1955     free(sf->fullname); sf->fullname = full;
1956 
1957     for ( pt=tpt=n; *pt; ) {
1958 	if ( !isspace(*pt))
1959 	    *tpt++ = *pt++;
1960 	else
1961 	    ++pt;
1962     }
1963     *tpt = '\0';
1964 
1965     /* In the URW world fontnames aren't just a simple concatenation of */
1966     /*  family name and modifiers, so neither the family name nor the modifiers */
1967     /*  changed, then don't change the font name */
1968     if ( strcmp(family,sf->familyname)==0 && strcmp(n,sf->fontname)==0 )
1969 	/* Don't change the fontname */
1970 	/* or anything else */
1971 	free(n);
1972     else {
1973 	free(sf->fontname); sf->fontname = n;
1974 	free(sf->familyname); sf->familyname = copy(family);
1975 	free(sf->weight); sf->weight = NULL;
1976 	if ( strstrmatch(mods,"extralight")!=NULL || strstrmatch(mods,"extra-light")!=NULL )
1977 	    sf->weight = copy("ExtraLight");
1978 	else if ( strstrmatch(mods,"demilight")!=NULL || strstrmatch(mods,"demi-light")!=NULL )
1979 	    sf->weight = copy("DemiLight");
1980 	else if ( strstrmatch(mods,"demibold")!=NULL || strstrmatch(mods,"demi-bold")!=NULL )
1981 	    sf->weight = copy("DemiBold");
1982 	else if ( strstrmatch(mods,"semibold")!=NULL || strstrmatch(mods,"semi-bold")!=NULL )
1983 	    sf->weight = copy("SemiBold");
1984 	else if ( strstrmatch(mods,"demiblack")!=NULL || strstrmatch(mods,"demi-black")!=NULL )
1985 	    sf->weight = copy("DemiBlack");
1986 	else if ( strstrmatch(mods,"extrabold")!=NULL || strstrmatch(mods,"extra-bold")!=NULL )
1987 	    sf->weight = copy("ExtraBold");
1988 	else if ( strstrmatch(mods,"extrablack")!=NULL || strstrmatch(mods,"extra-black")!=NULL )
1989 	    sf->weight = copy("ExtraBlack");
1990 	else if ( strstrmatch(mods,"book")!=NULL )
1991 	    sf->weight = copy("Book");
1992 	else if ( strstrmatch(mods,"regular")!=NULL )
1993 	    sf->weight = copy("Regular");
1994 	else if ( strstrmatch(mods,"roman")!=NULL )
1995 	    sf->weight = copy("Roman");
1996 	else if ( strstrmatch(mods,"normal")!=NULL )
1997 	    sf->weight = copy("Normal");
1998 	else if ( strstrmatch(mods,"demi")!=NULL )
1999 	    sf->weight = copy("Demi");
2000 	else if ( strstrmatch(mods,"medium")!=NULL )
2001 	    sf->weight = copy("Medium");
2002 	else if ( strstrmatch(mods,"bold")!=NULL )
2003 	    sf->weight = copy("Bold");
2004 	else if ( strstrmatch(mods,"heavy")!=NULL )
2005 	    sf->weight = copy("Heavy");
2006 	else if ( strstrmatch(mods,"black")!=NULL )
2007 	    sf->weight = copy("Black");
2008 	else if ( strstrmatch(mods,"Nord")!=NULL )
2009 	    sf->weight = copy("Nord");
2010 /* Sigh. URW uses 4 letter abreviations... */
2011 	else if ( strstrmatch(mods,"Regu")!=NULL )
2012 	    sf->weight = copy("Regular");
2013 	else if ( strstrmatch(mods,"Medi")!=NULL )
2014 	    sf->weight = copy("Medium");
2015 	else if ( strstrmatch(mods,"blac")!=NULL )
2016 	    sf->weight = copy("Black");
2017 	else
2018 	    sf->weight = copy("Medium");
2019     }
2020 
2021     FVSetTitles(sf);
2022 }
2023 
SFImportBDF(SplineFont * sf,char * filename,int ispk,int toback,EncMap * map)2024 static BDFFont *SFImportBDF(SplineFont *sf, char *filename,int ispk, int toback,
2025 	EncMap *map) {
2026     FILE *bdf;
2027     char tok[100];
2028     int pixelsize, ascent, descent;
2029     Encoding *enc;
2030     BDFFont *b;
2031     char family[100], mods[200], full[300], foundry[100], comments[1000], fontname[300];
2032     struct toc *toc=NULL;
2033     int depth=1;
2034     struct metrics defs;
2035     unsigned upos= (int) 0x80000000, uwidth = (int) 0x80000000;
2036     BDFFont dummy;
2037     int ch;
2038 
2039     memset(&dummy,0,sizeof(dummy));
2040 
2041     defs.swidth = defs.swidth1 = -1; defs.dwidth=defs.dwidth1=0;
2042     defs.metricsset = 0; defs.vertical_origin = 0;
2043     defs.res = -1;
2044     foundry[0] = '\0';
2045     fontname[0] = '\0';
2046     comments[0] = '\0';
2047 
2048     if ( ispk==1 && strcmp(filename+strlen(filename)-2,"gf")==0 )
2049 	ispk = 3;
2050     bdf = fopen(filename,"rb");
2051     if ( bdf==NULL ) {
2052 	ff_post_error(_("Couldn't open file"), _("Couldn't open file %.200s"), filename );
2053 return( NULL );
2054     }
2055     if ( ispk==1 ) {
2056 	pixelsize = pk_header(bdf,&ascent,&descent,&enc,family,mods,full, filename);
2057 	if ( pixelsize==-2 ) {
2058 	    fclose(bdf);
2059 	    ff_post_error(_("Not a pk file"), _("Not a (metafont) pk file %.200s"), filename );
2060 return( NULL );
2061 	}
2062     } else if ( ispk==3 ) {		/* gf */
2063 	pixelsize = gf_postamble(bdf,&ascent,&descent,&enc,family,mods,full, filename);
2064 	if ( pixelsize==-2 ) {
2065 	    fclose(bdf);
2066 	    ff_post_error(_("Not a gf file"), _("Not a (metafont) gf file %.200s"), filename );
2067 return( NULL );
2068 	}
2069     } else if ( ispk==2 ) {		/* pcf */
2070 	if (( toc = pcfReadTOC(bdf))== NULL ) {
2071 	    fclose(bdf);
2072 	    ff_post_error(_("Not a pcf file"), _("Not an X11 pcf file %.200s"), filename );
2073 return( NULL );
2074 	}
2075 	pixelsize = pcf_properties(bdf,toc,&ascent,&descent,&enc,family,mods,full,&dummy, filename);
2076 	if ( pixelsize==-2 ) {
2077 	    fclose(bdf); free(toc);
2078 	    ff_post_error(_("Not a pcf file"), _("Not an X11 pcf file %.200s"), filename );
2079 return( NULL );
2080 	}
2081     } else {
2082 	if ( gettoken(bdf,tok,sizeof(tok))==-1 || strcmp(tok,"STARTFONT")!=0 ) {
2083 	    fclose(bdf);
2084 	    ff_post_error(_("Not a bdf file"), _("Not a bdf file %.200s"), filename );
2085 return( NULL );
2086 	}
2087 	while ( (ch=getc(bdf))!='\n' && ch!='\r' && ch!=EOF );
2088 	pixelsize = slurp_header(bdf,&ascent,&descent,&enc,family,mods,full,
2089 		&depth,foundry,fontname,comments,&defs,&upos,&uwidth,&dummy,filename);
2090 	if ( defs.dwidth == 0 ) defs.dwidth = pixelsize;
2091 	if ( defs.dwidth1 == 0 ) defs.dwidth1 = pixelsize;
2092     }
2093     if ( pixelsize==-1 )
2094 	pixelsize = askusersize(filename);
2095     if ( pixelsize==-1 ) {
2096 	fclose(bdf); free(toc);
2097 return( NULL );
2098     }
2099     if ( /* !toback && */ sf->bitmaps==NULL && sf->onlybitmaps ) {
2100 	/* Loading first bitmap into onlybitmap font sets the name and encoding */
2101 	SFSetFontName(sf,family,mods,full);
2102 	if ( fontname[0]!='\0' ) {
2103 	    free(sf->fontname);
2104 	    sf->fontname = copy(fontname);
2105 	}
2106 	map->enc = enc;
2107 	if ( defs.metricsset!=0 ) {
2108 	    sf->hasvmetrics = true;
2109 	    /*sf->vertical_origin = defs.vertical_origin==0?sf->ascent:defs.vertical_origin;*/
2110 	}
2111 	sf->display_size = pixelsize;
2112 	if ( comments[0]!='\0' ) {
2113 	    free(sf->copyright);
2114 	    sf->copyright = copy(comments);
2115 	}
2116 	if ( upos!=0x80000000 )
2117 	    sf->upos = upos;
2118 	if ( uwidth!=0x80000000 )
2119 	    sf->upos = uwidth;
2120     }
2121 
2122     b = NULL;
2123     if ( !toback )
2124 	for ( b=sf->bitmaps; b!=NULL && (b->pixelsize!=pixelsize || BDFDepth(b)!=depth); b=b->next );
2125     if ( b!=NULL ) {
2126 	if ( !alreadyexists(pixelsize)) {
2127 	    fclose(bdf); free(toc);
2128 	    BDFPropsFree(&dummy);
2129 return( (BDFFont *) -1 );
2130 	}
2131     }
2132     if ( b==NULL ) {
2133 	if ( ascent==-1 && descent==-1 )
2134 	    ascent = rint(pixelsize*sf->ascent/(real) (sf->ascent+sf->descent));
2135 	if ( ascent==-1 && descent!=-1 )
2136 	    ascent = pixelsize - descent;
2137 	else if ( ascent!=-1 )
2138 	    descent = pixelsize -ascent;
2139 	b = calloc(1,sizeof(BDFFont));
2140 	b->sf = sf;
2141 	b->glyphcnt = b->glyphmax = sf->glyphcnt;
2142 	b->pixelsize = pixelsize;
2143 	b->glyphs = calloc(sf->glyphcnt,sizeof(BDFChar *));
2144 	b->ascent = ascent;
2145 	b->descent = pixelsize-b->ascent;
2146 	b->res = defs.res;
2147 	if ( depth!=1 )
2148 	    BDFClut(b,(1<<(depth/2)));
2149 	if ( !toback ) {
2150 	    b->next = sf->bitmaps;
2151 	    sf->bitmaps = b;
2152 	    SFOrderBitmapList(sf);
2153 	}
2154     }
2155     BDFPropsFree(b);
2156     b->prop_cnt = dummy.prop_cnt;
2157     b->props = dummy.props;
2158     free(b->foundry);
2159     b->foundry = ( foundry[0]=='\0' ) ? NULL : copy(foundry);
2160     if ( ispk==1 ) {
2161 	while ( pk_char(bdf,sf,b,map));
2162     } else if ( ispk==3 ) {
2163 	while ( gf_char(bdf,sf,b,map));
2164     } else if ( ispk==2 ) {
2165 	if ( !PcfParse(bdf,toc,sf,map,b,enc) ) {
2166 	    ff_post_error(_("Not a pcf file"), _("Not an X11 pcf file %.200s"), filename );
2167 	}
2168     } else {
2169 	while ( gettoken(bdf,tok,sizeof(tok))!=-1 ) {
2170 	    if ( strcmp(tok,"COMMENT")==0 ) {
2171 		int ch;
2172 		while ( (ch=getc(bdf))!=EOF && ch!='\n' && ch!='\r' );
2173 		if ( ch=='\r' ) {
2174 		    ch = getc(bdf);
2175 		    if ( ch!='\n' )
2176 			ungetc(ch,bdf);
2177 		}
2178 	    } else if ( strcmp(tok,"STARTCHAR")==0 ) {
2179 		AddBDFChar(bdf,sf,b,map,depth,&defs,enc);
2180 		ff_progress_next();
2181 	    }
2182 	}
2183     }
2184     fclose(bdf); free(toc);
2185     sf->changed = true;
2186     if ( sf->bitmaps!=NULL && sf->bitmaps->next==NULL && dummy.prop_cnt>0 &&
2187 	    map->enc == &custom )
2188 	BDFForceEnc(sf,map);
2189 return( b );
2190 }
2191 
_SFImportBDF(SplineFont * sf,char * filename,int ispk,int toback,EncMap * map)2192 static BDFFont *_SFImportBDF(SplineFont *sf, char *filename,int ispk, int toback, EncMap *map) {
2193     int i;
2194     char *pt, *temp=NULL;
2195     char buf[1500];
2196     BDFFont *ret;
2197 
2198     pt = strrchr(filename,'.');
2199     i = -1;
2200     if ( pt!=NULL ) for ( i=0; compressors[i].ext!=NULL; ++i )
2201 	if ( strcmp(compressors[i].ext,pt+1)==0 )
2202     break;
2203     if ( i==-1 || compressors[i].ext==NULL ) i=-1;
2204     else {
2205 	sprintf( buf, "%s %s", compressors[i].decomp, filename );
2206 	if ( system(buf)==0 )
2207 	    *pt='\0';
2208 	else {
2209 	    /* Assume no write access to file */
2210 	    char *dir = getenv("TMPDIR");
2211 	    if ( dir==NULL ) dir = P_tmpdir;
2212 	    temp = malloc(strlen(dir)+strlen(GFileNameTail(filename))+2);
2213 	    strcpy(temp,dir);
2214 	    strcat(temp,"/");
2215 	    strcat(temp,GFileNameTail(filename));
2216 	    *strrchr(temp,'.') = '\0';
2217 	    sprintf( buf, "%s -c %s > %s", compressors[i].decomp, filename, temp );
2218 	    if ( system(buf)==0 )
2219 		filename = temp;
2220 	    else {
2221 		free(temp);
2222 		ff_post_error(_("Decompress Failed!"),_("Decompress Failed!"));
2223 return( NULL );
2224 	    }
2225 	}
2226     }
2227     ret = SFImportBDF(sf, filename,ispk, toback, map);
2228     if ( temp!=NULL ) {
2229 	unlink(temp);
2230 	free(temp);
2231     } else if ( i!=-1 ) {
2232 	sprintf( buf, "%s %s", compressors[i].recomp, filename );
2233 	system(buf);
2234     }
2235 return( ret );
2236 }
2237 
SFSetupBitmap(SplineFont * sf,BDFFont * strike,EncMap * map)2238 static void SFSetupBitmap(SplineFont *sf,BDFFont *strike,EncMap *map) {
2239     int i;
2240     SplineChar *sc;
2241 
2242     strike->sf = sf;
2243     if ( strike->glyphcnt>sf->glyphcnt )
2244 	ExtendSF(sf,map,strike->glyphcnt);
2245     for ( i=0; i<strike->glyphcnt; ++i ) if ( strike->glyphs[i]!=NULL ) {
2246 	if ( i>=sf->glyphcnt || sf->glyphs[i]==NULL ) {
2247 	    int enc=-1;
2248 	    if ( strike->glyphs[i]->sc->unicodeenc!=-1 )
2249 		enc = EncFromUni(strike->glyphs[i]->sc->unicodeenc,map->enc);
2250 	    if ( enc==-1 )
2251 		enc = EncFromName(strike->glyphs[i]->sc->name,sf->uni_interp,map->enc);
2252 	    if ( enc==-1 )
2253 		enc = map->enccount;
2254 	    sc = MakeEncChar(sf,map,enc,strike->glyphs[i]->sc->name);
2255 	    strike->glyphs[i]->sc = sc;
2256 	} else
2257 	    strike->glyphs[i]->sc = sf->glyphs[i];
2258 	sc = strike->glyphs[i]->sc;
2259 	if ( sc!=NULL && !sc->widthset ) {
2260 	    sc->widthset = true;
2261 	    sc->width = strike->glyphs[i]->width*(sf->ascent+sf->descent)/strike->pixelsize;
2262 	}
2263     }
2264 }
2265 
SFMergeBitmaps(SplineFont * sf,BDFFont * strikes,EncMap * map)2266 static void SFMergeBitmaps(SplineFont *sf,BDFFont *strikes,EncMap *map) {
2267     BDFFont *b, *prev, *snext;
2268 
2269     while ( strikes ) {
2270 	snext = strikes->next;
2271 	strikes->next = NULL;
2272 	for ( prev=NULL,b=sf->bitmaps; b!=NULL &&
2273 		(b->pixelsize!=strikes->pixelsize || BDFDepth(b)!=BDFDepth(strikes));
2274 		b=b->next );
2275 	if ( b==NULL ) {
2276 	    strikes->next = sf->bitmaps;
2277 	    sf->bitmaps = strikes;
2278 	    SFSetupBitmap(sf,strikes,map);
2279 	} else if ( !alreadyexists(strikes->pixelsize)) {
2280 	    BDFFontFree(strikes);
2281 	} else {
2282 	    strikes->next = b->next;
2283 	    if ( prev==NULL )
2284 		sf->bitmaps = strikes;
2285 	    else
2286 		prev->next = strikes;
2287 	    BDFFontFree(b);
2288 	    SFSetupBitmap(sf,strikes,map);
2289 	}
2290 	strikes = snext;
2291     }
2292     SFOrderBitmapList(sf);
2293     SFDefaultAscent(sf);
2294 }
2295 
2296 static void SFAddToBackground(SplineFont *sf,BDFFont *bdf);
2297 
FVImportBDF(FontViewBase * fv,char * filename,int ispk,int toback)2298 int FVImportBDF(FontViewBase *fv, char *filename, int ispk, int toback) {
2299     BDFFont *b, *anyb=NULL;
2300     char *buf, *eod, *fpt, *file, *full, *freeme;
2301     int fcnt, any = 0;
2302     int oldenccnt = fv->map->enccount;
2303 
2304     freeme = filename = copy(filename);
2305     eod = strrchr(filename,'/');
2306     if (eod != NULL) {
2307         *eod = '\0';
2308         file = eod+1;
2309     } else {
2310         file = filename;
2311         filename = ".";
2312     }
2313     fcnt = 1;
2314     fpt = file;
2315     while (( fpt=strstr(fpt,"; "))!=NULL )
2316 	{ ++fcnt; fpt += 2; }
2317 
2318     buf = smprintf(_("Loading font from %.100s"), filename);
2319     ff_progress_start_indicator(10,_("Loading..."),buf,_("Reading Glyphs"),0,fcnt);
2320     ff_progress_enable_stop(false);
2321     free(buf);
2322 
2323     do {
2324 	fpt = strstr(file,"; ");
2325 	if ( fpt!=NULL ) *fpt = '\0';
2326 	full = smprintf("%s/%s", filename, file);
2327 	buf = smprintf(_("Loading font from %.100s"), full);
2328 	ff_progress_change_line1(buf);
2329 	free(buf);
2330 	b = _SFImportBDF(fv->sf,full,ispk,toback, fv->map);
2331 	free(full);
2332 	if ( fpt!=NULL ) ff_progress_next_stage();
2333 	if ( b!=NULL ) {
2334 	    anyb = b;
2335 	    any = true;
2336 	    FVRefreshAll(fv->sf);
2337 	}
2338 	file = fpt+2;
2339     } while ( fpt!=NULL );
2340     ff_progress_end_indicator();
2341     if ( oldenccnt != fv->map->enccount ) {
2342 	FontViewBase *fvs;
2343 	for ( fvs=fv->sf->fv; fvs!=NULL; fvs=fvs->nextsame ) {
2344 	    free(fvs->selected);
2345 	    fvs->selected = calloc(fvs->map->enccount,sizeof(uint8));
2346 	}
2347 	FontViewReformatAll(fv->sf);
2348     }
2349     if ( anyb==NULL ) {
2350 	ff_post_error( _("No Bitmap Font"), _("Could not find a bitmap font in %s"), filename );
2351     } else if ( toback )
2352 	SFAddToBackground(fv->sf,anyb);
2353     free(freeme);
2354 return( any );
2355 }
2356 
2357 /* sf and bdf are assumed to have the same gids */
SFAddToBackground(SplineFont * sf,BDFFont * bdf)2358 static void SFAddToBackground(SplineFont *sf,BDFFont *bdf) {
2359     struct _GImage *base;
2360     GClut *clut;
2361     GImage *img;
2362     int i;
2363     SplineChar *sc; BDFChar *bdfc;
2364     real scale = (sf->ascent+sf->descent)/(double) (bdf->ascent+bdf->descent);
2365     real yoff = sf->ascent-bdf->ascent*scale;
2366 
2367     for ( i=0; i<sf->glyphcnt && i<bdf->glyphcnt; ++i ) {
2368 	if ( bdf->glyphs[i]!=NULL ) {
2369 	    if ( (sc = sf->glyphs[i])==NULL ) {
2370 		sc = sf->glyphs[i] = SplineCharCreate(2);
2371 		sc->name = copy(bdf->glyphs[i]->sc->name);
2372 		sc->orig_pos = i;
2373 		sc->unicodeenc = bdf->glyphs[i]->sc->unicodeenc;
2374 	    }
2375 	    bdfc = bdf->glyphs[i];
2376 
2377 	    base = calloc(1,sizeof(struct _GImage));
2378 	    base->image_type = it_mono;
2379 	    base->data = bdfc->bitmap;
2380 	    base->bytes_per_line = bdfc->bytes_per_line;
2381 	    base->width = bdfc->xmax-bdfc->xmin+1;
2382 	    base->height = bdfc->ymax-bdfc->ymin+1;
2383 	    bdfc->bitmap = NULL;
2384 
2385 	    clut = calloc(1,sizeof(GClut));
2386 	    clut->clut_len = 2;
2387 	    clut->clut[0] = default_background;
2388 	    clut->clut[1] = 0x808080;
2389 	    clut->trans_index = 0;
2390 	    base->trans = 0;
2391 	    base->clut = clut;
2392 
2393 	    img = calloc(1,sizeof(GImage));
2394 	    img->u.image = base;
2395 
2396 	    SCInsertImage(sc,img,scale,yoff+(bdfc->ymax+1)*scale,bdfc->xmin*scale,ly_back);
2397 	}
2398     }
2399     BDFFontFree(bdf);
2400 }
2401 
FVImportMult(FontViewBase * fv,char * filename,int toback,int bf)2402 int FVImportMult(FontViewBase *fv, char *filename, int toback, int bf) {
2403     SplineFont *strikeholder, *sf = fv->sf;
2404     BDFFont *strikes;
2405     char buf[300];
2406 
2407     snprintf(buf, sizeof(buf), _("Loading font from %.100s"), filename);
2408     ff_progress_start_indicator(10,_("Loading..."),buf,_("Reading Glyphs"),0,2);
2409     ff_progress_enable_stop(false);
2410 
2411     if ( bf == bf_ttf )
2412 	strikeholder = SFReadTTF(filename,toback?ttf_onlyonestrike|ttf_onlystrikes:ttf_onlystrikes,0);
2413     else if ( bf == bf_fon )
2414 	strikeholder = SFReadWinFON(filename,toback);
2415     else if ( bf == bf_palm )
2416 	strikeholder = SFReadPalmPdb(filename);
2417     else
2418 	strikeholder = SFReadMacBinary(filename,toback?ttf_onlyonestrike|ttf_onlystrikes:ttf_onlystrikes,0);
2419 
2420     if ( strikeholder==NULL || (strikes = strikeholder->bitmaps)==NULL ) {
2421 	SplineFontFree(strikeholder);
2422 	ff_progress_end_indicator();
2423 return( false );
2424     }
2425     SFMatchGlyphs(strikeholder,sf,false);
2426     if ( toback )
2427 	SFAddToBackground(sf,strikes);
2428     else
2429 	SFMergeBitmaps(sf,strikes,fv->map);
2430 
2431     strikeholder->bitmaps =NULL;
2432     SplineFontFree(strikeholder);
2433     ff_progress_end_indicator();
2434 return( true );
2435 }
2436 
SFFromBDF(char * filename,int ispk,int toback)2437 SplineFont *SFFromBDF(char *filename,int ispk,int toback) {
2438     SplineFont *sf = SplineFontBlank(256);
2439     EncMap *map = EncMapNew(256,256,&custom);
2440     BDFFont *bdf;
2441 
2442     sf->onlybitmaps = true;
2443     bdf = SFImportBDF(sf,filename,ispk,toback, map);
2444     sf->map = map;
2445     if ( bdf==(BDFFont *) -1 )
2446 	/* Do Nothing: User cancelled a load of a duplicate pixelsize */;
2447     else if ( toback && bdf!=NULL )
2448 	SFAddToBackground(sf,bdf);
2449     else
2450 	sf->changed = false;
2451     SFDefaultAscent(sf);
2452 return( sf );
2453 }
2454 
SFCheckPSBitmap(SplineFont * sf)2455 void SFCheckPSBitmap(SplineFont *sf) {
2456     /* Check to see if this type3 font is actually a bitmap font in disguise */
2457     /*  (and make sure all bitmaps are the same size */
2458     /* If so, create a bitmap version of the font too */
2459     int i,j;
2460     SplineChar *sc;
2461     ImageList *il=NULL;
2462     double scale = 0;
2463     BDFFont *bdf;
2464     BDFChar *bdfc;
2465     struct _GImage *base;
2466 
2467     if ( !sf->multilayer )
2468 return;
2469 
2470     for ( i=0; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL ) {
2471 	if ( sc->layer_cnt!=2 )
2472 return;
2473 	if ( sc->layers[ly_fore].splines!=NULL || sc->layers[ly_fore].refs!=NULL )
2474 return;
2475 	if ( (il = sc->layers[ly_fore].images)!=NULL ) {
2476 	    base = il->image->list_len==0 ? il->image->u.image : il->image->u.images[0];
2477 	    if ( il->next!=NULL )
2478 return;
2479 	    if ( base->image_type!=it_mono )
2480 return;
2481 	    if ( !RealNear(il->xscale,il->yscale) )
2482 return;
2483 	    if ( scale == 0 )
2484 		scale = il->xscale;
2485 	    else if ( !RealNear(il->xscale,scale))
2486 return;
2487 	}
2488     }
2489     if ( il==NULL || scale <= 0 )
2490 return;			/* No images */
2491 
2492     /* Every glyph is either:
2493     	A single image
2494 	empty (space)
2495       and all images have the same scale
2496     */
2497 
2498     bdf = chunkalloc(sizeof(BDFFont));
2499     bdf->sf = sf;
2500     sf->bitmaps = bdf;
2501     bdf->pixelsize = (sf->ascent+sf->descent)/scale;
2502     bdf->ascent = rint(sf->ascent/scale);
2503     bdf->descent = bdf->pixelsize - bdf->ascent;
2504     bdf->res = -1;
2505     bdf->glyphcnt = bdf->glyphmax = sf->glyphcnt;
2506     bdf->glyphs = calloc(sf->glyphcnt,sizeof(BDFChar *));
2507 
2508     for ( i=0; i<sf->glyphcnt; ++i ) if ( (sc=sf->glyphs[i])!=NULL ) {
2509 	bdf->glyphs[i] = bdfc = chunkalloc(sizeof(BDFChar));
2510 	memset( bdfc,'\0',sizeof( BDFChar ));
2511 	bdfc->sc = sc;
2512 	bdfc->orig_pos = i;
2513 	bdfc->depth = 1;
2514 	bdfc->width = rint(sc->width/scale);
2515 	bdfc->vwidth = rint(sc->vwidth/scale);
2516 	if ( (il = sc->layers[ly_fore].images)==NULL )
2517 	    bdfc->bitmap = malloc(1);
2518 	else {
2519 	    base = il->image->list_len==0 ? il->image->u.image : il->image->u.images[0];
2520 	    bdfc->xmin = rint(il->xoff/scale);
2521 	    bdfc->ymax = rint(il->yoff/scale);
2522 	    bdfc->xmax = bdfc->xmin + base->width -1;
2523 	    bdfc->ymin = bdfc->ymax - base->height +1;
2524 	    bdfc->bytes_per_line = base->bytes_per_line;
2525 	    bdfc->bitmap = malloc(bdfc->bytes_per_line*base->height);
2526 	    memcpy(bdfc->bitmap,base->data,bdfc->bytes_per_line*base->height);
2527 	    for ( j=0; j<bdfc->bytes_per_line*base->height; ++j )
2528 		bdfc->bitmap[j] ^= 0xff;
2529 	}
2530     }
2531 }
2532