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:
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 #include "fontforgevw.h"
28 #include "ustring.h"
29 #include "utype.h"
30 #include "gfile.h"
31 #include "chardata.h"
32 
RefCharsCopy(RefChar * ref)33 RefChar *RefCharsCopy(RefChar *ref) {
34     RefChar *rhead=NULL, *last=NULL, *cur;
35 
36     while ( ref!=NULL ) {
37 	cur = RefCharCreate();
38 #ifdef FONTFORGE_CONFIG_TYPE3
39 	{ struct reflayer *layers = cur->layers; int layer;
40 	layers = grealloc(layers,ref->layer_cnt*sizeof(struct reflayer));
41 	memcpy(layers,ref->layers,ref->layer_cnt*sizeof(struct reflayer));
42 	*cur = *ref;
43 	cur->layers = layers;
44 	for ( layer=0; layer<cur->layer_cnt; ++layer ) {
45 	    cur->layers[layer].splines = NULL;
46 	    cur->layers[layer].images = NULL;
47 	}
48 	}
49 #else
50 	{struct reflayer *rl = cur->layers;
51 	*cur = *ref;
52 	cur->layers = rl;
53 	}
54 #endif
55 	if ( cur->sc!=NULL )
56 	    cur->orig_pos = cur->sc->orig_pos;
57 	cur->next = NULL;
58 	if ( rhead==NULL )
59 	    rhead = cur;
60 	else
61 	    last->next = cur;
62 	last = cur;
63 	ref = ref->next;
64     }
65 return( rhead );
66 }
67 
MCConvertLookup(struct sfmergecontext * mc,OTLookup * otl)68 static OTLookup *MCConvertLookup(struct sfmergecontext *mc,OTLookup *otl) {
69     int l;
70     OTLookup *newotl;
71 
72     if ( mc==NULL || mc->sf_from==mc->sf_to )
73 return( otl );		/* No translation needed */
74 
75     for ( l=0; l<mc->lcnt; ++l ) {
76 	if ( mc->lks[l].from == otl )
77     break;
78     }
79     if ( l==mc->lcnt )
80 return( NULL );
81     if ( mc->lks[l].to!=NULL )
82 return( mc->lks[l].to );
83 
84     mc->lks[l].to = newotl = chunkalloc(sizeof(struct lookup_subtable));
85     newotl->lookup_name = strconcat(mc->prefix,otl->lookup_name);
86     newotl->lookup_type = otl->lookup_type;
87     newotl->lookup_flags = otl->lookup_flags;
88     newotl->features = FeatureListCopy(otl->features);
89     newotl->store_in_afm = otl->store_in_afm;
90 return( newotl );
91 }
92 
MCConvertSubtable(struct sfmergecontext * mc,struct lookup_subtable * sub)93 struct lookup_subtable *MCConvertSubtable(struct sfmergecontext *mc,struct lookup_subtable *sub) {
94     int s;
95     struct lookup_subtable *newsub;
96 
97     if ( mc==NULL || mc->sf_from==mc->sf_to )
98 return( sub );		/* No translation needed */
99     if ( mc->prefix==NULL ) {
100 	int lcnt, scnt;
101 	OTLookup *otl;
102 	struct lookup_subtable *subs;
103 	int isgpos, doit;
104 	char *temp;
105 
106 	/* Not initialized */
107 	if ( mc->sf_from->cidmaster ) mc->sf_from = mc->sf_from->cidmaster;
108 	else if ( mc->sf_from->mm!=NULL ) mc->sf_from = mc->sf_from->mm->normal;
109 	if ( mc->sf_to->cidmaster ) mc->sf_to = mc->sf_to->cidmaster;
110 	else if ( mc->sf_to->mm!=NULL ) mc->sf_to = mc->sf_to->mm->normal;
111 	if ( mc->sf_from == mc->sf_to )
112 return( sub );
113 	mc->prefix = strconcat(mc->sf_from->fontname,"-");
114 	for ( doit = 0; doit<2; ++doit ) {
115 	    lcnt = scnt = 0;
116 	    for ( isgpos=0; isgpos<2; ++isgpos ) {
117 		for ( otl = isgpos ? mc->sf_from->gpos_lookups : mc->sf_from->gsub_lookups; otl!=NULL; otl=otl->next ) {
118 		    if ( doit ) {
119 			mc->lks[lcnt].from = otl;
120 			temp = strconcat(mc->prefix,otl->lookup_name);
121 			mc->lks[lcnt].to = SFFindLookup(mc->sf_to,temp);
122 			free(temp);
123 			mc->lks[lcnt].old = mc->lks[lcnt].to!=NULL;
124 		    }
125 		    ++lcnt;
126 		    for ( subs=otl->subtables; subs!=NULL; subs=subs->next ) {
127 			if ( doit ) {
128 			    mc->subs[scnt].from = subs;
129 			    temp = strconcat(mc->prefix,subs->subtable_name);
130 			    mc->subs[scnt].to = SFFindLookupSubtable(mc->sf_to,temp);
131 			    free(temp);
132 			    mc->subs[scnt].old = mc->subs[scnt].to!=NULL;
133 			}
134 			++scnt;
135 		    }
136 		}
137 	    }
138 	    if ( !doit ) {
139 		mc->lcnt = lcnt; mc->scnt = scnt;
140 		mc->lks = gcalloc(lcnt,sizeof(struct lookup_cvt));
141 		mc->subs = gcalloc(scnt,sizeof(struct sub_cvt));
142 	    }
143 	}
144     }
145 
146     for ( s=0; s<mc->scnt; ++s ) {
147 	if ( mc->subs[s].from == sub )
148     break;
149     }
150     if ( s==mc->scnt )
151 return( NULL );
152     if ( mc->subs[s].to!=NULL )
153 return( mc->subs[s].to );
154 
155     mc->subs[s].to = newsub = chunkalloc(sizeof(struct lookup_subtable));
156     newsub->subtable_name = strconcat(mc->prefix,sub->subtable_name);
157     newsub->lookup = MCConvertLookup(mc,sub->lookup);
158     newsub->anchor_classes = sub->anchor_classes;
159     newsub->per_glyph_pst_or_kern = sub->per_glyph_pst_or_kern;
160 return( newsub );
161 }
162 
PSTCopy(PST * base,SplineChar * sc,struct sfmergecontext * mc)163 PST *PSTCopy(PST *base,SplineChar *sc,struct sfmergecontext *mc) {
164     PST *head=NULL, *last=NULL, *cur;
165 
166     for ( ; base!=NULL; base = base->next ) {
167 	cur = chunkalloc(sizeof(PST));
168 	*cur = *base;
169 	cur->subtable = MCConvertSubtable(mc,base->subtable);
170 	if ( cur->type==pst_ligature ) {
171 	    cur->u.lig.components = copy(cur->u.lig.components);
172 	    cur->u.lig.lig = sc;
173 	} else if ( cur->type==pst_pair ) {
174 	    cur->u.pair.paired = copy(cur->u.pair.paired);
175 	    cur->u.pair.vr = chunkalloc(sizeof( struct vr [2]));
176 	    memcpy(cur->u.pair.vr,base->u.pair.vr,sizeof(struct vr [2]));
177 	} else if ( cur->type==pst_lcaret ) {
178 	    cur->u.lcaret.carets = galloc(cur->u.lcaret.cnt*sizeof(uint16));
179 	    memcpy(cur->u.lcaret.carets,base->u.lcaret.carets,cur->u.lcaret.cnt*sizeof(uint16));
180 	} else if ( cur->type==pst_substitution || cur->type==pst_multiple || cur->type==pst_alternate )
181 	    cur->u.subs.variant = copy(cur->u.subs.variant);
182 	if ( head==NULL )
183 	    head = cur;
184 	else
185 	    last->next = cur;
186 	last = cur;
187     }
188 return( head );
189 }
190 
AnchorPointsDuplicate(AnchorPoint * base,SplineChar * sc)191 static AnchorPoint *AnchorPointsDuplicate(AnchorPoint *base,SplineChar *sc) {
192     AnchorPoint *head=NULL, *last=NULL, *cur;
193     AnchorClass *ac;
194 
195     for ( ; base!=NULL; base = base->next ) {
196 	cur = chunkalloc(sizeof(AnchorPoint));
197 	*cur = *base;
198 	cur->next = NULL;
199 	for ( ac=sc->parent->anchor; ac!=NULL; ac=ac->next )
200 	    if ( strcmp(ac->name,base->anchor->name)==0 )
201 	break;
202 	cur->anchor = ac;
203 	if ( ac==NULL ) {
204 	    LogError( "No matching AnchorClass for %s", base->anchor->name);
205 	    chunkfree(cur,sizeof(AnchorPoint));
206 	} else {
207 	    if ( head==NULL )
208 		head = cur;
209 	    else
210 		last->next = cur;
211 	    last = cur;
212 	}
213     }
214 return( head );
215 }
216 
AltUniCopy(struct altuni * altuni,SplineFont * noconflicts)217 static struct altuni *AltUniCopy(struct altuni *altuni,SplineFont *noconflicts) {
218     struct altuni *head=NULL, *last=NULL, *cur;
219 
220     while ( altuni!=NULL ) {
221 	if ( noconflicts==NULL || SFGetChar(noconflicts,altuni->unienc,NULL)==NULL ) {
222 	    cur = chunkalloc(sizeof(struct altuni));
223 	    cur->unienc = altuni->unienc;
224 	    cur->vs = altuni->vs;
225 	    cur->fid = altuni->fid;
226 	    if ( head==NULL )
227 		head = cur;
228 	    else
229 		last->next = cur;
230 	    last = cur;
231 	}
232 	altuni = altuni->next;
233     }
234 return( head );
235 }
236 
SplineCharCopy(SplineChar * sc,SplineFont * into,struct sfmergecontext * mc)237 SplineChar *SplineCharCopy(SplineChar *sc,SplineFont *into,struct sfmergecontext *mc) {
238     SplineChar *nsc;
239     Layer *layers;
240     int layer;
241     if (into==NULL) {
242       nsc = SplineCharCreate(2);
243     } else {
244       nsc = SFSplineCharCreate(into);
245     }
246     layers = nsc->layers;
247     *nsc = *sc;		/* We copy the layers just below */
248     if (into==NULL || sc->layer_cnt!=into->layer_cnt )
249 	  layers = grealloc(layers,sc->layer_cnt*sizeof(Layer));
250     memcpy(layers,sc->layers,sc->layer_cnt*sizeof(Layer));
251     nsc->layers = layers;
252     for ( layer = ly_back; layer<sc->layer_cnt; ++layer ) {
253 	layers[layer].splines = SplinePointListCopy(layers[layer].splines);
254 	layers[layer].refs = RefCharsCopy(layers[layer].refs);
255 	layers[layer].images = ImageListCopy(layers[layer].images);
256 	layers[layer].undoes = NULL;
257 	layers[layer].redoes = NULL;
258     }
259     nsc->parent = into;
260     nsc->orig_pos = -2;
261     nsc->name = copy(sc->name);
262     nsc->hstem = StemInfoCopy(nsc->hstem);
263     nsc->vstem = StemInfoCopy(nsc->vstem);
264     nsc->anchor = AnchorPointsDuplicate(nsc->anchor,nsc);
265     nsc->views = NULL;
266     nsc->changed = true;
267     nsc->dependents = NULL;		/* Fix up later when we know more */
268     nsc->layers[ly_fore].undoes = nsc->layers[ly_back].undoes = NULL;
269     nsc->layers[ly_fore].redoes = nsc->layers[ly_back].redoes = NULL;
270     if ( nsc->ttf_instrs_len!=0 ) {
271 	nsc->ttf_instrs = galloc(nsc->ttf_instrs_len);
272 	memcpy(nsc->ttf_instrs,sc->ttf_instrs,nsc->ttf_instrs_len);
273     }
274     nsc->kerns = NULL;
275     nsc->possub = PSTCopy(nsc->possub,nsc,mc);
276     nsc->altuni = AltUniCopy(nsc->altuni,into);
277 return(nsc);
278 }
279 
280 static int _SFFindExistingSlot(SplineFont *sf, int unienc, const char *name );
281 
282 
283 #define GN_HSIZE	257
284 
285 struct glyphnamebucket {
286     SplineChar *sc;
287     struct glyphnamebucket *next;
288 };
289 
290 struct glyphnamehash {
291     struct glyphnamebucket *table[GN_HSIZE];
292 };
293 
294 #ifndef __GNUC__
295 # define __inline__
296 #endif
297 
hashname(const char * pt)298 static __inline__ int hashname(const char *pt) {
299     int val = 0;
300 
301     while ( *pt ) {
302 	val = (val<<3)|((val>>29)&0x7);
303 	val ^= (unsigned char)(*pt-'!');
304 	pt++;
305     }
306     val ^= (val>>16);
307     val &= 0xffff;
308     val %= GN_HSIZE;
309 return( val );
310 }
311 
_GlyphHashFree(SplineFont * sf)312 static void _GlyphHashFree(SplineFont *sf) {
313     struct glyphnamebucket *test, *next;
314     int i;
315 
316     if ( sf->glyphnames==NULL )
317 return;
318     for ( i=0; i<GN_HSIZE; ++i ) {
319 	for ( test = sf->glyphnames->table[i]; test!=NULL; test = next ) {
320 	    next = test->next;
321 	    chunkfree(test,sizeof(struct glyphnamebucket));
322 	}
323     }
324     free(sf->glyphnames);
325     sf->glyphnames = NULL;
326 }
327 
GlyphHashFree(SplineFont * sf)328 void GlyphHashFree(SplineFont *sf) {
329     _GlyphHashFree(sf);
330     if ( sf->cidmaster )
331 	_GlyphHashFree(sf->cidmaster);
332 }
333 
GlyphHashCreate(SplineFont * sf)334 static void GlyphHashCreate(SplineFont *sf) {
335     int i, k, hash;
336     SplineFont *_sf;
337     struct glyphnamehash *gnh;
338     struct glyphnamebucket *new;
339 
340     if ( sf->glyphnames!=NULL )
341 return;
342     sf->glyphnames = gnh = gcalloc(1,sizeof(*gnh));
343     k = 0;
344     do {
345 	_sf = k<sf->subfontcnt ? sf->subfonts[k] : sf;
346 	/* I walk backwards because there are some ttf files where multiple */
347 	/*  glyphs get the same name. In the cases I've seen only one of these */
348 	/*  has an encoding. That's the one we want. It will be earlier in the */
349 	/*  font than the others. If we build the list backwards then it will */
350 	/*  be the top name in the bucket, and will be the one we return */
351 	for ( i=_sf->glyphcnt-1; i>=0; --i ) if ( _sf->glyphs[i]!=NULL ) {
352 	    new = chunkalloc(sizeof(struct glyphnamebucket));
353 	    new->sc = _sf->glyphs[i];
354 	    hash = hashname(new->sc->name);
355 	    new->next = gnh->table[hash];
356 	    gnh->table[hash] = new;
357 	}
358 	++k;
359     } while ( k<sf->subfontcnt );
360 }
361 
SFHashGlyph(SplineFont * sf,SplineChar * sc)362 void SFHashGlyph(SplineFont *sf,SplineChar *sc) {
363     /* sc just got added to the font. Put it in the lookup */
364     int hash;
365     struct glyphnamebucket *new;
366 
367     if ( sf->glyphnames==NULL )
368 return;		/* No hash table, nothing to update */
369 
370     new = chunkalloc(sizeof(struct glyphnamebucket));
371     new->sc = sc;
372     hash = hashname(sc->name);
373     new->next = sf->glyphnames->table[hash];
374     sf->glyphnames->table[hash] = new;
375 }
376 
SFHashName(SplineFont * sf,const char * name)377 SplineChar *SFHashName(SplineFont *sf,const char *name) {
378     struct glyphnamebucket *test;
379 
380     if ( sf->glyphnames==NULL )
381 	GlyphHashCreate(sf);
382 
383     for ( test=sf->glyphnames->table[hashname(name)]; test!=NULL; test = test->next )
384 	if ( strcmp(test->sc->name,name)==0 )
385 return( test->sc );
386 
387 return( NULL );
388 }
389 
390 /* Find the position in the glyph list where this code point/name is found. */
391 /*  Returns -1 else on error */
SFFindGID(SplineFont * sf,int unienc,const char * name)392 int SFFindGID(SplineFont *sf, int unienc, const char *name ) {
393     struct altuni *altuni;
394     int gid;
395     SplineChar *sc;
396 
397     if ( unienc!=-1 ) {
398 	for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( sf->glyphs[gid]!=NULL ) {
399 	    if ( sf->glyphs[gid]->unicodeenc == unienc )
400 return( gid );
401 	    for ( altuni = sf->glyphs[gid]->altuni; altuni!=NULL; altuni=altuni->next ) {
402 		if ( altuni->unienc == unienc && altuni->vs==-1 && altuni->fid==0 )
403 return( gid );
404 	    }
405 	}
406     }
407     if ( name!=NULL ) {
408 	sc = SFHashName(sf,name);
409 	if ( sc!=NULL )
410 return( sc->orig_pos );
411     }
412 
413 return ( -1 );
414 }
415 
416 /* Find the position in the current encoding where this code point/name should*/
417 /*  be found. (or for unencoded glyphs where it is found). Returns -1 else */
SFFindSlot(SplineFont * sf,EncMap * map,int unienc,const char * name)418 int SFFindSlot(SplineFont *sf, EncMap *map, int unienc, const char *name ) {
419     int index=-1, pos;
420     struct cidmap *cidmap;
421 
422     if ( sf->cidmaster!=NULL && !map->enc->is_compact &&
423 		(cidmap = FindCidMap(sf->cidmaster->cidregistry,
424 				    sf->cidmaster->ordering,
425 				    sf->cidmaster->supplement,
426 				    sf->cidmaster))!=NULL )
427 	index = NameUni2CID(cidmap,unienc,name);
428     if ( index!=-1 )
429 	/* All done */;
430     else if ( (map->enc->is_custom || map->enc->is_compact ||
431 	    map->enc->is_original) && unienc!=-1 ) {
432 	if ( unienc<map->enccount && map->map[unienc]!=-1 &&
433 		sf->glyphs[map->map[unienc]]!=NULL &&
434 		sf->glyphs[map->map[unienc]]->unicodeenc==unienc )
435 	    index = unienc;
436 	else for ( index = map->enccount-1; index>=0; --index ) {
437 	    if ( (pos = map->map[index])!=-1 && sf->glyphs[pos]!=NULL &&
438 		    sf->glyphs[pos]->unicodeenc==unienc )
439 	break;
440 	}
441     } else if ( unienc!=-1 &&
442 	    ((unienc<0x10000 && map->enc->is_unicodebmp) ||
443 	     (unienc<0x110000 && map->enc->is_unicodefull))) {
444 	 index = unienc;
445     } else if ( unienc!=-1 ) {
446 	index = EncFromUni(unienc,map->enc);
447 	if ( index<0 || index>=map->enccount ) {
448 	    for ( index=map->enc->char_cnt; index<map->enccount; ++index )
449 		if ( (pos = map->map[index])!=-1 && sf->glyphs[pos]!=NULL &&
450 			sf->glyphs[pos]->unicodeenc==unienc )
451 	    break;
452 	    if ( index>=map->enccount )
453 		index = -1;
454 	}
455     }
456     if ( index==-1 && name!=NULL ) {
457 	SplineChar *sc = SFHashName(sf,name);
458 	if ( sc!=NULL ) index = map->backmap[sc->orig_pos];
459 	if ( index==-1 ) {
460 	    unienc = UniFromName(name,sf->uni_interp,map->enc);
461 	    if ( unienc!=-1 )
462 return( SFFindSlot(sf,map,unienc,NULL));
463 	    if ( map->enc->psnames!=NULL ) {
464 		for ( index = map->enc->char_cnt-1; index>=0; --index )
465 		    if ( map->enc->psnames[index]!=NULL &&
466 			    strcmp(map->enc->psnames[index],name)==0 )
467 return( index );
468 	    }
469 	}
470     }
471 
472 return( index );
473 }
474 
SFCIDFindCID(SplineFont * sf,int unienc,const char * name)475 int SFCIDFindCID(SplineFont *sf, int unienc, const char *name ) {
476     int j,ret;
477     struct cidmap *cidmap;
478 
479     if ( sf->cidmaster!=NULL || sf->subfontcnt!=0 ) {
480 	if ( sf->cidmaster!=NULL )
481 	    sf=sf->cidmaster;
482 	cidmap = FindCidMap(sf->cidregistry,sf->ordering,sf->supplement,sf);
483 	ret = NameUni2CID(cidmap,unienc,name);
484 	if ( ret!=-1 )
485 return( ret );
486     }
487 
488     if ( sf->subfonts==NULL && sf->cidmaster==NULL )
489 return( SFFindGID(sf,unienc,name));
490 
491     if ( sf->cidmaster!=NULL )
492 	sf=sf->cidmaster;
493     for ( j=0; j<sf->subfontcnt; ++j )
494 	if (( ret = SFFindGID(sf,unienc,name))!=-1 )
495 return( ret );
496 
497 return( -1 );
498 }
499 
SFHasCID(SplineFont * sf,int cid)500 int SFHasCID(SplineFont *sf,int cid) {
501     int i;
502     /* What subfont (if any) contains this cid? */
503     if ( sf->cidmaster!=NULL )
504 	sf=sf->cidmaster;
505     for ( i=0; i<sf->subfontcnt; ++i )
506 	if ( cid<sf->subfonts[i]->glyphcnt &&
507 		SCWorthOutputting(sf->subfonts[i]->glyphs[cid]) )
508 return( i );
509     for ( i=0; i<sf->subfontcnt; ++i )
510 	if ( cid<sf->subfonts[i]->glyphcnt && sf->subfonts[i]->glyphs[cid]!=NULL )
511 return( i );
512 
513 return( -1 );
514 }
515 
SFGetChar(SplineFont * sf,int unienc,const char * name)516 SplineChar *SFGetChar(SplineFont *sf, int unienc, const char *name ) {
517     int ind;
518     int j;
519 
520     ind = SFCIDFindCID(sf,unienc,name);
521     if ( ind==-1 )
522 return( NULL );
523 
524     if ( sf->subfonts==NULL && sf->cidmaster==NULL )
525 return( sf->glyphs[ind]);
526 
527     if ( sf->cidmaster!=NULL )
528 	sf=sf->cidmaster;
529 
530     j = SFHasCID(sf,ind);
531     if ( j==-1 )
532 return( NULL );
533 
534 return( sf->subfonts[j]->glyphs[ind] );
535 }
536 
_SFFindExistingSlot(SplineFont * sf,int unienc,const char * name)537 static int _SFFindExistingSlot(SplineFont *sf, int unienc, const char *name ) {
538     int gid = -1;
539     struct altuni *altuni;
540 
541     if ( unienc!=-1 ) {
542 	for ( gid=sf->glyphcnt-1; gid>=0; --gid ) if ( sf->glyphs[gid]!=NULL ) {
543 	    if ( sf->glyphs[gid]->unicodeenc==unienc )
544 	break;
545 	    for ( altuni=sf->glyphs[gid]->altuni ; altuni!=NULL &&
546 		    (altuni->unienc!=unienc || altuni->vs!=-1 || altuni->fid!=0);
547 		    altuni=altuni->next );
548 	    if ( altuni!=NULL )
549 	break;
550 	}
551     }
552     if ( gid==-1 && name!=NULL ) {
553 	SplineChar *sc = SFHashName(sf,name);
554 	if ( sc==NULL )
555 return( -1 );
556 	gid = sc->orig_pos;
557 	if ( gid<0 || gid>=sf->glyphcnt ) {
558 	    IError("Invalid glyph location when searching for %s", name );
559 return( -1 );
560 	}
561     }
562 return( gid );
563 }
564 
SFFindExistingSlot(SplineFont * sf,int unienc,const char * name)565 int SFFindExistingSlot(SplineFont *sf, int unienc, const char *name ) {
566     int gid = _SFFindExistingSlot(sf,unienc,name);
567 
568     if ( gid==-1 || !SCWorthOutputting(sf->glyphs[gid]) )
569 return( -1 );
570 
571 return( gid );
572 }
573