beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / luafontloader / fontforge / fontforge / splinefont.c
blob84e062c013e33d9aa811bb10a01d96c444625855
1 /* Copyright (C) 2000-2008 by George Williams */
2 /*
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright notice, this
7 * list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
13 * The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "fontforgevw.h"
29 #include <utype.h>
30 #include <ustring.h>
31 #include <math.h>
32 #include <unistd.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <gfile.h>
36 #include <time.h>
37 #include "unicoderange.h"
38 #include "psfont.h"
40 #ifdef _WIN32
41 #define MKDIR(A,B) mkdir(A)
42 #else
43 #define MKDIR(A,B) mkdir(A,B)
44 #endif
47 void SFUntickAll(SplineFont *sf) {
48 int i;
50 for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
51 sf->glyphs[i]->ticked = false;
54 SplineChar *SCBuildDummy(SplineChar *dummy,SplineFont *sf,EncMap *map,int i) {
55 static char namebuf[100];
56 static Layer layers[2];
58 memset(dummy,'\0',sizeof(*dummy));
59 dummy->color = COLOR_DEFAULT;
60 dummy->layer_cnt = 2;
61 dummy->layers = layers;
62 if ( sf->cidmaster!=NULL ) {
63 /* CID fonts don't have encodings, instead we must look up the cid */
64 if ( sf->cidmaster->loading_cid_map )
65 dummy->unicodeenc = -1;
66 else
67 dummy->unicodeenc = CID2NameUni(FindCidMap(sf->cidmaster->cidregistry,sf->cidmaster->ordering,sf->cidmaster->supplement,sf->cidmaster),
68 i,namebuf,sizeof(namebuf));
69 } else
70 dummy->unicodeenc = UniFromEnc(i,map->enc);
72 if ( sf->cidmaster!=NULL )
73 dummy->name = namebuf;
74 else if ( map->enc->psnames!=NULL && i<map->enc->char_cnt &&
75 map->enc->psnames[i]!=NULL )
76 dummy->name = map->enc->psnames[i];
77 else if ( dummy->unicodeenc==-1 )
78 dummy->name = NULL;
79 else
80 dummy->name = (char *) StdGlyphName(namebuf,dummy->unicodeenc,sf->uni_interp,sf->for_new_glyphs);
81 if ( dummy->name==NULL ) {
82 /*if ( dummy->unicodeenc!=-1 || i<256 )
83 dummy->name = ".notdef";
84 else*/ {
85 int j;
86 sprintf( namebuf, "NameMe.%d", i);
87 j=0;
88 while ( SFFindExistingSlot(sf,-1,namebuf)!=-1 )
89 sprintf( namebuf, "NameMe.%d.%d", i, ++j);
90 dummy->name = namebuf;
93 dummy->width = dummy->vwidth = sf->ascent+sf->descent;
94 if ( dummy->unicodeenc>0 && dummy->unicodeenc<0x10000 &&
95 iscombining(dummy->unicodeenc)) {
96 /* Mark characters should be 0 width */
97 dummy->width = 0;
98 /* Except in monospaced fonts on windows, where they should be the */
99 /* same width as everything else */
101 /* Actually, in a monospace font, all glyphs should be the same width */
102 /* whether mark or not */
103 if ( sf->pfminfo.panose_set && sf->pfminfo.panose[3]==9 &&
104 sf->glyphcnt>0 ) {
105 for ( i=sf->glyphcnt-1; i>=0; --i )
106 if ( SCWorthOutputting(sf->glyphs[i])) {
107 dummy->width = sf->glyphs[i]->width;
108 break;
111 dummy->parent = sf;
112 dummy->orig_pos = 0xffff;
113 return( dummy );
116 static SplineChar *_SFMakeChar(SplineFont *sf,EncMap *map,int enc) {
117 SplineChar dummy, *sc;
118 SplineFont *ssf;
119 int j, real_uni, gid;
120 extern const int cns14pua[], amspua[];
122 if ( enc>=map->enccount )
123 gid = -1;
124 else
125 gid = map->map[enc];
126 if ( sf->subfontcnt!=0 && gid!=-1 ) {
127 ssf = NULL;
128 for ( j=0; j<sf->subfontcnt; ++j )
129 if ( gid<sf->subfonts[j]->glyphcnt ) {
130 ssf = sf->subfonts[j];
131 if ( ssf->glyphs[gid]!=NULL ) {
132 return( ssf->glyphs[gid] );
135 sf = ssf;
138 if ( gid==-1 || (sc = sf->glyphs[gid])==NULL ) {
139 if (( map->enc->is_unicodebmp || map->enc->is_unicodefull ) &&
140 ( enc>=0xe000 && enc<=0xf8ff ) &&
141 ( sf->uni_interp==ui_ams || sf->uni_interp==ui_trad_chinese ) &&
142 ( real_uni = (sf->uni_interp==ui_ams ? amspua : cns14pua)[enc-0xe000])!=0 ) {
143 if ( real_uni<map->enccount ) {
144 SplineChar *sc;
145 /* if necessary, create the real unicode code point */
146 /* and then make us be a duplicate of it */
147 sc = _SFMakeChar(sf,map,real_uni);
148 map->map[enc] = gid = sc->orig_pos;
149 SCCharChangedUpdate(sc,ly_all);
150 return( sc );
154 SCBuildDummy(&dummy,sf,map,enc);
155 /* Let's say a user has a postscript encoding where the glyph ".notdef" */
156 /* is assigned to many slots. Once the user creates a .notdef glyph */
157 /* all those slots should fill in. If they don't they damn well better*/
158 /* when the user clicks on one to edit it */
159 /* Used to do that with all encodings. It just confused people */
160 if ( map->enc->psnames!=NULL &&
161 (sc = SFGetChar(sf,dummy.unicodeenc,dummy.name))!=NULL ) {
162 map->map[enc] = sc->orig_pos;
163 return( sc );
165 sc = SFSplineCharCreate(sf);
166 sc->unicodeenc = dummy.unicodeenc;
167 sc->name = copy(dummy.name);
168 sc->width = dummy.width;
169 sc->orig_pos = 0xffff;
170 /*SCLigDefault(sc);*/
171 SFAddGlyphAndEncode(sf,sc,map,enc);
173 return( sc );
176 SplineChar *SFMakeChar(SplineFont *sf,EncMap *map, int enc) {
177 int gid;
179 if ( enc==-1 )
180 return( NULL );
181 if ( enc>=map->enccount )
182 gid = -1;
183 else
184 gid = map->map[enc];
185 if ( sf->mm!=NULL && (gid==-1 || sf->glyphs[gid]==NULL) ) {
186 int j;
187 _SFMakeChar(sf->mm->normal,map,enc);
188 for ( j=0; j<sf->mm->instance_count; ++j )
189 _SFMakeChar(sf->mm->instances[j],map,enc);
191 return( _SFMakeChar(sf,map,enc));
194 struct unicoderange specialnames[] = {
195 { NULL, 0, 0, 0, 0, 0, 0 }
199 static SplineFont *_SFReadPostscript(FILE *file,char *filename) {
200 FontDict *fd=NULL;
201 SplineFont *sf=NULL;
203 ff_progress_change_stages(2);
204 fd = _ReadPSFont(file);
205 ff_progress_next_stage();
206 ff_progress_change_line2(_("Interpreting Glyphs"));
207 if ( fd!=NULL ) {
208 sf = SplineFontFromPSFont(fd);
209 PSFontFree(fd);
210 if ( sf!=NULL )
211 CheckAfmOfPostscript(sf,filename,sf->map);
213 return( sf );
216 static SplineFont *SFReadPostscript(char *filename) {
217 FontDict *fd=NULL;
218 SplineFont *sf=NULL;
220 ff_progress_change_stages(2);
221 fd = ReadPSFont(filename);
222 ff_progress_next_stage();
223 ff_progress_change_line2(_("Interpreting Glyphs"));
224 if ( fd!=NULL ) {
225 sf = SplineFontFromPSFont(fd);
226 PSFontFree(fd);
227 if ( sf!=NULL )
228 CheckAfmOfPostscript(sf,filename,sf->map);
230 return( sf );
234 struct compressors compressors[] = {
235 { ".gz", "gunzip", "gzip" },
236 { ".bz2", "bunzip2", "bzip2" },
237 { ".bz", "bunzip2", "bzip2" },
238 { ".Z", "gunzip", "compress" },
239 /* file types which are both archived and compressed (.tgz, .zip) are handled */
240 /* by the archiver above */
241 { NULL, NULL, NULL }
244 char *Decompress(char *name, int compression) {
245 char *dir = getenv("TMPDIR");
246 char buf[1500];
247 char *tmpfile;
249 if ( dir==NULL ) dir = P_tmpdir;
250 tmpfile = galloc(strlen(dir)+strlen(GFileNameTail(name))+2);
251 strcpy(tmpfile,dir);
252 strcat(tmpfile,"/");
253 strcat(tmpfile,GFileNameTail(name));
254 *strrchr(tmpfile,'.') = '\0';
255 #if defined( _NO_SNPRINTF ) || defined( __VMS )
256 sprintf( buf, "%s < %s > %s", compressors[compression].decomp, name, tmpfile );
257 #else
258 snprintf( buf, sizeof(buf), "%s < %s > %s", compressors[compression].decomp, name, tmpfile );
259 #endif
260 if ( system(buf)==0 )
261 return( tmpfile );
262 free(tmpfile);
263 return( NULL );
266 static char *ForceFileToHaveName(FILE *file, char *exten) {
267 char tmpfilename[L_tmpnam+100];
268 static int try=0;
269 FILE *newfile;
271 forever {
272 sprintf( tmpfilename, P_tmpdir "/fontforge%d-%d", getpid(), try++ );
273 if ( exten!=NULL )
274 strcat(tmpfilename,exten);
275 if ( access( tmpfilename, F_OK )==-1 &&
276 (newfile = fopen(tmpfilename,"w"))!=NULL ) {
277 char buffer[1024];
278 int len;
279 while ( (len = fread(buffer,1,sizeof(buffer),file))>0 )
280 fwrite(buffer,1,len,newfile);
281 fclose(newfile);
283 return(copy(tmpfilename)); /* The filename does not exist */
287 /* This does not check currently existing fontviews, and should only be used */
288 /* by LoadSplineFont (which does) and by RevertFile (which knows what it's doing) */
289 SplineFont *_ReadSplineFont(FILE *file,char *filename,enum openflags openflags) {
290 SplineFont *sf;
291 char ubuf[250], *temp;
292 int fromsfd = false;
293 int i;
294 char *pt, *strippedname, *oldstrippedname, *tmpfile=NULL, *paren=NULL, *fullname=filename, *rparen;
295 int len;
296 int checked;
297 int compression=0;
298 int wasurl = false, nowlocal = true;
300 if ( filename==NULL )
301 return( NULL );
303 strippedname = filename;
304 pt = strrchr(filename,'/');
305 if ( pt==NULL ) pt = filename;
306 /* Someone gave me a font "Nafees Nastaleeq(Updated).ttf" and complained */
307 /* that ff wouldn't open it */
308 /* Now someone will complain about "Nafees(Updated).ttc(fo(ob)ar)" */
309 if ( (paren = strrchr(pt,'('))!=NULL &&
310 (rparen = strrchr(paren,')'))!=NULL &&
311 rparen[1]=='\0' ) {
312 strippedname = copy(filename);
313 strippedname[paren-filename] = '\0';
316 pt = strrchr(strippedname,'.');
318 i = -1;
319 if ( pt!=NULL ) for ( i=0; compressors[i].ext!=NULL; ++i )
320 if ( strcmp(compressors[i].ext,pt)==0 )
321 break;
322 oldstrippedname = strippedname;
323 if ( i==-1 || compressors[i].ext==NULL )
324 i=-1;
325 else {
326 if ( file!=NULL ) {
327 char *spuriousname = ForceFileToHaveName(file,compressors[i].ext);
328 tmpfile = Decompress(spuriousname,i);
329 fclose(file); file = NULL;
330 unlink(spuriousname); free(spuriousname);
331 } else
332 tmpfile = Decompress(strippedname,i);
333 if ( tmpfile!=NULL ) {
334 strippedname = tmpfile;
335 } else {
336 ff_post_error(_("Decompress Failed!"),_("Decompress Failed!"));
337 return( NULL );
339 compression = i+1;
340 if ( strippedname!=filename && paren!=NULL ) {
341 fullname = galloc(strlen(strippedname)+strlen(paren)+1);
342 strcpy(fullname,strippedname);
343 strcat(fullname,paren);
344 } else
345 fullname = strippedname;
348 /* If there are no pfaedit windows, give them something to look at */
349 /* immediately. Otherwise delay a bit */
350 strcpy(ubuf,_("Loading font from "));
351 len = strlen(ubuf);
352 if ( !wasurl || i==-1 ) /* If it wasn't compressed, or it wasn't an url, then the fullname is reasonable, else use the original name */
353 strncat(ubuf,temp = copy(GFileNameTail(fullname)),100);
354 else
355 strncat(ubuf,temp = copy(GFileNameTail(filename)),100);
356 free(temp);
357 ubuf[100+len] = '\0';
358 ff_progress_start_indicator(FontViewFirst()==NULL?0:10,_("Loading..."),ubuf,_("Reading Glyphs"),0,1);
359 ff_progress_enable_stop(0);
361 if ( file==NULL ) {
362 file = fopen(strippedname,"rb");
363 nowlocal = true;
366 sf = NULL;
367 checked = false;
368 /* checked == false => not checked */
369 /* checked == 'u' => UFO */
370 /* checked == 't' => TTF/OTF */
371 /* checked == 'p' => pfb/general postscript */
372 /* checked == 'P' => pdf */
373 /* checked == 'c' => cff */
374 /* checked == 'S' => svg */
375 /* checked == 'f' => sfd */
376 /* checked == 'F' => sfdir */
377 /* checked == 'b' => bdf */
378 /* checked == 'i' => ikarus */
379 if ( file!=NULL ) {
380 /* Try to guess the file type from the first few characters... */
381 int ch1 = getc(file);
382 int ch2 = getc(file);
383 int ch3 = getc(file);
384 int ch4 = getc(file);
385 int ch9, ch10;
386 fseek(file, 98, SEEK_SET);
387 ch9 = getc(file);
388 ch10 = getc(file);
389 rewind(file);
390 if (( ch1==0 && ch2==1 && ch3==0 && ch4==0 ) ||
391 (ch1=='O' && ch2=='T' && ch3=='T' && ch4=='O') ||
392 (ch1=='t' && ch2=='r' && ch3=='u' && ch4=='e') ||
393 (ch1=='t' && ch2=='t' && ch3=='c' && ch4=='f') ) {
394 sf = _SFReadTTF(file,0,openflags,fullname,NULL);
395 checked = 't';
396 } else if (( ch1=='%' && ch2=='!' ) ||
397 ( ch1==0x80 && ch2=='\01' ) ) { /* PFB header */
398 sf = _SFReadPostscript(file,fullname);
399 checked = 'p';
400 } else if ( ch1==1 && ch2==0 && ch3==4 ) {
401 int len;
402 fseek(file,0,SEEK_END);
403 len = ftell(file);
404 fseek(file,0,SEEK_SET);
405 sf = _CFFParse(file,len,NULL);
406 checked = 'c';
407 } /* Too hard to figure out a valid mark for a mac resource file */
408 if ( file!=NULL ) fclose(file);
411 if ( sf!=NULL )
412 /* good */;
413 else if (( strmatch(fullname+strlen(fullname)-4, ".ttf")==0 ||
414 strmatch(fullname+strlen(strippedname)-4, ".ttc")==0 ||
415 strmatch(fullname+strlen(fullname)-4, ".gai")==0 ||
416 strmatch(fullname+strlen(fullname)-4, ".otf")==0 ||
417 strmatch(fullname+strlen(fullname)-4, ".otb")==0 ) && checked!='t') {
418 sf = SFReadTTF(fullname,0,openflags);
419 } else if ( strmatch(fullname+strlen(strippedname)-4, ".bin")==0 ||
420 strmatch(fullname+strlen(strippedname)-4, ".hqx")==0 ||
421 strmatch(fullname+strlen(strippedname)-6, ".dfont")==0 ) {
422 sf = SFReadMacBinary(fullname,0,openflags);
423 } else if ( (strmatch(fullname+strlen(fullname)-4, ".pfa")==0 ||
424 strmatch(fullname+strlen(fullname)-4, ".pfb")==0 ||
425 strmatch(fullname+strlen(fullname)-4, ".pf3")==0 ||
426 strmatch(fullname+strlen(fullname)-4, ".cid")==0 ||
427 strmatch(fullname+strlen(fullname)-4, ".gsf")==0 ||
428 strmatch(fullname+strlen(fullname)-4, ".pt3")==0 ||
429 strmatch(fullname+strlen(fullname)-3, ".ps")==0 ) && checked!='p' ) {
430 sf = SFReadPostscript(fullname);
431 } else if ( strmatch(fullname+strlen(fullname)-4, ".cff")==0 && checked!='c' ) {
432 sf = CFFParse(fullname);
433 } else {
434 sf = SFReadMacBinary(fullname,0,openflags);
436 ff_progress_end_indicator();
438 if ( sf!=NULL ) {
439 SplineFont *norm = sf->mm!=NULL ? sf->mm->normal : sf;
440 if ( compression!=0 ) {
441 free(sf->filename);
442 *strrchr(oldstrippedname,'.') = '\0';
443 sf->filename = copy( oldstrippedname );
445 if ( fromsfd )
446 sf->compression = compression;
447 free( norm->origname );
448 if ( sf->chosenname!=NULL && strippedname==filename ) {
449 norm->origname = galloc(strlen(filename)+strlen(sf->chosenname)+8);
450 strcpy(norm->origname,filename);
451 strcat(norm->origname,"(");
452 strcat(norm->origname,sf->chosenname);
453 strcat(norm->origname,")");
454 } else
455 norm->origname = copy(filename);
456 free( norm->chosenname ); norm->chosenname = NULL;
457 if ( sf->mm!=NULL ) {
458 int j;
459 for ( j=0; j<sf->mm->instance_count; ++j ) {
460 free(sf->mm->instances[j]->origname);
461 sf->mm->instances[j]->origname = copy(norm->origname);
464 } else if ( !GFileExists(filename) )
465 ff_post_error(_("Couldn't open font"),_("The requested file, %.100s, does not exist"),GFileNameTail(filename));
466 else if ( !GFileReadable(filename) )
467 ff_post_error(_("Couldn't open font"),_("You do not have permission to read %.100s"),GFileNameTail(filename));
468 else
469 ff_post_error(_("Couldn't open font"),_("%.100s is not in a known format (or is so badly corrupted as to be unreadable)"),GFileNameTail(filename));
471 if ( oldstrippedname!=filename )
472 free(oldstrippedname);
473 if ( fullname!=filename && fullname!=strippedname )
474 free(fullname);
475 if ( tmpfile!=NULL ) {
476 unlink(tmpfile);
477 free(tmpfile);
479 if ( (openflags&of_fstypepermitted) && sf!=NULL && (sf->pfminfo.fstype&0xff)==0x0002 ) {
480 /* Ok, they have told us from a script they have access to the font */
481 } else if ( !fromsfd && sf!=NULL && (sf->pfminfo.fstype&0xff)==0x0002 ) {
482 char *buts[3];
483 buts[0] = _("_Yes"); buts[1] = _("_No"); buts[2] = NULL;
484 if ( ff_ask(_("Restricted Font"),(const char **) buts,1,1,_("This font is marked with an FSType of 2 (Restricted\nLicense). That means it is not editable without the\npermission of the legal owner.\n\nDo you have such permission?"))==1 ) {
485 SplineFontFree(sf);
486 return( NULL );
489 return( sf );
492 SplineFont *ReadSplineFont(char *filename,enum openflags openflags) {
493 return( _ReadSplineFont(NULL,filename,openflags));
497 SplineFont *ReadSplineFontInfo(char *filename,enum openflags openflags) {
498 SplineFont *sf, *sf_ptr;
499 char **fontlist;
500 char *pt =NULL, *strippedname=filename, *paren=NULL, *rparen=NULL, *fullname=filename;
501 FILE *foo = NULL;
502 int checked = 0;
503 char s[512] = {0};
505 if ( filename==NULL )
506 return( NULL );
508 pt = strrchr(filename,'/');
509 if ( pt==NULL ) pt = filename;
510 /* Someone gave me a font "Nafees Nastaleeq(Updated).ttf" and complained */
511 /* that ff wouldn't open it */
512 /* Now someone will complain about "Nafees(Updated).ttc(fo(ob)ar)" */
513 if ( (paren = strrchr(pt,'('))!=NULL &&
514 (rparen = strrchr(paren,')'))!=NULL &&
515 rparen[1]=='\0' ) {
516 strippedname = copy(filename);
517 strippedname[paren-filename] = '\0';
520 sf = NULL;
521 foo = fopen(strippedname,"rb");
522 checked = false;
523 if ( foo!=NULL ) {
524 /* Try to guess the file type from the first few characters... */
525 int ch1 = getc(foo);
526 int ch2 = getc(foo);
527 int ch3 = getc(foo);
528 int ch4 = getc(foo);
529 fclose(foo);
530 if (( ch1==0 && ch2==1 && ch3==0 && ch4==0 ) ||
531 (ch1=='O' && ch2=='T' && ch3=='T' && ch4=='O') ||
532 (ch1=='t' && ch2=='r' && ch3=='u' && ch4=='e') ) {
533 sf = SFReadTTFInfo(fullname,0,openflags);
534 checked = 't';
535 } else if ((ch1=='t' && ch2=='t' && ch3=='c' && ch4=='f')) {
536 char **old_fontlist;
537 int i;
538 /* read all fonts in a collection */
539 fontlist = NamesReadTTF(fullname);
540 old_fontlist = fontlist;
541 if (fontlist) {
542 while (*fontlist != NULL) {
543 snprintf(s,511, "%s(%s)", fullname,*fontlist);
544 sf_ptr = SFReadTTFInfo(s,0,openflags);
545 if (sf != NULL)
546 sf_ptr->next = sf;
547 sf = sf_ptr;
548 fontlist++;
550 /* fontlist is (g)allocated */
551 fontlist = old_fontlist;
552 for(i=0; fontlist[i]; i++)
553 free(fontlist[i]);
554 free(fontlist);
555 old_fontlist = NULL;
557 } else if ( strmatch(fullname+strlen(strippedname)-4, ".bin")==0 ||
558 strmatch(fullname+strlen(strippedname)-4, ".hqx")==0 ||
559 strmatch(fullname+strlen(strippedname)-6, ".dfont")==0 ) {
560 fontlist = NamesReadMacBinary(fullname);
561 if (fontlist) {
562 while (*fontlist != NULL) {
563 snprintf(s,511, "%s(%s)", fullname,*fontlist);
564 sf_ptr = SFReadMacBinaryInfo(s,0,openflags);
565 if (sf != NULL)
566 sf_ptr->next = sf;
567 sf = sf_ptr;
568 fontlist++;
571 } else {
572 sf = ReadSplineFont (fullname, openflags);
575 if ( strippedname!=filename )
576 free(strippedname);
577 return( sf );
581 /* Use URW 4 letter abbreviations */
582 char *knownweights[] = { "Demi", "Bold", "Regu", "Medi", "Book", "Thin",
583 "Ligh", "Heav", "Blac", "Ultr", "Nord", "Norm", "Gras", "Stan", "Halb",
584 "Fett", "Mage", "Mitt", "Buch", NULL };
585 char *realweights[] = { "Demi", "Bold", "Regular", "Medium", "Book", "Thin",
586 "Light", "Heavy", "Black", "Ultra", "Nord", "Normal", "Gras", "Standard", "Halbfett",
587 "Fett", "Mager", "Mittel", "Buchschrift", NULL};
588 static char *moreweights[] = { "ExtraLight", "VeryLight", NULL };
589 char **noticeweights[] = { moreweights, realweights, knownweights, NULL };
591 static char *modifierlist[] = { "Ital", "Obli", "Kursive", "Cursive", "Slanted",
592 "Expa", "Cond", NULL };
593 static char *modifierlistfull[] = { "Italic", "Oblique", "Kursive", "Cursive", "Slanted",
594 "Expanded", "Condensed", NULL };
595 static char **mods[] = { knownweights, modifierlist, NULL };
596 static char **fullmods[] = { realweights, modifierlistfull, NULL };
598 char *_GetModifiers(char *fontname, char *familyname,char *weight) {
599 char *pt, *fpt;
600 int i, j;
602 /* URW fontnames don't match the familyname */
603 /* "NimbusSanL-Regu" vs "Nimbus Sans L" (note "San" vs "Sans") */
604 /* so look for a '-' if there is one and use that as the break point... */
606 if ( (fpt=strchr(fontname,'-'))!=NULL ) {
607 ++fpt;
608 if ( *fpt=='\0' )
609 fpt = NULL;
610 } else if ( familyname!=NULL ) {
611 for ( pt = fontname, fpt=familyname; *fpt!='\0' && *pt!='\0'; ) {
612 if ( *fpt == *pt ) {
613 ++fpt; ++pt;
614 } else if ( *fpt==' ' )
615 ++fpt;
616 else if ( *pt==' ' )
617 ++pt;
618 else if ( *fpt=='a' || *fpt=='e' || *fpt=='i' || *fpt=='o' || *fpt=='u' )
619 ++fpt; /* allow vowels to be omitted from family when in fontname */
620 else
621 break;
623 if ( *fpt=='\0' && *pt!='\0' )
624 fpt = pt;
625 else
626 fpt = NULL;
629 if ( fpt == NULL ) {
630 for ( i=0; mods[i]!=NULL; ++i ) for ( j=0; mods[i][j]!=NULL; ++j ) {
631 pt = strstr(fontname,mods[i][j]);
632 if ( pt!=NULL && (fpt==NULL || pt<fpt))
633 fpt = pt;
636 if ( fpt!=NULL ) {
637 for ( i=0; mods[i]!=NULL; ++i ) for ( j=0; mods[i][j]!=NULL; ++j ) {
638 if ( strcmp(fpt,mods[i][j])==0 )
639 return( fullmods[i][j]);
641 if ( strcmp(fpt,"BoldItal")==0 )
642 return( "BoldItalic" );
643 else if ( strcmp(fpt,"BoldObli")==0 )
644 return( "BoldOblique" );
646 return( fpt );
649 return( weight==NULL || *weight=='\0' ? "Regular": weight );
652 char *SFGetModifiers(SplineFont *sf) {
653 return( _GetModifiers(sf->fontname,sf->familyname,sf->weight));