beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / luafontloader / fontforge / fontforge / splinesave.c
blob75f951038586e1ca323d7d2e536ea5bcb80c1ac0
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 "pfaedit.h"
28 #include <stdio.h>
29 #include <math.h>
30 #include "splinefont.h"
31 #include "psfont.h"
32 #include <ustring.h>
33 #include <string.h>
34 #include <utype.h>
36 int autohint_before_generate = 1;
38 /* Let's talk about references. */
39 /* If we are doing Type1 output, then the obvious way of doing them is seac */
40 /* but that's so limitting. It only works for exactly two characters both */
41 /* of which are in Adobe's Standard Enc. Only translations allowed. Only */
42 /* one reference may be translated and the width of the char must match */
43 /* that of the non-translated reference */
44 /* The first extension we can make is to allow a single character reference */
45 /* by making the other character be a space */
46 /* But if we want to do more than that we must use subrs. If we have two */
47 /* refs in subrs then we can do translations by preceding the subr calls by */
48 /* appropriate rmovetos. Actually the specs say that only one rmoveto should */
49 /* precede a path, so that means we can't allow the subroutines to position */
50 /* themselves, they must just assume that they are called with the current */
51 /* position correct for the first point. But then we need to know where the */
52 /* first point should be placed, so we allocate a BasePoint to hold that info*/
53 /* and store it into the "keys" array (which the subrs don't use). Similarly */
54 /* we need to know where the subr will leave us, so we actually allocate 2 */
55 /* BasePoints, one containing the start point, one the end point */
56 /* But that's still not good enough, hints are defined in such a way that */
57 /* they are not relocateable. So our subrs can't include any hint definitions*/
58 /* (or if they do then that subr can't be translated at all). So hints must */
59 /* be set outside the subrs, and the subrs can't be for chars that need hint */
60 /* substitution. Unless... The subr will never be relocated. */
61 /* So we generate two types of reference subrs, one containing no hints, the*/
62 /* other containing all the hints, stems and flexes. The first type may be */
63 /* translated, the second cannot */
64 /* Type2 doesn't allow any seacs */
65 /* So everything must go in subrs. We have a slightly different problem here:*/
66 /* hintmasks need to know exactly how many stem hints there are in the char */
67 /* so we can't include any hintmask operators inside a subr (unless we */
68 /* guarantee that all invocations of that subr are done with the same number */
69 /* of hints in the character). This again means that no char with hint subs- */
70 /* titutions may be put in a subr. UNLESS all the other references in a */
71 /* refering character contain no hints */
73 /* That's very complex. And it doesn't do a very good job. */
74 /* Instead let's take all strings bounded by either moveto or hintmask operators */
75 /* store these as potential subroutines. So a glyph becomes a sequence of */
76 /* potential subroutine calls preceded by the glyph header (width, hint decl,*/
77 /* counter declarations, etc.) and intersperced by hintmask/moveto operators */
78 /* Each time we get a potential subr we hash it and see if we've used that */
79 /* string before. If we have then we merge the two. Otherwise it's a new one.*/
80 /* Then at the end we see what strings get used often enough to go into subrs */
81 /* we create the subrs array from that. */
82 /* Then each glyph. We insert the preamble. We check of the potential subroutine */
83 /* became a real subroutine. If so we call it, else we insert the data inline*/
84 /* Do the same for the next hintmask/moveto and potential subroutine... */
86 /* Then, on top of that I tried generating some full glyph subroutines, and */
87 /* to my surprise, it just made things worse. */
89 typedef struct growbuf {
90 unsigned char *pt;
91 unsigned char *base;
92 unsigned char *end;
93 } GrowBuf;
95 #define HSH_SIZE 511
96 /* In type2 charstrings we divide every character into bits where a bit is */
97 /* bounded by a hintmask/moveto. Each of these is a potential subroutine and */
98 /* is stored here */
99 typedef struct glyphinfo {
100 struct potentialsubrs {
101 uint8 *data; /* the charstring of the subr */
102 int len; /* the length of the charstring */
103 int idx; /* initially index into psubrs array */
104 /* then index into subrs array or -1 if none */
105 int cnt; /* the usage count */
106 int fd; /* Which sub font is it in */
107 /* -1 => used in more than one */
108 int next;
109 int full_glyph_index; /* Into the glyphbits array */
110 /* for full references */
111 BasePoint *startstop; /* Again for full references */
112 } *psubrs;
113 int pcnt, pmax;
114 int hashed[HSH_SIZE];
115 struct glyphbits {
116 SplineChar *sc;
117 int fd; /* Which subfont is it in */
118 int bcnt;
119 struct bits {
120 uint8 *data;
121 int dlen;
122 int psub_index;
123 } *bits;
124 uint8 wasseac;
125 } *gb, *active;
126 SplineFont *sf;
127 int layer;
128 int glyphcnt;
129 int subfontcnt;
130 int bcnt, bmax;
131 struct bits *bits; /* For current glyph */
132 const int *bygid;
133 int justbroken;
134 int instance_count;
135 } GlyphInfo;
137 struct mhlist {
138 uint8 mask[HntMax/8];
139 int subr;
140 struct mhlist *next;
143 struct hintdb {
144 uint8 mask[HntMax/8];
145 int cnt; /* number of hints */
146 struct mhlist *sublist;
147 struct pschars *subrs;
148 /*SplineChar *sc;*/
149 SplineChar **scs;
150 int instance_count;
151 unsigned int iscjk: 1; /* If cjk then don't do stem3 hints */
152 /* Will be done with counters instead */
153 /* actually, most of the time we can't use stem3s, only if those three*/
154 /* stems are always active and there are no other stems !(h/v)hasoverlap*/
155 unsigned int noconflicts: 1;
156 unsigned int startset: 1;
157 unsigned int skiphm: 1; /* Set when coming back to the start point of a contour. hintmask should be set the first time, not the second */
158 unsigned int donefirsthm: 1;
159 int cursub; /* Current subr number */
160 DBasePoint current;
161 GlyphInfo *gi;
164 static void GIContentsFree(GlyphInfo *gi,SplineChar *dummynotdef) {
165 int i,j;
167 if ( gi->glyphcnt>0 && gi->gb[0].sc == dummynotdef ) {
168 if ( dummynotdef->layers!=NULL ) {
169 SplinePointListsFree(dummynotdef->layers[gi->layer].splines);
170 dummynotdef->layers[gi->layer].splines = NULL;
172 StemInfosFree(dummynotdef->hstem);
173 StemInfosFree(dummynotdef->vstem);
174 dummynotdef->vstem = dummynotdef->hstem = NULL;
175 free(dummynotdef->layers);
176 dummynotdef->layers = NULL;
179 for ( i=0; i<gi->pcnt; ++i ) {
180 free(gi->psubrs[i].data);
181 free(gi->psubrs[i].startstop);
182 gi->psubrs[i].data = NULL;
183 gi->psubrs[i].startstop = NULL;
185 for ( i=0; i<gi->glyphcnt; ++i ) {
186 for ( j=0; j<gi->gb[i].bcnt; ++j )
187 free(gi->gb[i].bits[j].data);
188 free(gi->gb[i].bits);
189 gi->gb[i].bits = NULL;
190 gi->gb[i].bcnt = 0;
193 gi->pcnt = 0;
194 gi->bcnt = 0;
195 gi->justbroken = 0;
198 static void GIFree(GlyphInfo *gi,SplineChar *dummynotdef) {
200 GIContentsFree(gi,dummynotdef);
202 free(gi->gb);
203 free(gi->psubrs);
204 free(gi->bits);
207 static void GrowBuffer(GrowBuf *gb) {
208 if ( gb->base==NULL ) {
209 gb->base = gb->pt = galloc(200);
210 gb->end = gb->base + 200;
211 } else {
212 int len = (gb->end-gb->base) + 400;
213 int off = gb->pt-gb->base;
214 gb->base = grealloc(gb->base,len);
215 gb->end = gb->base + len;
216 gb->pt = gb->base+off;
220 static void StartNextSubroutine(GrowBuf *gb,struct hintdb *hdb) {
221 GlyphInfo *gi;
223 if ( hdb==NULL )
224 return;
225 gi = hdb->gi;
226 if ( gi==NULL )
227 return;
228 /* Store everything in the grow buf into the data/dlen of the next bit */
229 if ( gi->bcnt==-1 ) gi->bcnt = 0;
230 if ( gi->bcnt>=gi->bmax )
231 gi->bits = grealloc(gi->bits,(gi->bmax+=20)*sizeof(struct bits));
232 gi->bits[gi->bcnt].dlen = gb->pt-gb->base;
233 gi->bits[gi->bcnt].data = galloc(gi->bits[gi->bcnt].dlen);
234 gi->bits[gi->bcnt].psub_index = -1;
235 memcpy(gi->bits[gi->bcnt].data,gb->base,gi->bits[gi->bcnt].dlen);
236 gb->pt = gb->base;
237 gi->justbroken = false;
240 static int hashfunc(uint8 *data, int len) {
241 uint8 *end = data+len;
242 unsigned int hash = 0, r;
244 while ( data<end ) {
245 r = (hash>>30)&3;
246 hash <<= 2;
247 hash = (hash|r)&0xffffffff;
248 hash ^= *data++;
250 return( hash%HSH_SIZE );
253 static void BreakSubroutine(GrowBuf *gb,struct hintdb *hdb) {
254 GlyphInfo *gi;
255 struct potentialsubrs *ps;
256 int hash;
257 int pi;
259 if ( hdb==NULL )
260 return;
261 gi = hdb->gi;
262 if ( gi==NULL )
263 return;
264 /* The stuff before the first moveto in a glyph (the header that sets */
265 /* the width, sets up the hints, counters, etc.) can't go into a subr */
266 if ( gi->bcnt==-1 ) {
267 gi->bcnt=0;
268 gi->justbroken = true;
269 return;
270 } else if ( gi->justbroken )
271 return;
272 /* Otherwise stuff everything in the growbuffer into a subr */
273 hash = hashfunc(gb->base,gb->pt-gb->base);
274 ps = NULL;
275 for ( pi=gi->hashed[hash]; pi!=-1; pi=gi->psubrs[pi].next ) {
276 ps = &gi->psubrs[pi];
277 if ( ps->len==gb->pt-gb->base && memcmp(ps->data,gb->base,gb->pt-gb->base)==0 )
278 break;
280 if ( pi==-1 ) {
281 if ( gi->pcnt>=gi->pmax )
282 gi->psubrs = grealloc(gi->psubrs,(gi->pmax+=gi->glyphcnt)*sizeof(struct potentialsubrs));
283 ps = &gi->psubrs[gi->pcnt];
284 memset(ps,0,sizeof(*ps)); /* set cnt to 0 */
285 ps->idx = gi->pcnt++;
286 ps->len = gb->pt-gb->base;
287 ps->data = galloc(ps->len);
288 memcpy(ps->data,gb->base,ps->len);
289 ps->next = gi->hashed[hash];
290 gi->hashed[hash] = ps->idx;
291 ps->fd = gi->active->fd;
292 ps->full_glyph_index = -1;
294 if ( ps->fd!=gi->active->fd )
295 ps->fd = -1; /* used in multiple cid sub-fonts */
296 gi->bits[gi->bcnt].psub_index = ps->idx;
297 ++ps->cnt;
298 gb->pt = gb->base;
299 ++gi->bcnt;
300 gi->justbroken = true;
303 static void MoveSubrsToChar(GlyphInfo *gi) {
304 struct glyphbits *active;
306 if ( gi==NULL )
307 return;
308 active = gi->active;
309 active->bcnt = gi->bcnt;
310 active->bits = galloc(active->bcnt*sizeof(struct bits));
311 memcpy(active->bits,gi->bits,active->bcnt*sizeof(struct bits));
312 gi->bcnt = 0;
315 static int NumberHints(SplineChar *scs[MmMax], int instance_count) {
316 int i,j, cnt=-1;
317 StemInfo *s;
319 for ( j=0; j<instance_count; ++j ) {
320 for ( s=scs[j]->hstem, i=0; s!=NULL; s=s->next ) {
321 if ( i<HntMax )
322 s->hintnumber = i++;
323 else
324 s->hintnumber = -1;
326 for ( s=scs[j]->vstem; s!=NULL; s=s->next ) {
327 if ( i<HntMax )
328 s->hintnumber = i++;
329 else
330 s->hintnumber = -1;
332 if ( cnt==-1 )
333 cnt = i;
334 else if ( cnt!=i )
335 IError("MM font with different hint counts");
337 return( cnt );
340 void RefCharsFreeRef(RefChar *ref) {
341 RefChar *rnext;
343 while ( ref!=NULL ) {
344 rnext = ref->next;
345 /* don't free the splines */
346 chunkfree(ref,sizeof(RefChar));
347 ref = rnext;
351 static void MarkTranslationRefs(SplineFont *sf,int layer) {
352 int i;
353 SplineChar *sc;
354 RefChar *r;
356 for ( i=0; i<sf->glyphcnt; ++i ) if ( (sc = sf->glyphs[i])!=NULL ) {
357 for ( r = sc->layers[layer].refs; r!=NULL; r=r->next )
358 r->justtranslated = (r->transform[0]==1 && r->transform[3]==1 &&
359 r->transform[1]==0 && r->transform[2]==0);
363 /* ************************************************************************** */
364 /* ********************** Type1 PostScript CharStrings ********************** */
365 /* ************************************************************************** */
367 static real myround( real pos, int round ) {
368 if ( round )
369 return( rint( pos ));
370 else
371 return( rint( pos*100. )/100. );
374 static void AddNumber(GrowBuf *gb, real pos, int round) {
375 int dodiv = 0;
376 int val;
377 unsigned char *str;
379 if ( gb->pt+8>=gb->end )
380 GrowBuffer(gb);
382 pos = rint(100*pos)/100;
384 if ( !round && pos!=floor(pos)) {
385 pos *= 100;
386 dodiv = true;
388 str = gb->pt;
389 val = rint(pos);
390 if ( pos>=-107 && pos<=107 )
391 *str++ = val+139;
392 else if ( pos>=108 && pos<=1131 ) {
393 val -= 108;
394 *str++ = (val>>8)+247;
395 *str++ = val&0xff;
396 } else if ( pos>=-1131 && pos<=-108 ) {
397 val = -val;
398 val -= 108;
399 *str++ = (val>>8)+251;
400 *str++ = val&0xff;
401 } else {
402 *str++ = '\377';
403 *str++ = (val>>24)&0xff;
404 *str++ = (val>>16)&0xff;
405 *str++ = (val>>8)&0xff;
406 *str++ = val&0xff;
408 if ( dodiv ) {
409 *str++ = 100+139; /* 100 */
410 *str++ = 12; /* div (byte1) */
411 *str++ = 12; /* div (byte2) */
413 gb->pt = str;
416 /* When doing a multiple master font we have multiple instances of the same data */
417 /* which must all be added, and then a call made to the appropriate blend routine */
418 /* This is complicated because all the data may not fit on the stack so we */
419 /* may need to make multiple calls */
420 static void AddData(GrowBuf *gb, real data[MmMax][6], int instances, int num_coords,
421 int round) {
422 int allsame = true, alls[6];
423 int i,j, chunk,min,max,subr;
425 for ( j=0; j<num_coords; ++j ) {
426 alls[j] = true;
427 for ( i=1; i<instances; ++i ) {
428 if ( data[i][j]!=data[0][j] ) {
429 alls[j] = false;
430 allsame = false;
431 break;
436 if ( allsame ) { /* No need for blending */
437 /* Probably a normal font, but possible in an mm */
438 for ( j=0; j<num_coords; ++j )
439 AddNumber(gb,data[0][j],round);
440 return;
443 chunk = 22/instances;
444 if ( chunk == 5 ) chunk = 4; /* No subroutine for 5 items */
445 min = 0;
446 while ( min<num_coords ) {
447 while ( min<num_coords && alls[min] ) {
448 AddNumber(gb,data[0][min],round);
449 ++min;
451 max = min+chunk;
452 if ( max>num_coords ) max = num_coords;
453 while ( max-1>min && alls[max-1] )
454 --max;
455 if ( max-min==5 ) max=min+4;
456 if ( min<max ) {
457 for ( j=min; j<max; ++j )
458 AddNumber(gb,data[0][j],round);
459 for ( j=min; j<max; ++j )
460 for ( i=1; i<instances; ++i )
461 AddNumber(gb,data[i][j]-data[0][j],round);
462 subr = (j-min) + 4;
463 if ( j-min==6 ) subr = 9;
464 AddNumber(gb,subr,round);
465 if ( gb->pt+1>=gb->end )
466 GrowBuffer(gb);
467 *gb->pt++ = 10; /* callsubr */
468 min = j;
473 int CvtPsStem3(GrowBuf *gb, SplineChar *scs[MmMax], int instance_count,
474 int ishstem, int round) {
475 StemInfo *h1, *h2, *h3;
476 StemInfo _h1, _h2, _h3;
477 real data[MmMax][6];
478 int i;
479 real off;
481 for ( i=0; i<instance_count; ++i ) {
482 if ( (ishstem && scs[i]->hconflicts) || (!ishstem && scs[i]->vconflicts))
483 return( false );
484 h1 = ishstem ? scs[i]->hstem : scs[i]->vstem;
485 if ( h1==NULL || (h2 = h1->next)==NULL || (h3=h2->next)==NULL )
486 return( false );
487 if ( h3->next!=NULL )
488 return( false );
489 off = ishstem ? 0 : scs[i]->lsidebearing;
490 if ( h1->width<0 ) {
491 _h1 = *h1;
492 _h1.start += _h1.width;
493 _h1.width = -_h1.width;
494 h1 = &_h1;
496 if ( h2->width<0 ) {
497 _h2 = *h2;
498 _h2.start += _h2.width;
499 _h2.width = -_h2.width;
500 h2 = &_h2;
502 if ( h3->width<0 ) {
503 _h3 = *h3;
504 _h3.start += _h3.width;
505 _h3.width = -_h3.width;
506 h3 = &_h3;
509 if ( h1->start>h2->start ) {
510 StemInfo *ht = h1; h1 = h2; h2 = ht;
512 if ( h1->start>h3->start ) {
513 StemInfo *ht = h1; h1 = h3; h3 = ht;
515 if ( h2->start>h3->start ) {
516 StemInfo *ht = h2; h2 = h3; h3 = ht;
518 if ( h1->width != h3->width )
519 return( false );
520 if ( (h2->start+h2->width/2) - (h1->start+h1->width/2) !=
521 (h3->start+h3->width/2) - (h2->start+h2->width/2) )
522 return( false );
523 data[i][0] = h1->start-off;
524 data[i][1] = h1->width;
525 data[i][2] = h2->start-off;
526 data[i][3] = h2->width;
527 data[i][4] = h3->start-off;
528 data[i][5] = h3->width;
530 if ( gb==NULL )
531 return( true );
532 AddData(gb,data,instance_count,6,round);
533 if ( gb->pt+3>=gb->end )
534 GrowBuffer(gb);
535 *(gb->pt)++ = 12;
536 *(gb->pt)++ = ishstem?2:1; /* h/v stem3 */
537 return( true );
540 static int _SCNeedsSubsPts(SplineChar *sc,int layer) {
541 RefChar *ref;
543 if ( sc->hstem==NULL && sc->vstem==NULL )
544 return( false );
546 if ( sc->layers[layer].splines!=NULL )
547 return( sc->layers[layer].splines->first->hintmask==NULL );
549 for ( ref = sc->layers[layer].refs; ref!=NULL; ref=ref->next )
550 if ( ref->layers[0].splines!=NULL )
551 return( ref->layers[0].splines->first->hintmask==NULL );
553 return( false ); /* It's empty. that's easy. */
556 static int SCNeedsSubsPts(SplineChar *sc,enum fontformat format,int layer) {
557 if ( (format!=ff_mma && format!=ff_mmb) || sc->parent->mm==NULL ) {
558 if ( !sc->hconflicts && !sc->vconflicts )
559 return( false ); /* No conflicts, no swap-over points needed */
560 return( _SCNeedsSubsPts(sc,layer));
561 } else {
562 MMSet *mm = sc->parent->mm;
563 int i;
564 for ( i=0; i<mm->instance_count; ++i ) if ( sc->orig_pos<mm->instances[i]->glyphcnt ) {
565 if ( _SCNeedsSubsPts(mm->instances[i]->glyphs[sc->orig_pos],layer) )
566 return( true );
568 return( false );
572 /* Mark those glyphs which can live totally in subrs */
573 static void SplineFont2FullSubrs1(int flags,GlyphInfo *gi) {
574 int i;
575 SplineChar *sc;
577 for ( i=0; i<gi->glyphcnt; ++i ) if ( (sc=gi->gb[i].sc)!=NULL )
578 sc->ttf_glyph = 0x7fff;
582 int SFOneWidth(SplineFont *sf) {
583 int width, i;
585 width = -2;
586 for ( i=0; i<sf->glyphcnt; ++i ) if ( SCWorthOutputting(sf->glyphs[i]) &&
587 (strcmp(sf->glyphs[i]->name,".notdef")!=0 || sf->glyphs[i]->layers[ly_fore].splines!=NULL)) {
588 /* Only trust the width of notdef if it's got some content */
589 /* (at least as far as fixed pitch determination goes) */
590 if ( width==-2 ) width = sf->glyphs[i]->width;
591 else if ( width!=sf->glyphs[i]->width ) {
592 width = -1;
593 break;
596 return(width);
599 int CIDOneWidth(SplineFont *_sf) {
600 int width, i;
601 int k;
602 SplineFont *sf;
604 if ( _sf->cidmaster!=NULL ) _sf = _sf->cidmaster;
605 width = -2;
606 k=0;
607 do {
608 sf = _sf->subfonts==NULL? _sf : _sf->subfonts[k];
609 for ( i=0; i<sf->glyphcnt; ++i ) if ( SCWorthOutputting(sf->glyphs[i]) &&
610 strcmp(sf->glyphs[i]->name,".null")!=0 &&
611 strcmp(sf->glyphs[i]->name,"nonmarkingreturn")!=0 &&
612 (strcmp(sf->glyphs[i]->name,".notdef")!=0 || sf->glyphs[i]->layers[ly_fore].splines!=NULL)) {
613 /* Only trust the width of notdef if it's got some content */
614 /* (at least as far as fixed pitch determination goes) */
615 if ( width==-2 ) width = sf->glyphs[i]->width;
616 else if ( width!=sf->glyphs[i]->width ) {
617 width = -1;
618 break;
621 ++k;
622 } while ( k<_sf->subfontcnt );
623 return(width);
627 static void SetupType1Subrs(struct pschars *subrs,GlyphInfo *gi) {
628 int scnt, call_size;
629 int i;
631 scnt = subrs->next;
632 call_size = gi->pcnt+scnt<1131 ? 3 : 6;
633 for ( i=0; i<gi->pcnt; ++i ) {
634 /* A subroutine call takes somewhere between 2 and 6 bytes itself. */
635 /* and we must add a return statement to the end. We don't want to */
636 /* make things bigger */
637 if ( gi->psubrs[i].full_glyph_index!=-1 )
638 gi->psubrs[i].idx = scnt++;
639 else if ( gi->psubrs[i].cnt*gi->psubrs[i].len>(gi->psubrs[i].cnt*call_size)+gi->psubrs[i].len+1 )
640 gi->psubrs[i].idx = scnt++;
641 else
642 gi->psubrs[i].idx = -1;
645 subrs->cnt = scnt;
646 subrs->next = scnt;
647 subrs->lens = grealloc(subrs->lens,scnt*sizeof(int));
648 subrs->values = grealloc(subrs->values,scnt*sizeof(unsigned char *));
650 for ( i=0; i<gi->pcnt; ++i ) {
651 scnt = gi->psubrs[i].idx;
652 if ( scnt==-1 || gi->psubrs[i].full_glyph_index != -1 )
653 continue;
654 subrs->lens[scnt] = gi->psubrs[i].len+1;
655 subrs->values[scnt] = galloc(subrs->lens[scnt]);
656 memcpy(subrs->values[scnt],gi->psubrs[i].data,gi->psubrs[i].len);
657 subrs->values[scnt][gi->psubrs[i].len] = 11; /* Add a return to end of subr */
661 static void SetupType1Chrs(struct pschars *chrs,struct pschars *subrs,GlyphInfo *gi, int iscid) {
662 int i,k,j;
664 /* If a glyph lives entirely in a subroutine then we need to create both */
665 /* the subroutine entry, and the char entry which calls the subr. */
666 /* The subroutine entry will be everything EXCEPT the glyph header */
667 /* the char entry will be the glyph header and a subroutine call */
668 /* If the glyph does not go into a subr then everything goes into the char */
669 for ( i=0; i<gi->glyphcnt; ++i ) {
670 int len=0;
671 struct glyphbits *gb = &gi->gb[i];
672 if ( gb->sc==NULL )
673 continue;
674 if ( !iscid )
675 chrs->keys[i] = copy(gb->sc->name);
676 for ( k=0; k<2; ++k ) if ( k!=0 || gb->sc->ttf_glyph!=0x7fff ) {
677 uint8 *vals;
678 for ( j=0; j<gb->bcnt; ++j ) {
679 if ( k!=0 || j!=0 )
680 len += gb->bits[j].dlen;
681 if ( k==1 && gb->sc->ttf_glyph!=0x7fff ) {
682 int si = gi->psubrs[ gb->sc->ttf_glyph ].idx;
683 len += 1 + (si<=107?1:si<=1131?2:5);
684 break;
686 if ( gi->psubrs[ gb->bits[j].psub_index ].idx==-1 )
687 len += gi->psubrs[ gb->bits[j].psub_index ].len;
688 else {
689 int si = gi->psubrs[ gb->bits[j].psub_index ].idx;
690 len += 1 + (si<=107?1:si<=1131?2:5);
691 /* Space for a subr call & the sub number to call */
694 if ( k==0 ) {
695 int si = gi->psubrs[ gb->sc->ttf_glyph ].idx;
696 subrs->lens[si] = len+1;
697 vals = subrs->values[si] = galloc(len+2);
698 } else {
699 /* Don't need or want and endchar if we are using seac */
700 chrs->lens[i] = len + !gb->wasseac;
701 vals = chrs->values[i] = galloc(len+2); /* space for endchar and a final NUL (which is really meaningless, but makes me feel better) */
704 len = 0;
705 for ( j=0; j<gb->bcnt; ++j ) {
706 int si;
707 if ( k!=0 || j!=0 ) {
708 memcpy(vals+len,gb->bits[j].data,gb->bits[j].dlen);
709 len += gb->bits[j].dlen;
711 si = -1;
712 if ( k==1 && gb->sc->ttf_glyph!=0x7fff )
713 si = gi->psubrs[ gb->sc->ttf_glyph ].idx;
714 else if ( gi->psubrs[ gb->bits[j].psub_index ].idx==-1 ) {
715 memcpy(vals+len,gi->psubrs[ gb->bits[j].psub_index ].data,
716 gi->psubrs[ gb->bits[j].psub_index ].len);
717 len += gi->psubrs[ gb->bits[j].psub_index ].len;
718 } else
719 si = gi->psubrs[ gb->bits[j].psub_index ].idx;
720 if ( si!=-1 ) {
721 /* space for the number (subroutine index) */
722 if ( si<=107 )
723 vals[len++] = si+139;
724 else if ( si>0 && si<=1131 ) {
725 si-=108;
726 vals[len++] = (si>>8)+247;
727 vals[len++] = si&0xff;
728 } else {
729 vals[len++] = '\377';
730 vals[len++] = (si>>24)&0xff;
731 vals[len++] = (si>>16)&0xff;
732 vals[len++] = (si>>8)&0xff;
733 vals[len++] = si&0xff;
735 /* space for the subroutine operator */
736 vals[len++] = 10;
738 if ( k==1 && gb->sc->ttf_glyph!=0x7fff )
739 break;
741 if ( k==0 ) {
742 vals[len++] = 11; /* return */
743 vals[len] = '\0';
744 } else if ( gb->wasseac ) {
745 /* Don't want an endchar */
746 vals[len] = '\0';
747 } else {
748 vals[len++] = 14; /* endchar */
749 vals[len] = '\0';
755 /* ************************************************************************** */
756 /* ********************** Type2 PostScript CharStrings ********************** */
757 /* ************************************************************************** */
759 #if 0
760 static int real_warn = false;
761 #endif
763 static real myround2(real pos, int round) {
764 if ( round )
765 return( rint(pos));
767 return( rint(65536*pos)/65536 );
770 static void AddNumber2(GrowBuf *gb, real pos, int round) {
771 int val, factor;
772 unsigned char *str;
774 if ( gb->pt+5>=gb->end )
775 GrowBuffer(gb);
777 pos = rint(65536*pos)/65536;
778 if ( round )
779 pos = rint(pos);
781 str = gb->pt;
782 if ( pos>32767.99 || pos<-32768 ) {
783 /* same logic for big ints and reals */
784 if ( pos>0x3fffffff || pos<-0x40000000 ) {
785 LogError( _("Number out of range: %g in type2 output (must be [-65536,65535])\n"),
786 pos );
787 if ( pos>0 ) pos = 0x3fffffff; else pos = -0x40000000;
789 for ( factor=2; factor<32768; factor<<=2 )
790 if ( pos/factor<32767.99 && pos/factor>-32768 )
791 break;
792 AddNumber2(gb,pos/factor,false);
793 AddNumber2(gb,factor,false);
794 if ( gb->pt+2>=gb->end )
795 GrowBuffer(gb);
796 *(gb->pt++) = 0x0c; /* Multiply operator */
797 *(gb->pt++) = 0x18;
798 } else if ( pos!=floor(pos )) {
799 val = pos*65536;
800 *str++ = '\377';
801 *str++ = (val>>24)&0xff;
802 *str++ = (val>>16)&0xff;
803 *str++ = (val>>8)&0xff;
804 *str++ = val&0xff;
805 } else {
806 val = rint(pos);
807 if ( pos>=-107 && pos<=107 )
808 *str++ = val+139;
809 else if ( pos>=108 && pos<=1131 ) {
810 val -= 108;
811 *str++ = (val>>8)+247;
812 *str++ = val&0xff;
813 } else if ( pos>=-1131 && pos<=-108 ) {
814 val = -val;
815 val -= 108;
816 *str++ = (val>>8)+251;
817 *str++ = val&0xff;
818 } else {
819 *str++ = 28;
820 *str++ = (val>>8)&0xff;
821 *str++ = val&0xff;
824 gb->pt = str;
827 static void AddMask2(GrowBuf *gb,uint8 mask[12],int cnt, int oper) {
828 int i;
830 if ( gb->pt+1+((cnt+7)>>3)>=gb->end )
831 GrowBuffer(gb);
832 *gb->pt++ = oper; /* hintmask,cntrmask */
833 for ( i=0; i< ((cnt+7)>>3); ++i )
834 *gb->pt++ = mask[i];
837 static void CounterHints2(GrowBuf *gb, SplineChar *sc, int hcnt) {
838 int i;
840 for ( i=0; i<sc->countermask_cnt; ++i )
841 AddMask2(gb,sc->countermasks[i],hcnt,20); /* cntrmask */
844 static int HintSetup2(GrowBuf *gb,struct hintdb *hdb, SplinePoint *to, int break_subr ) {
846 /* We might get a point with a hintmask in a glyph with no conflicts */
847 /* (ie. the initial point when we return to it at the end of the splineset*/
848 /* in that case hdb->cnt will be 0 and we should ignore it */
849 /* components in subroutines depend on not having any hintmasks */
850 if ( to->hintmask==NULL || hdb->cnt==0 || hdb->noconflicts || hdb->skiphm )
851 return( false );
853 if ( memcmp(hdb->mask,*to->hintmask,(hdb->cnt+7)/8)==0 )
854 return( false );
856 if ( break_subr )
857 BreakSubroutine(gb,hdb);
859 AddMask2(gb,*to->hintmask,hdb->cnt,19); /* hintmask */
860 memcpy(hdb->mask,*to->hintmask,sizeof(HintMask));
861 hdb->donefirsthm = true;
862 if ( break_subr )
863 StartNextSubroutine(gb,hdb);
864 return( true );
867 static void moveto2(GrowBuf *gb,struct hintdb *hdb,SplinePoint *to, int round) {
868 BasePoint temp, *tom;
870 if ( gb->pt+18 >= gb->end )
871 GrowBuffer(gb);
873 BreakSubroutine(gb,hdb);
874 HintSetup2(gb,hdb,to,false);
875 tom = &to->me;
876 if ( round ) {
877 temp.x = rint(tom->x);
878 temp.y = rint(tom->y);
879 tom = &temp;
881 #if 0
882 if ( hdb->current.x==tom->x && hdb->current.y==tom->y ) {
883 /* we're already here */
884 /* Yes, but a move is required anyway at char start */
885 } else
886 #endif
887 if ( hdb->current.x==tom->x ) {
888 AddNumber2(gb,tom->y-hdb->current.y,round);
889 *(gb->pt)++ = 4; /* v move to */
890 } else if ( hdb->current.y==tom->y ) {
891 AddNumber2(gb,tom->x-hdb->current.x,round);
892 *(gb->pt)++ = 22; /* h move to */
893 } else {
894 AddNumber2(gb,tom->x-hdb->current.x,round);
895 AddNumber2(gb,tom->y-hdb->current.y,round);
896 *(gb->pt)++ = 21; /* r move to */
898 hdb->current.x = rint(32768*tom->x)/32768;
899 hdb->current.y = rint(32768*tom->y)/32768;
900 StartNextSubroutine(gb,hdb);
903 static Spline *lineto2(GrowBuf *gb,struct hintdb *hdb,Spline *spline, Spline *done, int round) {
904 int cnt, hv, hvcnt;
905 Spline *test, *lastgood, *lasthvgood;
906 BasePoint temp1, temp2, *tom, *fromm;
907 int donehm;
909 lastgood = NULL;
910 for ( test=spline, cnt=0; test->knownlinear && cnt<15; ) {
911 ++cnt;
912 lastgood = test;
913 test = test->to->next;
914 /* it will be smaller to use a closepath operator so ignore the */
915 /* ultimate spline */
916 if ( test==done || test==NULL || test->to->next==done )
917 break;
920 HintSetup2(gb,hdb,spline->to,true);
922 hv = -1; hvcnt=1; lasthvgood = NULL;
923 if ( spline->from->me.x==spline->to->me.x )
924 hv = 1; /* Vertical */
925 else if ( spline->from->me.y==spline->to->me.y )
926 hv = 0; /* Horizontal */
927 donehm = true;
928 if ( hv!=-1 ) {
929 lasthvgood = spline; hvcnt = 1;
930 if ( cnt!=1 ) {
931 for ( test=spline->to->next; test!=NULL ; test = test->to->next ) {
932 fromm = &test->from->me;
933 if ( round ) {
934 temp2.x = rint(fromm->x);
935 temp2.y = rint(fromm->y);
936 fromm = &temp2;
938 tom = &test->to->me;
939 if ( round ) {
940 temp1.x = rint(tom->x);
941 temp1.y = rint(tom->y);
942 tom = &temp1;
944 if ( hv==1 && tom->y==fromm->y )
945 hv = 0;
946 else if ( hv==0 && tom->x==fromm->x )
947 hv = 1;
948 else
949 break;
950 lasthvgood = test;
951 ++hvcnt;
952 if ( test==lastgood )
953 break;
956 donehm = true;
957 if ( hvcnt==cnt || hvcnt>=2 ) {
958 /* It's more efficient to do some h/v linetos */
959 for ( test=spline; ; test = test->to->next ) {
960 if ( !donehm && test->to->hintmask!=NULL )
961 break;
962 donehm = false;
963 fromm = &test->from->me;
964 if ( round ) {
965 temp2.x = rint(fromm->x);
966 temp2.y = rint(fromm->y);
967 fromm = &temp2;
969 tom = &test->to->me;
970 if ( round ) {
971 temp1.x = rint(tom->x);
972 temp1.y = rint(tom->y);
973 tom = &temp1;
975 if ( fromm->x==tom->x )
976 AddNumber2(gb,tom->y-fromm->y,round);
977 else
978 AddNumber2(gb,tom->x-fromm->x,round);
979 hdb->current.x = rint(32768*tom->x)/32768;
980 hdb->current.y = rint(32768*tom->y)/32768;
981 if ( test==lasthvgood ) {
982 test = test->to->next;
983 break;
986 if ( gb->pt+1 >= gb->end )
987 GrowBuffer(gb);
988 *(gb->pt)++ = spline->from->me.x==spline->to->me.x? 7 : 6;
989 return( test );
993 for ( test=spline; test!=NULL; test = test->to->next ) {
994 if ( !donehm && test->to->hintmask!=NULL )
995 break;
996 donehm = false;
997 fromm = &test->from->me;
998 if ( round ) {
999 temp2.x = rint(fromm->x);
1000 temp2.y = rint(fromm->y);
1001 fromm = &temp2;
1003 tom = &test->to->me;
1004 if ( round ) {
1005 temp1.x = rint(tom->x);
1006 temp1.y = rint(tom->y);
1007 tom = &temp1;
1009 AddNumber2(gb,tom->x-fromm->x,round);
1010 AddNumber2(gb,tom->y-fromm->y,round);
1011 hdb->current.x = rint(32768*tom->x)/32768;
1012 hdb->current.y = rint(32768*tom->y)/32768;
1013 if ( test==lastgood ) {
1014 test = test->to->next;
1015 break;
1018 if ( gb->pt+1 >= gb->end )
1019 GrowBuffer(gb);
1020 *(gb->pt)++ = 5; /* r line to */
1021 return( test );
1024 static Spline *curveto2(GrowBuf *gb,struct hintdb *hdb,Spline *spline, Spline *done, int round) {
1025 int cnt=0, hv;
1026 Spline *first;
1027 DBasePoint start;
1028 int donehm;
1030 HintSetup2(gb,hdb,spline->to,true);
1032 hv = -1;
1033 if ( hdb->current.x==myround2(spline->from->nextcp.x,round) &&
1034 myround2(spline->to->prevcp.y,round)==myround2(spline->to->me.y,round) )
1035 hv = 1;
1036 else if ( hdb->current.y==myround2(spline->from->nextcp.y,round) &&
1037 myround2(spline->to->prevcp.x,round)==myround2(spline->to->me.x,round) )
1038 hv = 0;
1039 donehm = true;
1040 if ( hv!=-1 ) {
1041 first = spline; start = hdb->current;
1042 while (
1043 (hv==1 && hdb->current.x==myround2(spline->from->nextcp.x,round) &&
1044 myround2(spline->to->prevcp.y,round)==myround2(spline->to->me.y,round) ) ||
1045 (hv==0 && hdb->current.y==myround2(spline->from->nextcp.y,round) &&
1046 myround2(spline->to->prevcp.x,round)==myround2(spline->to->me.x,round) ) ) {
1047 if ( !donehm && spline->to->hintmask!=NULL )
1048 break;
1049 donehm = false;
1050 if ( hv==1 ) {
1051 AddNumber2(gb,myround2(spline->from->nextcp.y,round)-hdb->current.y,round);
1052 AddNumber2(gb,myround2(spline->to->prevcp.x,round)-myround2(spline->from->nextcp.x,round),round);
1053 AddNumber2(gb,myround2(spline->to->prevcp.y,round)-myround2(spline->from->nextcp.y,round),round);
1054 AddNumber2(gb,myround2(spline->to->me.x,round)-myround2(spline->to->prevcp.x,round),round);
1055 hv = 0;
1056 } else {
1057 AddNumber2(gb,myround2(spline->from->nextcp.x,round)-hdb->current.x,round);
1058 AddNumber2(gb,myround2(spline->to->prevcp.x,round)-myround2(spline->from->nextcp.x,round),round);
1059 AddNumber2(gb,myround2(spline->to->prevcp.y,round)-myround2(spline->from->nextcp.y,round),round);
1060 AddNumber2(gb,myround2(spline->to->me.y,round)-myround2(spline->to->prevcp.y,round),round);
1061 hv = 1;
1063 hdb->current.x = myround2(spline->to->me.x,round);
1064 hdb->current.y = myround2(spline->to->me.y,round);
1065 ++cnt;
1066 spline = spline->to->next;
1067 if ( spline==done || spline==NULL || cnt>9 || spline->knownlinear )
1068 break;
1070 if ( gb->pt+1 >= gb->end )
1071 GrowBuffer(gb);
1072 *(gb->pt)++ = ( start.x==myround2(first->from->nextcp.x,round) && myround2(first->to->prevcp.y,round)==myround2(first->to->me.y,round) )?
1073 30:31; /* vhcurveto:hvcurveto */
1074 return( spline );
1076 while ( cnt<6 ) {
1077 if ( !donehm && spline->to->hintmask!=NULL )
1078 break;
1079 donehm = false;
1080 hv = -1;
1081 if ( hdb->current.x==myround2(spline->from->nextcp.x,round) &&
1082 myround2(spline->to->prevcp.y,round)==myround2(spline->to->me.y,round) &&
1083 spline->to->next!=NULL &&
1084 myround2(spline->to->me.y,round)==myround2(spline->to->nextcp.y,round) &&
1085 myround2(spline->to->next->to->prevcp.x,round)==myround2(spline->to->next->to->me.x,round) )
1086 break;
1087 else if ( hdb->current.y==myround2(spline->from->nextcp.y,round) &&
1088 myround2(spline->to->prevcp.x,round)==myround2(spline->to->me.x,round) &&
1089 spline->to->next!=NULL &&
1090 myround2(spline->to->me.x,round)==myround2(spline->to->nextcp.x,round) &&
1091 myround2(spline->to->next->to->prevcp.y,round)==myround2(spline->to->next->to->me.y,round) )
1092 break;
1093 AddNumber2(gb,myround2(spline->from->nextcp.x,round)-hdb->current.x,round);
1094 AddNumber2(gb,myround2(spline->from->nextcp.y,round)-hdb->current.y,round);
1095 AddNumber2(gb,myround2(spline->to->prevcp.x,round)-myround2(spline->from->nextcp.x,round),round);
1096 AddNumber2(gb,myround2(spline->to->prevcp.y,round)-myround2(spline->from->nextcp.y,round),round);
1097 AddNumber2(gb,myround2(spline->to->me.x,round)-myround2(spline->to->prevcp.x,round),round);
1098 AddNumber2(gb,myround2(spline->to->me.y,round)-myround2(spline->to->prevcp.y,round),round);
1099 hdb->current.x = myround2(spline->to->me.x,round);
1100 hdb->current.y = myround2(spline->to->me.y,round);
1101 ++cnt;
1102 spline = spline->to->next;
1103 if ( spline==done || spline==NULL || spline->knownlinear )
1104 break;
1106 if ( gb->pt+1 >= gb->end )
1107 GrowBuffer(gb);
1108 *(gb->pt)++ = 8; /* rrcurveto */
1109 return( spline );
1112 static void flexto2(GrowBuf *gb,struct hintdb *hdb,Spline *pspline,int round) {
1113 BasePoint *c0, *c1, *mid, *end, *nc0, *nc1;
1114 Spline *nspline;
1116 c0 = &pspline->from->nextcp;
1117 c1 = &pspline->to->prevcp;
1118 mid = &pspline->to->me;
1119 nspline = pspline->to->next;
1120 nc0 = &nspline->from->nextcp;
1121 nc1 = &nspline->to->prevcp;
1122 end = &nspline->to->me;
1124 HintSetup2(gb,hdb,nspline->to,true);
1126 if ( myround2(c0->y,round)==hdb->current.y && myround2(nc1->y,round)==hdb->current.y &&
1127 myround2(end->y,round)==hdb->current.y &&
1128 myround2(c1->y,round)==myround2(mid->y,round) && myround2(nc0->y,round)==myround2(mid->y,round) ) {
1129 if ( gb->pt+7*6+2 >= gb->end )
1130 GrowBuffer(gb);
1131 AddNumber2(gb,myround2(c0->x,round)-hdb->current.x,round);
1132 AddNumber2(gb,myround2(c1->x,round)-myround2(c0->x,round),round);
1133 AddNumber2(gb,myround2(c1->y,round)-myround2(c0->y,round),round);
1134 AddNumber2(gb,myround2(mid->x,round)-myround2(c1->x,round),round);
1135 AddNumber2(gb,myround2(nc0->x,round)-myround2(mid->x,round),round);
1136 AddNumber2(gb,myround2(nc1->x,round)-myround2(nc0->x,round),round);
1137 AddNumber2(gb,myround2(end->x,round)-myround2(nc1->x,round),round);
1138 *gb->pt++ = 12; *gb->pt++ = 34; /* hflex */
1139 } else {
1140 if ( gb->pt+11*6+2 >= gb->end )
1141 GrowBuffer(gb);
1142 AddNumber2(gb,myround2(c0->x,round)-hdb->current.x,round);
1143 AddNumber2(gb,myround2(c0->y,round)-hdb->current.y,round);
1144 AddNumber2(gb,myround2(c1->x,round)-myround2(c0->x,round),round);
1145 AddNumber2(gb,myround2(c1->y,round)-myround2(c0->y,round),round);
1146 AddNumber2(gb,myround2(mid->x,round)-myround2(c1->x,round),round);
1147 AddNumber2(gb,myround2(mid->y,round)-myround2(c1->y,round),round);
1148 AddNumber2(gb,myround2(nc0->x,round)-myround2(mid->x,round),round);
1149 AddNumber2(gb,myround2(nc0->y,round)-myround2(mid->y,round),round);
1150 AddNumber2(gb,myround2(nc1->x,round)-myround2(nc0->x,round),round);
1151 AddNumber2(gb,myround2(nc1->y,round)-myround2(nc0->y,round),round);
1152 if ( hdb->current.y==myround2(end->y,round) )
1153 AddNumber2(gb,myround2(end->x,round)-myround2(nc1->x,round),round);
1154 else
1155 AddNumber2(gb,myround2(end->y,round)-myround2(nc1->y,round),round);
1156 *gb->pt++ = 12; *gb->pt++ = 37; /* flex1 */
1159 hdb->current.x = rint(32768*end->x)/32768;
1160 hdb->current.y = rint(32768*end->y)/32768;
1163 static void CvtPsSplineSet2(GrowBuf *gb, SplinePointList *spl,
1164 struct hintdb *hdb, int is_order2,int round ) {
1165 Spline *spline, *first;
1166 SplinePointList temp, *freeme = NULL;
1167 int unhinted = true;;
1169 if ( is_order2 )
1170 freeme = spl = SplineSetsPSApprox(spl);
1172 for ( ; spl!=NULL; spl = spl->next ) {
1173 first = NULL;
1174 SplineSetReverse(spl);
1175 /* PostScript and TrueType store their splines in in reverse */
1176 /* orientations. Annoying. Oh well. I shall adopt TrueType and */
1177 /* If I reverse the PS splinesets after reading them in, and then */
1178 /* again when saving them out, all should be well */
1179 if ( spl->first->flexy || spl->first->flexx ) {
1180 /* can't handle a flex (mid) point as the first point. rotate the */
1181 /* list by one, this is possible because only closed paths have */
1182 /* points marked as flex, and because we can't have two flex mid- */
1183 /* points in a row */
1184 if ( spl->first->hintmask==NULL || spl->first->next->to->hintmask!=NULL ) {
1185 /* But we can't rotate it if we expect it to provide us with */
1186 /* a hintmask. */
1187 temp = *spl;
1188 temp.first = temp.last = spl->first->next->to;
1189 spl = &temp;
1191 if ( spl->first->flexy || spl->first->flexx ) {
1192 /* If we couldn't rotate, or if we rotated to something that */
1193 /* also is flexible, then just turn off flex. That's safe */
1194 spl->first->flexx = spl->first->flexy = false;
1197 if ( unhinted && hdb->cnt>0 && spl->first->hintmask!=NULL ) {
1198 hdb->mask[0] = ~(*spl->first->hintmask)[0]; /* Make it different */
1199 unhinted = false;
1201 moveto2(gb,hdb,spl->first,round);
1202 for ( spline = spl->first->next; spline!=NULL && spline!=first; ) {
1203 if ( first==NULL ) first = spline;
1204 else if ( first->from==spline->to )
1205 hdb->skiphm = true;
1206 if ( spline->to->flexx || spline->to->flexy ) {
1207 flexto2(gb,hdb,spline,round); /* does two adjacent splines */
1208 spline = spline->to->next->to->next;
1209 } else if ( spline->knownlinear && spline->to == spl->first )
1210 /* In Type2 we don't even need a closepath to finish this off */
1211 /* (which is good, because there isn't a close path) */
1212 break;
1213 else if ( spline->knownlinear )
1214 spline = lineto2(gb,hdb,spline,first,round);
1215 else
1216 spline = curveto2(gb,hdb,spline,first,round);
1218 hdb->skiphm = false;
1219 /* No closepath oper in type2 fonts, it's implied */
1220 SplineSetReverse(spl);
1221 /* Of course, I have to Reverse again to get back to my convention after*/
1222 /* saving */
1224 SplinePointListsFree(freeme);
1227 static void DumpHints(GrowBuf *gb,StemInfo *h,int oper,int midoper,int round) {
1228 real last = 0, cur;
1229 int cnt;
1231 if ( h==NULL )
1232 return;
1233 cnt = 0;
1234 while ( h!=NULL && h->hintnumber!=-1 ) {
1235 /* Type2 hints do not support negative widths except in the case of */
1236 /* ghost (now called edge) hints */
1237 if ( cnt>24-1 ) { /* stack max = 48 numbers, => 24 hints, leave a bit of slop for the width */
1238 if ( gb->pt+1>=gb->end )
1239 GrowBuffer(gb);
1240 *gb->pt++ = midoper;
1241 cnt = 0;
1243 cur = myround2(h->start,round) + myround2(h->width,round);
1244 if ( h->width<0 ) {
1245 AddNumber2(gb,cur-last,round);
1246 AddNumber2(gb,-myround2(h->width,round),round);
1247 cur -= myround2(h->width,round);
1248 } else if ( h->ghost ) {
1249 if ( h->width==20 ) {
1250 AddNumber2(gb,myround2(h->start,round)-last+20,round);
1251 AddNumber2(gb,-20,round);
1252 cur = myround2(h->start,round);
1253 } else {
1254 AddNumber2(gb,myround2(h->start+21,round)-last,round);
1255 AddNumber2(gb,-21,round);
1256 cur = myround2(h->start+21,round)-21;
1258 } else {
1259 AddNumber2(gb,myround2(h->start,round)-last,round);
1260 AddNumber2(gb,myround2(h->width,round),round);
1262 last = cur;
1263 h = h->next;
1264 ++cnt;
1266 if ( oper!=-1 ) {
1267 if ( gb->pt+1>=gb->end )
1268 GrowBuffer(gb);
1269 *gb->pt++ = oper;
1273 static void DumpRefsHints(GrowBuf *gb, struct hintdb *hdb,RefChar *cur,StemInfo *h,StemInfo *v,
1274 BasePoint *trans, int round,int layer) {
1275 uint8 masks[12];
1276 int cnt, sets=0;
1277 StemInfo *rs;
1279 /* trans has already been rounded (whole char is translated by an integral amount) */
1281 /* If we have a subroutine containing conflicts, then its hints will match*/
1282 /* ours exactly, and we can use its hintmasks directly */
1283 if (( cur->sc->hconflicts || cur->sc->vconflicts ) &&
1284 cur->sc->layers[layer].splines!=NULL &&
1285 cur->sc->layers[layer].splines->first->hintmask!=NULL ) {
1286 AddMask2(gb,*cur->sc->layers[layer].splines->first->hintmask,hdb->cnt,19); /* hintmask */
1287 hdb->donefirsthm = true;
1288 memcpy(hdb->mask,*cur->sc->layers[layer].splines->first->hintmask,sizeof(HintMask));
1289 return;
1292 if ( h==NULL && v==NULL )
1293 IError("hintmask invoked when there are no hints");
1294 memset(masks,'\0',sizeof(masks));
1295 cnt = 0;
1296 while ( h!=NULL && h->hintnumber>=0 ) {
1297 /* Horizontal stems are defined by vertical bounds */
1298 real pos = (round ? rint(h->start) : h->start) - trans->y;
1299 for ( rs = cur->sc->hstem; rs!=NULL; rs=rs->next ) {
1300 real rpos = round ? rint(rs->start) : rs->start;
1301 if ( rpos==pos && (round ? (rint(rs->width)==rint(h->width)) : (rs->width==h->width)) ) {
1302 masks[h->hintnumber>>3] |= 0x80>>(h->hintnumber&7);
1303 ++sets;
1304 break;
1305 } else if ( rpos>pos )
1306 break;
1308 h = h->next; ++cnt;
1310 while ( v!=NULL && v->hintnumber>=0 ) {
1311 real pos = (round ? rint(v->start) : v->start) - trans->x;
1312 for ( rs = cur->sc->vstem; rs!=NULL; rs=rs->next ) {
1313 real rpos = round ? rint(rs->start) : rs->start;
1314 if ( rpos==pos && (round ? (rint(rs->width)==rint(v->width)) : (rs->width==v->width)) ) {
1315 masks[v->hintnumber>>3] |= 0x80>>(v->hintnumber&7);
1316 ++sets;
1317 break;
1318 } else if ( rpos>pos )
1319 break;
1321 v = v->next; ++cnt;
1323 BreakSubroutine(gb,hdb);
1324 hdb->donefirsthm = true;
1325 /* if ( sets!=0 ) */ /* First ref will need a hintmask even if it has no hints (if there are conflicts) */
1326 AddMask2(gb,masks,cnt,19); /* hintmask */
1329 static void DummyHintmask(GrowBuf *gb,struct hintdb *hdb) {
1330 HintMask hm;
1332 memset(hm,0,sizeof(hm));
1333 if ( hdb->cnt!=0 ) {
1334 BreakSubroutine(gb,hdb);
1335 hdb->donefirsthm = true;
1336 AddMask2(gb,hm,hdb->cnt,19); /* hintmask */
1340 static void SetTransformedHintMask(GrowBuf *gb,struct hintdb *hdb,
1341 SplineChar *sc, RefChar *ref, BasePoint *trans, int round) {
1342 HintMask hm;
1344 if ( HintMaskFromTransformedRef(ref,trans,sc,&hm)!=NULL ) {
1345 BreakSubroutine(gb,hdb);
1346 hdb->donefirsthm = true;
1347 AddMask2(gb,hm,hdb->cnt,19); /* hintmask */
1348 } else if ( !hdb->donefirsthm )
1349 DummyHintmask(gb,hdb);
1352 static void ExpandRef2(GrowBuf *gb, SplineChar *sc, struct hintdb *hdb,
1353 RefChar *r, BasePoint *trans,
1354 struct pschars *subrs, int round,int layer) {
1355 BasePoint *bpt;
1356 BasePoint temp, rtrans;
1357 GlyphInfo *gi;
1358 /* The only refs I deal with here have no hint conflicts within them */
1360 rtrans.x = r->transform[4]+trans->x;
1361 rtrans.y = r->transform[5]+trans->y;
1362 if ( round ) {
1363 rtrans.x = rint(rtrans.x);
1364 rtrans.y = rint(rtrans.y);
1367 BreakSubroutine(gb,hdb);
1368 if ( hdb->cnt>0 && !hdb->noconflicts )
1369 DumpRefsHints(gb,hdb,r,sc->hstem,sc->vstem,&rtrans,round,layer);
1371 /* Translate from end of last character to where this one should */
1372 /* start (we must have one moveto operator to start off, none */
1373 /* in the subr) */
1374 bpt = hdb->gi->psubrs[r->sc->lsidebearing].startstop;
1375 temp.x = bpt[0].x+rtrans.x;
1376 temp.y = bpt[0].y+rtrans.y;
1377 if ( hdb->current.x!=temp.x )
1378 AddNumber2(gb,temp.x-hdb->current.x,round);
1379 if ( hdb->current.y!=temp.y || hdb->current.x==temp.x )
1380 AddNumber2(gb,temp.y-hdb->current.y,round);
1381 if ( gb->pt+1>=gb->end )
1382 GrowBuffer(gb);
1383 *gb->pt++ = hdb->current.x==temp.x?4: /* vmoveto */
1384 hdb->current.y==temp.y?22: /* hmoveto */
1385 21; /* rmoveto */
1386 if ( r->sc->lsidebearing==0x7fff )
1387 IError("Attempt to reference an unreferenceable glyph %s", r->sc->name );
1389 gi = hdb->gi;
1390 StartNextSubroutine(gb,hdb);
1391 gi->bits[gi->bcnt].psub_index = r->sc->lsidebearing;
1392 ++gi->bcnt;
1393 gi->justbroken = true;
1394 hdb->current.x = bpt[1].x+rtrans.x;
1395 hdb->current.y = bpt[1].y+rtrans.y;
1398 static void RSC2PS2(GrowBuf *gb, SplineChar *base,SplineChar *rsc,
1399 struct hintdb *hdb, BasePoint *trans, struct pschars *subrs,
1400 int flags, int layer ) {
1401 BasePoint subtrans;
1402 int stationary = trans->x==0 && trans->y==0;
1403 RefChar *r, *unsafe=NULL;
1404 int unsafecnt=0, allwithouthints=true;
1405 int round = (flags&ps_flag_round)? true : false;
1406 StemInfo *oldh = NULL, *oldv = NULL;
1407 int hc = 0, vc = 0;
1408 SplineSet *freeme, *temp;
1409 int wasntconflicted = hdb->noconflicts;
1411 if ( flags&ps_flag_nohints ) {
1412 oldh = rsc->hstem; oldv = rsc->vstem;
1413 hc = rsc->hconflicts; vc = rsc->vconflicts;
1414 rsc->hstem = NULL; rsc->vstem = NULL;
1415 rsc->hconflicts = false; rsc->vconflicts = false;
1416 } else {
1417 for ( r=rsc->layers[layer].refs; r!=NULL; r=r->next ) {
1418 if ( !r->justtranslated )
1419 continue;
1420 if ( r->sc->hconflicts || r->sc->vconflicts ) {
1421 ++unsafecnt;
1422 unsafe = r;
1423 } else if ( r->sc->hstem!=NULL || r->sc->vstem!=NULL )
1424 allwithouthints = false;
1426 if ( !stationary )
1427 allwithouthints = false;
1428 if ( allwithouthints && unsafe!=NULL && hdb->cnt!=NumberHints(&unsafe->sc,1))
1429 allwithouthints = false; /* There are other hints elsewhere in the base glyph */
1432 if ( unsafe && allwithouthints ) {
1433 if ( unsafe->sc->lsidebearing!=0x7fff ) {
1434 ExpandRef2(gb,base,hdb,unsafe,trans,subrs,round,layer);
1435 } else if ( unsafe->transform[4]==0 && unsafe->transform[5]==0 )
1436 RSC2PS2(gb,base,unsafe->sc,hdb,trans,subrs,flags,layer);
1437 else
1438 unsafe = NULL;
1439 } else
1440 unsafe = NULL;
1442 /* What is the hintmask state here? It should not matter */
1443 freeme = NULL; temp = rsc->layers[layer].splines;
1444 if ( base!=rsc )
1445 temp = freeme = SPLCopyTranslatedHintMasks(temp,base,rsc,trans);
1446 CvtPsSplineSet2(gb,temp,hdb,rsc->layers[layer].order2,round);
1447 SplinePointListsFree(freeme);
1449 for ( r = rsc->layers[layer].refs; r!=NULL; r = r->next ) if ( r!=unsafe ) {
1450 if ( !r->justtranslated ) {
1451 if ( !r->sc->hconflicts && !r->sc->vconflicts && !hdb->noconflicts &&
1452 r->transform[1]==0 && r->transform[2]==0 &&
1453 r->transform[0]>0 && r->transform[3]>0 )
1454 SetTransformedHintMask(gb,hdb,base,r,trans,round);
1455 if ( !hdb->donefirsthm )
1456 DummyHintmask(gb,hdb);
1457 temp = SPLCopyTransformedHintMasks(r,base,trans,layer);
1458 CvtPsSplineSet2(gb,temp,hdb,rsc->layers[layer].order2,round);
1459 SplinePointListsFree(temp);
1460 } else if ( r->sc->lsidebearing!=0x7fff &&
1461 ((flags&ps_flag_nohints) ||
1462 (!r->sc->hconflicts && !r->sc->vconflicts)) ) {
1463 ExpandRef2(gb,base,hdb,r,trans,subrs,round,layer);
1464 } else {
1465 subtrans.x = trans->x + r->transform[4];
1466 subtrans.y = trans->y + r->transform[5];
1467 if ( !hdb->noconflicts && !r->sc->hconflicts && !r->sc->vconflicts) {
1468 SetTransformedHintMask(gb,hdb,base,r,trans,round);
1469 hdb->noconflicts = true;
1471 RSC2PS2(gb,base,r->sc,hdb,&subtrans,subrs,flags,layer);
1472 hdb->noconflicts = wasntconflicted;
1476 if ( flags&ps_flag_nohints ) {
1477 rsc->hstem = oldh; rsc->vstem = oldv;
1478 rsc->hconflicts = hc; rsc->vconflicts = vc;
1482 static unsigned char *SplineChar2PS2(SplineChar *sc,int *len, int nomwid,
1483 int defwid, struct pschars *subrs, int flags,
1484 GlyphInfo *gi) {
1485 GrowBuf gb;
1486 unsigned char *ret;
1487 struct hintdb hdb;
1488 StemInfo *oldh = NULL, *oldv = NULL;
1489 int hc = 0, vc = 0;
1490 SplineChar *scs[MmMax];
1491 int round = (flags&ps_flag_round)? true : false;
1492 HintMask *hm = NULL;
1493 BasePoint trans;
1495 if ( !(flags&ps_flag_nohints) && SCNeedsSubsPts(sc,ff_otf,gi->layer))
1496 SCFigureHintMasks(sc,gi->layer);
1498 if ( flags&ps_flag_nohints ) {
1499 oldh = sc->hstem; oldv = sc->vstem;
1500 hc = sc->hconflicts; vc = sc->vconflicts;
1501 sc->hstem = NULL; sc->vstem = NULL;
1502 sc->hconflicts = false; sc->vconflicts = false;
1503 } else if ( sc->layers[gi->layer].splines!=NULL && !sc->vconflicts &&
1504 !sc->hconflicts ) {
1505 hm = sc->layers[gi->layer].splines->first->hintmask;
1506 sc->layers[gi->layer].splines->first->hintmask = NULL;
1509 memset(&gb,'\0',sizeof(gb));
1511 GrowBuffer(&gb);
1513 /* store the width on the stack */
1514 if ( sc->width==defwid )
1515 /* Don't need to do anything for the width */;
1516 else
1517 AddNumber2(&gb,sc->width-nomwid,round);
1519 memset(&trans,'\0',sizeof(trans));
1520 memset(&hdb,'\0',sizeof(hdb));
1521 hdb.scs = scs;
1522 hdb.gi = gi;
1523 if ( gi!=NULL )
1524 gi->bcnt = -1;
1525 scs[0] = sc;
1526 hdb.noconflicts = !sc->hconflicts && !sc->vconflicts;
1527 hdb.cnt = NumberHints(hdb.scs,1);
1528 DumpHints(&gb,sc->hstem,sc->hconflicts || sc->vconflicts?18:1,
1529 sc->hconflicts || sc->vconflicts?18:1,round);
1530 DumpHints(&gb,sc->vstem,sc->hconflicts || sc->vconflicts?-1:3,
1531 sc->hconflicts || sc->vconflicts?23:3,round);
1532 CounterHints2(&gb, sc, hdb.cnt );
1533 RSC2PS2(&gb,sc,sc,&hdb,&trans,subrs,flags,gi->layer);
1535 if ( gi->bcnt==-1 ) { /* If it's whitespace */
1536 gi->bcnt = 0;
1537 StartNextSubroutine(&gb,&hdb);
1539 BreakSubroutine(&gb,&hdb);
1540 MoveSubrsToChar(gi);
1541 ret = NULL;
1543 free(gb.base);
1544 if ( flags&ps_flag_nohints ) {
1545 sc->hstem = oldh; sc->vstem = oldv;
1546 sc->hconflicts = hc; sc->vconflicts = vc;
1547 } else if ( hm!=NULL )
1548 sc->layers[gi->layer].splines->first->hintmask = hm;
1549 return( ret );
1552 static SplinePoint *FFLineTo(SplinePoint *last, int x, int y) {
1553 SplinePoint *sp = SplinePointCreate(x,y);
1554 SplineMake3(last,sp);
1555 return( sp );
1558 static void Type2NotDefSplines(SplineFont *sf,SplineChar *sc,int layer) {
1559 /* I'd always assumed that Type2 notdefs would look like type1 notdefs */
1560 /* but they don't, they look like truetype notdefs. And Ralf Stubner */
1561 /* points out that the spec says they should. So make a box here */
1562 int stem, ymax;
1563 SplineSet *inner, *ss;
1564 StemInfo *h, *hints;
1566 stem = (sf->ascent+sf->descent)/20;
1567 ymax = 2*sf->ascent/3;
1569 ss = chunkalloc(sizeof(SplineSet));
1570 ss->first = ss->last = SplinePointCreate(stem,0);
1571 ss->last = FFLineTo(ss->last,stem,ymax);
1572 ss->last = FFLineTo(ss->last,sc->width-stem,ymax);
1573 ss->last = FFLineTo(ss->last,sc->width-stem,0);
1574 SplineMake3(ss->last,ss->first);
1575 ss->last = ss->first;
1577 ss->next = inner = chunkalloc(sizeof(SplineSet));
1578 inner->first = inner->last = SplinePointCreate(2*stem,stem);
1579 inner->last = FFLineTo(inner->last,sc->width-2*stem,stem);
1580 inner->last = FFLineTo(inner->last,sc->width-2*stem,ymax-stem);
1581 inner->last = FFLineTo(inner->last,2*stem,ymax-stem);
1582 SplineMake3(inner->last,inner->first);
1583 inner->last = inner->first;
1585 sc->layers[layer].splines = ss;
1587 hints = chunkalloc(sizeof(StemInfo));
1588 hints->start = stem;
1589 hints->width = stem;
1590 hints->next = h = chunkalloc(sizeof(StemInfo));
1591 h->start = sc->width-2*stem;
1592 h->width = stem;
1593 sc->vstem = hints;
1595 hints = chunkalloc(sizeof(StemInfo));
1596 hints->start = 0;
1597 hints->width = stem;
1598 hints->next = h = chunkalloc(sizeof(StemInfo));
1599 h->start = ymax-stem;
1600 h->width = stem;
1601 sc->hstem = hints;
1604 /* Mark those glyphs which can live totally in subrs */
1605 static void SplineFont2FullSubrs2(int flags,GlyphInfo *gi) {
1606 int i;
1607 SplineChar *sc;
1609 for ( i=0; i<gi->glyphcnt; ++i ) if ( (sc=gi->gb[i].sc)!=NULL )
1610 sc->lsidebearing = 0x7fff;
1614 struct pschars *SplineFont2ChrsSubrs2(SplineFont *sf, int nomwid, int defwid,
1615 const int *bygid, int cnt, int flags, struct pschars **_subrs, int layer) {
1616 struct pschars *subrs, *chrs;
1617 int i,j,k,scnt;
1618 SplineChar *sc;
1619 GlyphInfo gi;
1620 SplineChar dummynotdef;
1622 memset(&gi,0,sizeof(gi));
1623 memset(&gi.hashed,-1,sizeof(gi.hashed));
1624 gi.instance_count = 1;
1625 gi.sf = sf;
1626 gi.layer = layer;
1627 gi.glyphcnt = cnt;
1628 gi.bygid = bygid;
1629 gi.gb = gcalloc(cnt,sizeof(struct glyphbits));
1630 gi.pmax = 3*cnt;
1631 gi.psubrs = galloc(gi.pmax*sizeof(struct potentialsubrs));
1632 for ( i=0; i<cnt; ++i ) {
1633 int gid = bygid[i];
1634 if ( i==0 && gid==-1 ) {
1635 sc = &dummynotdef;
1636 memset(sc,0,sizeof(dummynotdef));
1637 dummynotdef.name = ".notdef";
1638 dummynotdef.parent = sf;
1639 dummynotdef.layer_cnt = sf->layer_cnt;
1640 dummynotdef.layers = gcalloc(sf->layer_cnt,sizeof(Layer));
1641 dummynotdef.width = SFOneWidth(sf);
1642 if ( dummynotdef.width==-1 )
1643 dummynotdef.width = (sf->ascent+sf->descent)/2;
1644 Type2NotDefSplines(sf,&dummynotdef,layer);
1645 } else if ( gid!=-1 )
1646 sc = sf->glyphs[gid];
1647 else
1648 continue;
1649 gi.gb[i].sc = sc;
1650 sc->lsidebearing = 0x7fff;
1652 MarkTranslationRefs(sf,layer);
1653 SplineFont2FullSubrs2(flags,&gi);
1655 for ( i=0; i<cnt; ++i ) {
1656 if ( (sc = gi.gb[i].sc)==NULL )
1657 continue;
1658 gi.active = &gi.gb[i];
1659 SplineChar2PS2(sc,NULL,nomwid,defwid,NULL,flags,&gi);
1660 ff_progress_next();
1663 for ( i=scnt=0; i<gi.pcnt; ++i ) {
1664 /* A subroutine call takes somewhere between 2 and 4 bytes itself. */
1665 /* and we must add a return statement to the end. We don't want to */
1666 /* make things bigger */
1667 /* if we have more than 65535 subrs a subr call can take 9 bytes */
1668 if ( gi.psubrs[i].full_glyph_index!=-1 )
1669 gi.psubrs[i].idx = scnt++;
1670 else if ( gi.psubrs[i].cnt*gi.psubrs[i].len>(gi.psubrs[i].cnt*4)+gi.psubrs[i].len+1 )
1671 gi.psubrs[i].idx = scnt++;
1672 else
1673 gi.psubrs[i].idx = -1;
1675 subrs = gcalloc(1,sizeof(struct pschars));
1676 subrs->cnt = scnt;
1677 subrs->next = scnt;
1678 subrs->lens = galloc(scnt*sizeof(int));
1679 subrs->values = galloc(scnt*sizeof(unsigned char *));
1680 subrs->bias = scnt<1240 ? 107 :
1681 scnt<33900 ? 1131 : 32768;
1682 for ( i=0; i<gi.pcnt; ++i ) {
1683 if ( gi.psubrs[i].idx != -1 ) {
1684 scnt = gi.psubrs[i].idx;
1685 subrs->lens[scnt] = gi.psubrs[i].len+1;
1686 subrs->values[scnt] = galloc(subrs->lens[scnt]);
1687 memcpy(subrs->values[scnt],gi.psubrs[i].data,gi.psubrs[i].len);
1688 subrs->values[scnt][gi.psubrs[i].len] = 11; /* Add a return to end of subr */
1692 chrs = gcalloc(1,sizeof(struct pschars));
1693 chrs->cnt = cnt;
1694 chrs->next = cnt;
1695 chrs->lens = galloc(cnt*sizeof(int));
1696 chrs->values = galloc(cnt*sizeof(unsigned char *));
1697 chrs->keys = galloc(cnt*sizeof(char *));
1698 for ( i=0; i<cnt; ++i ) {
1699 int len=0;
1700 uint8 *vals;
1701 struct glyphbits *gb = &gi.gb[i];
1702 if ( gb->sc==NULL )
1703 continue;
1704 chrs->keys[i] = copy(gb->sc->name);
1705 for ( k=0; k<2; ++k ) if ( k!=0 || gb->sc->lsidebearing!=0x7fff ) {
1706 for ( j=0; j<gb->bcnt; ++j ) {
1707 if ( k!=0 || j!=0 )
1708 len += gb->bits[j].dlen;
1709 if ( k==1 && gb->sc->lsidebearing!=0x7fff ) {
1710 int si = gi.psubrs[ gb->sc->lsidebearing ].idx;
1711 len += 1 + (si<=107 && si>=-107?1:si<=1131 && si>=-1131?2:si>=-32768 && si<32767?3:8);
1712 break;
1714 if ( gi.psubrs[ gb->bits[j].psub_index ].idx==-1 )
1715 len += gi.psubrs[ gb->bits[j].psub_index ].len;
1716 else {
1717 int si = gi.psubrs[ gb->bits[j].psub_index ].idx - subrs->bias;
1718 /* space for the number (subroutine index) */
1719 if ( si>=-107 && si<=107 )
1720 ++len;
1721 else if ( si>=-1131 && si<=1131 )
1722 len += 2;
1723 else if ( si>=-32768 && si<=32767 )
1724 len += 3;
1725 else
1726 len += 8;
1727 /* space for the subroutine operator */
1728 ++len;
1731 if ( k==0 ) {
1732 int si = gi.psubrs[ gb->sc->lsidebearing ].idx;
1733 subrs->lens[si] = len+1;
1734 vals = subrs->values[si] = galloc(len+2);
1735 } else {
1736 chrs->lens[i] = len+1;
1737 vals = chrs->values[i] = galloc(len+2); /* space for endchar and a final NUL (which is really meaningless, but makes me feel better) */
1740 len = 0;
1741 for ( j=0; j<gb->bcnt; ++j ) {
1742 int si;
1743 if ( k!=0 || j!=0 ) {
1744 memcpy(vals+len,gb->bits[j].data,gb->bits[j].dlen);
1745 len += gb->bits[j].dlen;
1747 si = 0x80000000;
1748 if ( k==1 && gb->sc->lsidebearing!=0x7fff )
1749 si = gi.psubrs[ gb->sc->lsidebearing ].idx - subrs->bias;
1750 else if ( gi.psubrs[ gb->bits[j].psub_index ].idx==-1 ) {
1751 memcpy(vals+len,gi.psubrs[ gb->bits[j].psub_index ].data,
1752 gi.psubrs[ gb->bits[j].psub_index ].len);
1753 len += gi.psubrs[ gb->bits[j].psub_index ].len;
1754 } else
1755 si = gi.psubrs[ gb->bits[j].psub_index ].idx - subrs->bias;
1756 if ( si!=0x80000000 ) {
1757 /* space for the number (subroutine index) */
1758 if ( si>=-107 && si<=107 )
1759 vals[len++] = si+139;
1760 else if ( si>0 && si<=1131 ) {
1761 si-=108;
1762 vals[len++] = (si>>8)+247;
1763 vals[len++] = si&0xff;
1764 } else if ( si>=-1131 && si<0 ) {
1765 si=(-si)-108;
1766 vals[len++] = (si>>8)+251;
1767 vals[len++] = si&0xff;
1768 } else if ( si>=-32768 && si<=32767 ) {
1769 vals[len++] = 28;
1770 vals[len++] = (si>>8)&0xff;
1771 vals[len++] = si&0xff;
1772 } else {
1773 /* store as fixed point, then multiply by 64. Takes 8 bytes */
1774 si *= (65536/64);
1775 vals[len++] = '\377';
1776 vals[len++] = (si>>24)&0xff;
1777 vals[len++] = (si>>16)&0xff;
1778 vals[len++] = (si>>8)&0xff;
1779 vals[len++] = si&0xff;
1780 vals[len++] = 64 + 139;
1781 vals[len++] = 0xc; vals[len++] = 0x18; /* Multiply */
1784 /* space for the subroutine operator */
1785 vals[len++] = 10;
1787 if ( k==1 && gb->sc->lsidebearing!=0x7fff )
1788 break;
1790 if ( k==0 ) {
1791 vals[len++] = 11; /* return */
1792 vals[len] = '\0';
1793 } else {
1794 vals[len++] = 14; /* endchar */
1795 vals[len] = '\0';
1800 GIFree(&gi,&dummynotdef);
1801 *_subrs = subrs;
1802 return( chrs );
1805 struct pschars *CID2ChrsSubrs2(SplineFont *cidmaster,struct fd2data *fds,
1806 int flags, struct pschars **_glbls, int layer) {
1807 struct pschars *chrs, *glbls;
1808 int i, j, cnt, cid, max, fd;
1809 int *scnts;
1810 SplineChar *sc;
1811 SplineFont *sf = NULL;
1812 /* In a cid-keyed font, cid 0 is defined to be .notdef so there are no */
1813 /* special worries. If it is defined we use it. If it is not defined */
1814 /* we add it. */
1815 GlyphInfo gi;
1816 SplineChar dummynotdef;
1818 max = 0;
1819 for ( i=0; i<cidmaster->subfontcnt; ++i ) {
1820 if ( max<cidmaster->subfonts[i]->glyphcnt )
1821 max = cidmaster->subfonts[i]->glyphcnt;
1822 MarkTranslationRefs(cidmaster->subfonts[i],layer);
1824 cnt = 1; /* for .notdef */
1825 for ( cid = 1; cid<max; ++cid ) {
1826 for ( i=0; i<cidmaster->subfontcnt; ++i ) {
1827 sf = cidmaster->subfonts[i];
1828 if ( cid<sf->glyphcnt && (sc=sf->glyphs[cid])!=NULL ) {
1829 sc->ttf_glyph = -1;
1830 sc->lsidebearing = 0x7fff;
1831 if ( SCWorthOutputting(sc))
1832 ++cnt;
1833 break;
1838 memset(&gi,0,sizeof(gi));
1839 memset(&gi.hashed,-1,sizeof(gi.hashed));
1840 gi.instance_count = 1;
1841 gi.sf = sf;
1842 gi.glyphcnt = cnt;
1843 gi.bygid = NULL;
1844 gi.gb = gcalloc(cnt,sizeof(struct glyphbits));
1845 gi.pmax = 3*cnt;
1846 gi.psubrs = galloc(gi.pmax*sizeof(struct potentialsubrs));
1847 gi.layer = layer;
1849 for ( cid = cnt = 0; cid<max; ++cid ) {
1850 sf = NULL;
1851 for ( i=0; i<cidmaster->subfontcnt; ++i ) {
1852 sf = cidmaster->subfonts[i];
1853 if ( cid<sf->glyphcnt && SCWorthOutputting(sf->glyphs[cid]) )
1854 break;
1856 if ( cid!=0 && i==cidmaster->subfontcnt ) {
1857 sc=NULL;
1858 } else if ( i==cidmaster->subfontcnt ) {
1859 /* They didn't define CID 0 */
1860 sc = &dummynotdef;
1861 /* Place it in the final subfont (which is what sf points to) */
1862 memset(sc,0,sizeof(dummynotdef));
1863 dummynotdef.name = ".notdef";
1864 dummynotdef.parent = sf;
1865 dummynotdef.layer_cnt = layer+1;
1866 dummynotdef.layers = gcalloc(layer+1,sizeof(Layer));
1867 dummynotdef.width = SFOneWidth(sf);
1868 if ( dummynotdef.width==-1 )
1869 dummynotdef.width = (sf->ascent+sf->descent);
1870 Type2NotDefSplines(sf,&dummynotdef,layer);
1871 gi.gb[cnt].sc = sc;
1872 gi.gb[cnt].fd = i = cidmaster->subfontcnt-1;
1873 #if 0 && HANYANG /* Too much stuff knows the glyph cnt, can't refigure it here at the end */
1874 } else if ( sf->glyphs[cid]->compositionunit ) {
1875 sc=NULL; /* don't output it, should be in a subroutine */;
1876 #endif
1877 } else {
1878 gi.gb[cnt].sc = sc = sf->glyphs[cid];
1879 gi.gb[cnt].fd = i;
1881 if ( sc!=NULL ) {
1882 sc->lsidebearing = 0x7fff;
1883 gi.active = &gi.gb[cnt];
1884 sc->ttf_glyph = cnt++;
1885 SplineChar2PS2(sc,NULL,fds[i].nomwid,fds[i].defwid,NULL,flags,&gi);
1887 ff_progress_next();
1890 scnts = gcalloc( cidmaster->subfontcnt+1,sizeof(int));
1891 for ( i=0; i<gi.pcnt; ++i ) {
1892 gi.psubrs[i].idx = -1;
1893 if ( gi.psubrs[i].cnt*gi.psubrs[i].len>(gi.psubrs[i].cnt*4)+gi.psubrs[i].len+1 )
1894 gi.psubrs[i].idx = scnts[gi.psubrs[i].fd+1]++;
1897 glbls = gcalloc(1,sizeof(struct pschars));
1898 glbls->cnt = scnts[0];
1899 glbls->next = scnts[0];
1900 glbls->lens = galloc(scnts[0]*sizeof(int));
1901 glbls->values = galloc(scnts[0]*sizeof(unsigned char *));
1902 glbls->bias = scnts[0]<1240 ? 107 :
1903 scnts[0]<33900 ? 1131 : 32768;
1904 for ( fd=0; fd<cidmaster->subfontcnt; ++fd ) {
1905 fds[fd].subrs = gcalloc(1,sizeof(struct pschars));
1906 fds[fd].subrs->cnt = scnts[fd+1];
1907 fds[fd].subrs->next = scnts[fd+1];
1908 fds[fd].subrs->lens = galloc(scnts[fd+1]*sizeof(int));
1909 fds[fd].subrs->values = galloc(scnts[fd+1]*sizeof(unsigned char *));
1910 fds[fd].subrs->bias = scnts[fd+1]<1240 ? 107 :
1911 scnts[fd+1]<33900 ? 1131 : 32768;
1913 free( scnts);
1915 for ( i=0; i<gi.pcnt; ++i ) {
1916 if ( gi.psubrs[i].idx != -1 ) {
1917 struct pschars *subrs = gi.psubrs[i].fd==-1 ? glbls : fds[gi.psubrs[i].fd].subrs;
1918 int scnt = gi.psubrs[i].idx;
1919 subrs->lens[scnt] = gi.psubrs[i].len+1;
1920 subrs->values[scnt] = galloc(subrs->lens[scnt]);
1921 memcpy(subrs->values[scnt],gi.psubrs[i].data,gi.psubrs[i].len);
1922 subrs->values[scnt][gi.psubrs[i].len] = 11; /* Add a return to end of subr */
1927 chrs = gcalloc(1,sizeof(struct pschars));
1928 chrs->cnt = cnt;
1929 chrs->next = cnt;
1930 chrs->lens = galloc(cnt*sizeof(int));
1931 chrs->values = galloc(cnt*sizeof(unsigned char *));
1932 chrs->keys = galloc(cnt*sizeof(char *));
1933 for ( i=0; i<cnt; ++i ) {
1934 int len=0;
1935 struct glyphbits *gb = &gi.gb[i];
1936 chrs->keys[i] = copy(gb->sc->name);
1937 for ( j=0; j<gb->bcnt; ++j ) {
1938 len += gb->bits[j].dlen;
1939 if ( gi.psubrs[ gb->bits[j].psub_index ].idx==-1 )
1940 len += gi.psubrs[ gb->bits[j].psub_index ].len;
1941 else {
1942 struct pschars *subrs = gi.psubrs[gb->bits[j].psub_index].fd==-1 ? glbls : fds[gi.psubrs[gb->bits[j].psub_index].fd].subrs;
1943 int si = gi.psubrs[ gb->bits[j].psub_index ].idx - subrs->bias;
1944 /* space for the number (subroutine index) */
1945 if ( si>=-107 && si<=107 )
1946 ++len;
1947 else if ( si>=-1131 && si<=1131 )
1948 len += 2;
1949 else if ( si>=-32768 && si<=32767 )
1950 len += 3;
1951 else
1952 len += 8;
1953 /* space for the subroutine operator */
1954 ++len;
1957 chrs->lens[i] = len+1;
1958 chrs->values[i] = galloc(len+2); /* space for endchar and a final NUL (which is really meaningless, but makes me feel better) */
1960 len = 0;
1961 for ( j=0; j<gb->bcnt; ++j ) {
1962 memcpy(chrs->values[i]+len,gb->bits[j].data,gb->bits[j].dlen);
1963 len += gb->bits[j].dlen;
1964 if ( gi.psubrs[ gb->bits[j].psub_index ].idx==-1 ) {
1965 memcpy(chrs->values[i]+len,gi.psubrs[ gb->bits[j].psub_index ].data,
1966 gi.psubrs[ gb->bits[j].psub_index ].len);
1967 len += gi.psubrs[ gb->bits[j].psub_index ].len;
1968 } else {
1969 struct pschars *subrs = gi.psubrs[gb->bits[j].psub_index].fd==-1 ? glbls : fds[gi.psubrs[gb->bits[j].psub_index].fd].subrs;
1970 int si = gi.psubrs[ gb->bits[j].psub_index ].idx - subrs->bias;
1971 /* space for the number (subroutine index) */
1972 if ( si>=-107 && si<=107 )
1973 chrs->values[i][len++] = si+139;
1974 else if ( si>0 && si<=1131 ) {
1975 si-=108;
1976 chrs->values[i][len++] = (si>>8)+247;
1977 chrs->values[i][len++] = si&0xff;
1978 } else if ( si>=-1131 && si<0 ) {
1979 si=(-si)-108;
1980 chrs->values[i][len++] = (si>>8)+251;
1981 chrs->values[i][len++] = si&0xff;
1982 } else if ( si>=-32768 && si<=32767 ) {
1983 chrs->values[i][len++] = 28;
1984 chrs->values[i][len++] = (si>>8)&0xff;
1985 chrs->values[i][len++] = si&0xff;
1986 } else {
1987 /* store as fixed point, then multiply by 64. Takes 8 bytes */
1988 si *= (65536/64);
1989 chrs->values[i][len++] = '\377';
1990 chrs->values[i][len++] = (si>>24)&0xff;
1991 chrs->values[i][len++] = (si>>16)&0xff;
1992 chrs->values[i][len++] = (si>>8)&0xff;
1993 chrs->values[i][len++] = si&0xff;
1994 chrs->values[i][len++] = 64 + 139;
1995 chrs->values[i][len++] = 0xc; chrs->values[i][len++] = 0x18; /* Multiply */
1997 /* space for the subroutine operator */
1998 if ( gi.psubrs[ gb->bits[j].psub_index ].fd==-1 ) {
1999 chrs->values[i][len++] = 29;
2000 } else
2001 chrs->values[i][len++] = 10;
2004 chrs->values[i][len++] = 14; /* endchar */
2005 chrs->values[i][len] = '\0';
2007 GIFree(&gi,&dummynotdef);
2008 *_glbls = glbls;
2009 return( chrs );