1 /* Copyright (C) 2000-2008 by George Williams */
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"
33 RefChar
*RefCharsCopy(RefChar
*ref
) {
34 RefChar
*rhead
=NULL
, *last
=NULL
, *cur
;
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
));
44 for ( layer
=0; layer
<cur
->layer_cnt
; ++layer
) {
45 cur
->layers
[layer
].splines
= NULL
;
46 cur
->layers
[layer
].images
= NULL
;
50 {struct reflayer
*rl
= cur
->layers
;
56 cur
->orig_pos
= cur
->sc
->orig_pos
;
68 static OTLookup
*MCConvertLookup(struct sfmergecontext
*mc
,OTLookup
*otl
) {
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
)
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
;
93 struct lookup_subtable
*MCConvertSubtable(struct sfmergecontext
*mc
,struct lookup_subtable
*sub
) {
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
) {
102 struct lookup_subtable
*subs
;
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
)
113 mc
->prefix
= strconcat(mc
->sf_from
->fontname
,"-");
114 for ( doit
= 0; doit
<2; ++doit
) {
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
) {
119 mc
->lks
[lcnt
].from
= otl
;
120 temp
= strconcat(mc
->prefix
,otl
->lookup_name
);
121 mc
->lks
[lcnt
].to
= SFFindLookup(mc
->sf_to
,temp
);
123 mc
->lks
[lcnt
].old
= mc
->lks
[lcnt
].to
!=NULL
;
126 for ( subs
=otl
->subtables
; subs
!=NULL
; subs
=subs
->next
) {
128 mc
->subs
[scnt
].from
= subs
;
129 temp
= strconcat(mc
->prefix
,subs
->subtable_name
);
130 mc
->subs
[scnt
].to
= SFFindLookupSubtable(mc
->sf_to
,temp
);
132 mc
->subs
[scnt
].old
= mc
->subs
[scnt
].to
!=NULL
;
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
)
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
;
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
));
169 cur
->subtable
= MCConvertSubtable(mc
,base
->subtable
);
170 if ( cur
->type
==pst_ligature
) {
171 cur
->u
.lig
.components
= copy(cur
->u
.lig
.components
);
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
);
191 static AnchorPoint
*AnchorPointsDuplicate(AnchorPoint
*base
,SplineChar
*sc
) {
192 AnchorPoint
*head
=NULL
, *last
=NULL
, *cur
;
195 for ( ; base
!=NULL
; base
= base
->next
) {
196 cur
= chunkalloc(sizeof(AnchorPoint
));
199 for ( ac
=sc
->parent
->anchor
; ac
!=NULL
; ac
=ac
->next
)
200 if ( strcmp(ac
->name
,base
->anchor
->name
)==0 )
204 LogError( "No matching AnchorClass for %s", base
->anchor
->name
);
205 chunkfree(cur
,sizeof(AnchorPoint
));
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
;
232 altuni
= altuni
->next
;
237 SplineChar
*SplineCharCopy(SplineChar
*sc
,SplineFont
*into
,struct sfmergecontext
*mc
) {
242 nsc
= SplineCharCreate(2);
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
;
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
);
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
);
275 nsc
->possub
= PSTCopy(nsc
->possub
,nsc
,mc
);
276 nsc
->altuni
= AltUniCopy(nsc
->altuni
,into
);
280 static int _SFFindExistingSlot(SplineFont
*sf
, int unienc
, const char *name
);
285 struct glyphnamebucket
{
287 struct glyphnamebucket
*next
;
290 struct glyphnamehash
{
291 struct glyphnamebucket
*table
[GN_HSIZE
];
298 static __inline__
int hashname(const char *pt
) {
302 val
= (val
<<3)|((val
>>29)&0x7);
303 val
^= (unsigned char)(*pt
-'!');
312 static void _GlyphHashFree(SplineFont
*sf
) {
313 struct glyphnamebucket
*test
, *next
;
316 if ( sf
->glyphnames
==NULL
)
318 for ( i
=0; i
<GN_HSIZE
; ++i
) {
319 for ( test
= sf
->glyphnames
->table
[i
]; test
!=NULL
; test
= next
) {
321 chunkfree(test
,sizeof(struct glyphnamebucket
));
324 free(sf
->glyphnames
);
325 sf
->glyphnames
= NULL
;
328 void GlyphHashFree(SplineFont
*sf
) {
331 _GlyphHashFree(sf
->cidmaster
);
334 static void GlyphHashCreate(SplineFont
*sf
) {
337 struct glyphnamehash
*gnh
;
338 struct glyphnamebucket
*new;
340 if ( sf
->glyphnames
!=NULL
)
342 sf
->glyphnames
= gnh
= gcalloc(1,sizeof(*gnh
));
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;
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 */
365 struct glyphnamebucket
*new;
367 if ( sf
->glyphnames
==NULL
)
368 return; /* No hash table, nothing to update */
370 new = chunkalloc(sizeof(struct glyphnamebucket
));
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
)
383 for ( test
=sf
->glyphnames
->table
[hashname(name
)]; test
!=NULL
; test
= test
->next
)
384 if ( strcmp(test
->sc
->name
,name
)==0 )
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
;
398 for ( gid
=0; gid
<sf
->glyphcnt
; ++gid
) if ( sf
->glyphs
[gid
]!=NULL
) {
399 if ( sf
->glyphs
[gid
]->unicodeenc
== unienc
)
401 for ( altuni
= sf
->glyphs
[gid
]->altuni
; altuni
!=NULL
; altuni
=altuni
->next
) {
402 if ( altuni
->unienc
== unienc
&& altuni
->vs
==-1 && altuni
->fid
==0 )
408 sc
= SFHashName(sf
,name
);
410 return( sc
->orig_pos
);
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
) {
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
);
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
)
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
)
441 } else if ( unienc
!=-1 &&
442 ((unienc
<0x10000 && map
->enc
->is_unicodebmp
) ||
443 (unienc
<0x110000 && map
->enc
->is_unicodefull
))) {
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
)
452 if ( index
>=map
->enccount
)
456 if ( index
==-1 && name
!=NULL
) {
457 SplineChar
*sc
= SFHashName(sf
,name
);
458 if ( sc
!=NULL
) index
= map
->backmap
[sc
->orig_pos
];
460 unienc
= UniFromName(name
,sf
->uni_interp
,map
->enc
);
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 )
475 int SFCIDFindCID(SplineFont
*sf
, int unienc
, const char *name
) {
477 struct cidmap
*cidmap
;
479 if ( sf
->cidmaster
!=NULL
|| sf
->subfontcnt
!=0 ) {
480 if ( sf
->cidmaster
!=NULL
)
482 cidmap
= FindCidMap(sf
->cidregistry
,sf
->ordering
,sf
->supplement
,sf
);
483 ret
= NameUni2CID(cidmap
,unienc
,name
);
488 if ( sf
->subfonts
==NULL
&& sf
->cidmaster
==NULL
)
489 return( SFFindGID(sf
,unienc
,name
));
491 if ( sf
->cidmaster
!=NULL
)
493 for ( j
=0; j
<sf
->subfontcnt
; ++j
)
494 if (( ret
= SFFindGID(sf
,unienc
,name
))!=-1 )
500 int SFHasCID(SplineFont
*sf
,int cid
) {
502 /* What subfont (if any) contains this cid? */
503 if ( sf
->cidmaster
!=NULL
)
505 for ( i
=0; i
<sf
->subfontcnt
; ++i
)
506 if ( cid
<sf
->subfonts
[i
]->glyphcnt
&&
507 SCWorthOutputting(sf
->subfonts
[i
]->glyphs
[cid
]) )
509 for ( i
=0; i
<sf
->subfontcnt
; ++i
)
510 if ( cid
<sf
->subfonts
[i
]->glyphcnt
&& sf
->subfonts
[i
]->glyphs
[cid
]!=NULL
)
516 SplineChar
*SFGetChar(SplineFont
*sf
, int unienc
, const char *name
) {
520 ind
= SFCIDFindCID(sf
,unienc
,name
);
524 if ( sf
->subfonts
==NULL
&& sf
->cidmaster
==NULL
)
525 return( sf
->glyphs
[ind
]);
527 if ( sf
->cidmaster
!=NULL
)
530 j
= SFHasCID(sf
,ind
);
534 return( sf
->subfonts
[j
]->glyphs
[ind
] );
537 static int _SFFindExistingSlot(SplineFont
*sf
, int unienc
, const char *name
) {
539 struct altuni
*altuni
;
542 for ( gid
=sf
->glyphcnt
-1; gid
>=0; --gid
) if ( sf
->glyphs
[gid
]!=NULL
) {
543 if ( sf
->glyphs
[gid
]->unicodeenc
==unienc
)
545 for ( altuni
=sf
->glyphs
[gid
]->altuni
; altuni
!=NULL
&&
546 (altuni
->unienc
!=unienc
|| altuni
->vs
!=-1 || altuni
->fid
!=0);
547 altuni
=altuni
->next
);
552 if ( gid
==-1 && name
!=NULL
) {
553 SplineChar
*sc
= SFHashName(sf
,name
);
557 if ( gid
<0 || gid
>=sf
->glyphcnt
) {
558 IError("Invalid glyph location when searching for %s", name
);
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
]) )