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