beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / luafontloader / fontforge / fontforge / fvfonts.c
blobdb709cea56e84b16180f782f9d7fdf16c26804a7
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.
27 #include "fontforgevw.h"
28 #include "ustring.h"
29 #include "utype.h"
30 #include "gfile.h"
31 #include "chardata.h"
33 RefChar *RefCharsCopy(RefChar *ref) {
34 RefChar *rhead=NULL, *last=NULL, *cur;
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;
49 #else
50 {struct reflayer *rl = cur->layers;
51 *cur = *ref;
52 cur->layers = rl;
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;
65 return( rhead );
68 static OTLookup *MCConvertLookup(struct sfmergecontext *mc,OTLookup *otl) {
69 int l;
70 OTLookup *newotl;
72 if ( mc==NULL || mc->sf_from==mc->sf_to )
73 return( otl ); /* No translation needed */
75 for ( l=0; l<mc->lcnt; ++l ) {
76 if ( mc->lks[l].from == otl )
77 break;
79 if ( l==mc->lcnt )
80 return( NULL );
81 if ( mc->lks[l].to!=NULL )
82 return( mc->lks[l].to );
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 );
93 struct lookup_subtable *MCConvertSubtable(struct sfmergecontext *mc,struct lookup_subtable *sub) {
94 int s;
95 struct lookup_subtable *newsub;
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;
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;
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;
134 ++scnt;
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));
146 for ( s=0; s<mc->scnt; ++s ) {
147 if ( mc->subs[s].from == sub )
148 break;
150 if ( s==mc->scnt )
151 return( NULL );
152 if ( mc->subs[s].to!=NULL )
153 return( mc->subs[s].to );
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 );
163 PST *PSTCopy(PST *base,SplineChar *sc,struct sfmergecontext *mc) {
164 PST *head=NULL, *last=NULL, *cur;
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;
188 return( head );
191 static AnchorPoint *AnchorPointsDuplicate(AnchorPoint *base,SplineChar *sc) {
192 AnchorPoint *head=NULL, *last=NULL, *cur;
193 AnchorClass *ac;
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;
214 return( head );
217 static struct altuni *AltUniCopy(struct altuni *altuni,SplineFont *noconflicts) {
218 struct altuni *head=NULL, *last=NULL, *cur;
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;
232 altuni = altuni->next;
234 return( head );
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);
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;
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);
274 nsc->kerns = NULL;
275 nsc->possub = PSTCopy(nsc->possub,nsc,mc);
276 nsc->altuni = AltUniCopy(nsc->altuni,into);
277 return(nsc);
280 static int _SFFindExistingSlot(SplineFont *sf, int unienc, const char *name );
283 #define GN_HSIZE 257
285 struct glyphnamebucket {
286 SplineChar *sc;
287 struct glyphnamebucket *next;
290 struct glyphnamehash {
291 struct glyphnamebucket *table[GN_HSIZE];
294 #ifndef __GNUC__
295 # define __inline__
296 #endif
298 static __inline__ int hashname(const char *pt) {
299 int val = 0;
301 while ( *pt ) {
302 val = (val<<3)|((val>>29)&0x7);
303 val ^= (unsigned char)(*pt-'!');
304 pt++;
306 val ^= (val>>16);
307 val &= 0xffff;
308 val %= GN_HSIZE;
309 return( val );
312 static void _GlyphHashFree(SplineFont *sf) {
313 struct glyphnamebucket *test, *next;
314 int i;
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));
324 free(sf->glyphnames);
325 sf->glyphnames = NULL;
328 void GlyphHashFree(SplineFont *sf) {
329 _GlyphHashFree(sf);
330 if ( sf->cidmaster )
331 _GlyphHashFree(sf->cidmaster);
334 static void GlyphHashCreate(SplineFont *sf) {
335 int i, k, hash;
336 SplineFont *_sf;
337 struct glyphnamehash *gnh;
338 struct glyphnamebucket *new;
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;
358 ++k;
359 } while ( k<sf->subfontcnt );
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;
367 if ( sf->glyphnames==NULL )
368 return; /* No hash table, nothing to update */
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;
377 SplineChar *SFHashName(SplineFont *sf,const char *name) {
378 struct glyphnamebucket *test;
380 if ( sf->glyphnames==NULL )
381 GlyphHashCreate(sf);
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 );
387 return( NULL );
390 /* Find the position in the glyph list where this code point/name is found. */
391 /* Returns -1 else on error */
392 int SFFindGID(SplineFont *sf, int unienc, const char *name ) {
393 struct altuni *altuni;
394 int gid;
395 SplineChar *sc;
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 );
407 if ( name!=NULL ) {
408 sc = SFHashName(sf,name);
409 if ( sc!=NULL )
410 return( sc->orig_pos );
413 return ( -1 );
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 */
418 int SFFindSlot(SplineFont *sf, EncMap *map, int unienc, const char *name ) {
419 int index=-1, pos;
420 struct cidmap *cidmap;
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;
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;
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 );
472 return( index );
475 int SFCIDFindCID(SplineFont *sf, int unienc, const char *name ) {
476 int j,ret;
477 struct cidmap *cidmap;
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 );
488 if ( sf->subfonts==NULL && sf->cidmaster==NULL )
489 return( SFFindGID(sf,unienc,name));
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 );
497 return( -1 );
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 );
513 return( -1 );
516 SplineChar *SFGetChar(SplineFont *sf, int unienc, const char *name ) {
517 int ind;
518 int j;
520 ind = SFCIDFindCID(sf,unienc,name);
521 if ( ind==-1 )
522 return( NULL );
524 if ( sf->subfonts==NULL && sf->cidmaster==NULL )
525 return( sf->glyphs[ind]);
527 if ( sf->cidmaster!=NULL )
528 sf=sf->cidmaster;
530 j = SFHasCID(sf,ind);
531 if ( j==-1 )
532 return( NULL );
534 return( sf->subfonts[j]->glyphs[ind] );
537 static int _SFFindExistingSlot(SplineFont *sf, int unienc, const char *name ) {
538 int gid = -1;
539 struct altuni *altuni;
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;
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 );
562 return( gid );
565 int SFFindExistingSlot(SplineFont *sf, int unienc, const char *name ) {
566 int gid = _SFFindExistingSlot(sf,unienc,name);
568 if ( gid==-1 || !SCWorthOutputting(sf->glyphs[gid]) )
569 return( -1 );
571 return( gid );