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.
30 #include "splinefont.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
{
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 */
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 */
109 int full_glyph_index
; /* Into the glyphbits array */
110 /* for full references */
111 BasePoint
*startstop
; /* Again for full references */
114 int hashed
[HSH_SIZE
];
117 int fd
; /* Which subfont is it in */
131 struct bits
*bits
; /* For current glyph */
138 uint8 mask
[HntMax
/8];
144 uint8 mask
[HntMax
/8];
145 int cnt
; /* number of hints */
146 struct mhlist
*sublist
;
147 struct pschars
*subrs
;
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 */
164 static void GIContentsFree(GlyphInfo
*gi
,SplineChar
*dummynotdef
) {
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
;
198 static void GIFree(GlyphInfo
*gi
,SplineChar
*dummynotdef
) {
200 GIContentsFree(gi
,dummynotdef
);
207 static void GrowBuffer(GrowBuf
*gb
) {
208 if ( gb
->base
==NULL
) {
209 gb
->base
= gb
->pt
= galloc(200);
210 gb
->end
= gb
->base
+ 200;
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
) {
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
);
237 gi
->justbroken
= false;
240 static int hashfunc(uint8
*data
, int len
) {
241 uint8
*end
= data
+len
;
242 unsigned int hash
= 0, r
;
247 hash
= (hash
|r
)&0xffffffff;
250 return( hash
%HSH_SIZE
);
253 static void BreakSubroutine(GrowBuf
*gb
,struct hintdb
*hdb
) {
255 struct potentialsubrs
*ps
;
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 ) {
268 gi
->justbroken
= true;
270 } else if ( gi
->justbroken
)
272 /* Otherwise stuff everything in the growbuffer into a subr */
273 hash
= hashfunc(gb
->base
,gb
->pt
-gb
->base
);
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 )
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
;
300 gi
->justbroken
= true;
303 static void MoveSubrsToChar(GlyphInfo
*gi
) {
304 struct glyphbits
*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
));
315 static int NumberHints(SplineChar
*scs
[MmMax
], int instance_count
) {
319 for ( j
=0; j
<instance_count
; ++j
) {
320 for ( s
=scs
[j
]->hstem
, i
=0; s
!=NULL
; s
=s
->next
) {
326 for ( s
=scs
[j
]->vstem
; s
!=NULL
; s
=s
->next
) {
335 IError("MM font with different hint counts");
340 void RefCharsFreeRef(RefChar
*ref
) {
343 while ( ref
!=NULL
) {
345 /* don't free the splines */
346 chunkfree(ref
,sizeof(RefChar
));
351 static void MarkTranslationRefs(SplineFont
*sf
,int layer
) {
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
) {
369 return( rint( pos
));
371 return( rint( pos
*100. )/100. );
374 static void AddNumber(GrowBuf
*gb
, real pos
, int round
) {
379 if ( gb
->pt
+8>=gb
->end
)
382 pos
= rint(100*pos
)/100;
384 if ( !round
&& pos
!=floor(pos
)) {
390 if ( pos
>=-107 && pos
<=107 )
392 else if ( pos
>=108 && pos
<=1131 ) {
394 *str
++ = (val
>>8)+247;
396 } else if ( pos
>=-1131 && pos
<=-108 ) {
399 *str
++ = (val
>>8)+251;
403 *str
++ = (val
>>24)&0xff;
404 *str
++ = (val
>>16)&0xff;
405 *str
++ = (val
>>8)&0xff;
409 *str
++ = 100+139; /* 100 */
410 *str
++ = 12; /* div (byte1) */
411 *str
++ = 12; /* div (byte2) */
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
,
422 int allsame
= true, alls
[6];
423 int i
,j
, chunk
,min
,max
,subr
;
425 for ( j
=0; j
<num_coords
; ++j
) {
427 for ( i
=1; i
<instances
; ++i
) {
428 if ( data
[i
][j
]!=data
[0][j
] ) {
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
);
443 chunk
= 22/instances
;
444 if ( chunk
== 5 ) chunk
= 4; /* No subroutine for 5 items */
446 while ( min
<num_coords
) {
447 while ( min
<num_coords
&& alls
[min
] ) {
448 AddNumber(gb
,data
[0][min
],round
);
452 if ( max
>num_coords
) max
= num_coords
;
453 while ( max
-1>min
&& alls
[max
-1] )
455 if ( max
-min
==5 ) max
=min
+4;
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
);
463 if ( j
-min
==6 ) subr
= 9;
464 AddNumber(gb
,subr
,round
);
465 if ( gb
->pt
+1>=gb
->end
)
467 *gb
->pt
++ = 10; /* callsubr */
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
;
481 for ( i
=0; i
<instance_count
; ++i
) {
482 if ( (ishstem
&& scs
[i
]->hconflicts
) || (!ishstem
&& scs
[i
]->vconflicts
))
484 h1
= ishstem
? scs
[i
]->hstem
: scs
[i
]->vstem
;
485 if ( h1
==NULL
|| (h2
= h1
->next
)==NULL
|| (h3
=h2
->next
)==NULL
)
487 if ( h3
->next
!=NULL
)
489 off
= ishstem
? 0 : scs
[i
]->lsidebearing
;
492 _h1
.start
+= _h1
.width
;
493 _h1
.width
= -_h1
.width
;
498 _h2
.start
+= _h2
.width
;
499 _h2
.width
= -_h2
.width
;
504 _h3
.start
+= _h3
.width
;
505 _h3
.width
= -_h3
.width
;
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
)
520 if ( (h2
->start
+h2
->width
/2) - (h1
->start
+h1
->width
/2) !=
521 (h3
->start
+h3
->width
/2) - (h2
->start
+h2
->width
/2) )
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
;
532 AddData(gb
,data
,instance_count
,6,round
);
533 if ( gb
->pt
+3>=gb
->end
)
536 *(gb
->pt
)++ = ishstem
?2:1; /* h/v stem3 */
540 static int _SCNeedsSubsPts(SplineChar
*sc
,int layer
) {
543 if ( sc
->hstem
==NULL
&& sc
->vstem
==NULL
)
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
));
562 MMSet
*mm
= sc
->parent
->mm
;
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
) )
572 /* Mark those glyphs which can live totally in subrs */
573 static void SplineFont2FullSubrs1(int flags
,GlyphInfo
*gi
) {
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
) {
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
) {
599 int CIDOneWidth(SplineFont
*_sf
) {
604 if ( _sf
->cidmaster
!=NULL
) _sf
= _sf
->cidmaster
;
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
) {
622 } while ( k
<_sf
->subfontcnt
);
627 static void SetupType1Subrs(struct pschars
*subrs
,GlyphInfo
*gi
) {
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
++;
642 gi
->psubrs
[i
].idx
= -1;
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 )
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
) {
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
) {
671 struct glyphbits
*gb
= &gi
->gb
[i
];
675 chrs
->keys
[i
] = copy(gb
->sc
->name
);
676 for ( k
=0; k
<2; ++k
) if ( k
!=0 || gb
->sc
->ttf_glyph
!=0x7fff ) {
678 for ( j
=0; j
<gb
->bcnt
; ++j
) {
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);
686 if ( gi
->psubrs
[ gb
->bits
[j
].psub_index
].idx
==-1 )
687 len
+= gi
->psubrs
[ gb
->bits
[j
].psub_index
].len
;
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 */
695 int si
= gi
->psubrs
[ gb
->sc
->ttf_glyph
].idx
;
696 subrs
->lens
[si
] = len
+1;
697 vals
= subrs
->values
[si
] = galloc(len
+2);
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) */
705 for ( j
=0; j
<gb
->bcnt
; ++j
) {
707 if ( k
!=0 || j
!=0 ) {
708 memcpy(vals
+len
,gb
->bits
[j
].data
,gb
->bits
[j
].dlen
);
709 len
+= gb
->bits
[j
].dlen
;
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
;
719 si
= gi
->psubrs
[ gb
->bits
[j
].psub_index
].idx
;
721 /* space for the number (subroutine index) */
723 vals
[len
++] = si
+139;
724 else if ( si
>0 && si
<=1131 ) {
726 vals
[len
++] = (si
>>8)+247;
727 vals
[len
++] = si
&0xff;
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 */
738 if ( k
==1 && gb
->sc
->ttf_glyph
!=0x7fff )
742 vals
[len
++] = 11; /* return */
744 } else if ( gb
->wasseac
) {
745 /* Don't want an endchar */
748 vals
[len
++] = 14; /* endchar */
755 /* ************************************************************************** */
756 /* ********************** Type2 PostScript CharStrings ********************** */
757 /* ************************************************************************** */
760 static int real_warn
= false;
763 static real
myround2(real pos
, int round
) {
767 return( rint(65536*pos
)/65536 );
770 static void AddNumber2(GrowBuf
*gb
, real pos
, int round
) {
774 if ( gb
->pt
+5>=gb
->end
)
777 pos
= rint(65536*pos
)/65536;
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"),
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 )
792 AddNumber2(gb
,pos
/factor
,false);
793 AddNumber2(gb
,factor
,false);
794 if ( gb
->pt
+2>=gb
->end
)
796 *(gb
->pt
++) = 0x0c; /* Multiply operator */
798 } else if ( pos
!=floor(pos
)) {
801 *str
++ = (val
>>24)&0xff;
802 *str
++ = (val
>>16)&0xff;
803 *str
++ = (val
>>8)&0xff;
807 if ( pos
>=-107 && pos
<=107 )
809 else if ( pos
>=108 && pos
<=1131 ) {
811 *str
++ = (val
>>8)+247;
813 } else if ( pos
>=-1131 && pos
<=-108 ) {
816 *str
++ = (val
>>8)+251;
820 *str
++ = (val
>>8)&0xff;
827 static void AddMask2(GrowBuf
*gb
,uint8 mask
[12],int cnt
, int oper
) {
830 if ( gb
->pt
+1+((cnt
+7)>>3)>=gb
->end
)
832 *gb
->pt
++ = oper
; /* hintmask,cntrmask */
833 for ( i
=0; i
< ((cnt
+7)>>3); ++i
)
837 static void CounterHints2(GrowBuf
*gb
, SplineChar
*sc
, int hcnt
) {
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
)
853 if ( memcmp(hdb
->mask
,*to
->hintmask
,(hdb
->cnt
+7)/8)==0 )
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;
863 StartNextSubroutine(gb
,hdb
);
867 static void moveto2(GrowBuf
*gb
,struct hintdb
*hdb
,SplinePoint
*to
, int round
) {
868 BasePoint temp
, *tom
;
870 if ( gb
->pt
+18 >= gb
->end
)
873 BreakSubroutine(gb
,hdb
);
874 HintSetup2(gb
,hdb
,to
,false);
877 temp
.x
= rint(tom
->x
);
878 temp
.y
= rint(tom
->y
);
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 */
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 */
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
) {
905 Spline
*test
, *lastgood
, *lasthvgood
;
906 BasePoint temp1
, temp2
, *tom
, *fromm
;
910 for ( test
=spline
, cnt
=0; test
->knownlinear
&& cnt
<15; ) {
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
)
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 */
929 lasthvgood
= spline
; hvcnt
= 1;
931 for ( test
=spline
->to
->next
; test
!=NULL
; test
= test
->to
->next
) {
932 fromm
= &test
->from
->me
;
934 temp2
.x
= rint(fromm
->x
);
935 temp2
.y
= rint(fromm
->y
);
940 temp1
.x
= rint(tom
->x
);
941 temp1
.y
= rint(tom
->y
);
944 if ( hv
==1 && tom
->y
==fromm
->y
)
946 else if ( hv
==0 && tom
->x
==fromm
->x
)
952 if ( test
==lastgood
)
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
)
963 fromm
= &test
->from
->me
;
965 temp2
.x
= rint(fromm
->x
);
966 temp2
.y
= rint(fromm
->y
);
971 temp1
.x
= rint(tom
->x
);
972 temp1
.y
= rint(tom
->y
);
975 if ( fromm
->x
==tom
->x
)
976 AddNumber2(gb
,tom
->y
-fromm
->y
,round
);
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
;
986 if ( gb
->pt
+1 >= gb
->end
)
988 *(gb
->pt
)++ = spline
->from
->me
.x
==spline
->to
->me
.x
? 7 : 6;
993 for ( test
=spline
; test
!=NULL
; test
= test
->to
->next
) {
994 if ( !donehm
&& test
->to
->hintmask
!=NULL
)
997 fromm
= &test
->from
->me
;
999 temp2
.x
= rint(fromm
->x
);
1000 temp2
.y
= rint(fromm
->y
);
1003 tom
= &test
->to
->me
;
1005 temp1
.x
= rint(tom
->x
);
1006 temp1
.y
= rint(tom
->y
);
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
;
1018 if ( gb
->pt
+1 >= gb
->end
)
1020 *(gb
->pt
)++ = 5; /* r line to */
1024 static Spline
*curveto2(GrowBuf
*gb
,struct hintdb
*hdb
,Spline
*spline
, Spline
*done
, int round
) {
1030 HintSetup2(gb
,hdb
,spline
->to
,true);
1033 if ( hdb
->current
.x
==myround2(spline
->from
->nextcp
.x
,round
) &&
1034 myround2(spline
->to
->prevcp
.y
,round
)==myround2(spline
->to
->me
.y
,round
) )
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
) )
1041 first
= spline
; start
= hdb
->current
;
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
)
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
);
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
);
1063 hdb
->current
.x
= myround2(spline
->to
->me
.x
,round
);
1064 hdb
->current
.y
= myround2(spline
->to
->me
.y
,round
);
1066 spline
= spline
->to
->next
;
1067 if ( spline
==done
|| spline
==NULL
|| cnt
>9 || spline
->knownlinear
)
1070 if ( gb
->pt
+1 >= gb
->end
)
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 */
1077 if ( !donehm
&& spline
->to
->hintmask
!=NULL
)
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
) )
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
) )
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
);
1102 spline
= spline
->to
->next
;
1103 if ( spline
==done
|| spline
==NULL
|| spline
->knownlinear
)
1106 if ( gb
->pt
+1 >= gb
->end
)
1108 *(gb
->pt
)++ = 8; /* rrcurveto */
1112 static void flexto2(GrowBuf
*gb
,struct hintdb
*hdb
,Spline
*pspline
,int round
) {
1113 BasePoint
*c0
, *c1
, *mid
, *end
, *nc0
, *nc1
;
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
)
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 */
1140 if ( gb
->pt
+11*6+2 >= gb
->end
)
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
);
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;;
1170 freeme
= spl
= SplineSetsPSApprox(spl
);
1172 for ( ; spl
!=NULL
; spl
= spl
->next
) {
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 */
1188 temp
.first
= temp
.last
= spl
->first
->next
->to
;
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 */
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
)
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) */
1213 else if ( spline
->knownlinear
)
1214 spline
= lineto2(gb
,hdb
,spline
,first
,round
);
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*/
1224 SplinePointListsFree(freeme
);
1227 static void DumpHints(GrowBuf
*gb
,StemInfo
*h
,int oper
,int midoper
,int round
) {
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
)
1240 *gb
->pt
++ = midoper
;
1243 cur
= myround2(h
->start
,round
) + myround2(h
->width
,round
);
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
);
1254 AddNumber2(gb
,myround2(h
->start
+21,round
)-last
,round
);
1255 AddNumber2(gb
,-21,round
);
1256 cur
= myround2(h
->start
+21,round
)-21;
1259 AddNumber2(gb
,myround2(h
->start
,round
)-last
,round
);
1260 AddNumber2(gb
,myround2(h
->width
,round
),round
);
1267 if ( gb
->pt
+1>=gb
->end
)
1273 static void DumpRefsHints(GrowBuf
*gb
, struct hintdb
*hdb
,RefChar
*cur
,StemInfo
*h
,StemInfo
*v
,
1274 BasePoint
*trans
, int round
,int layer
) {
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
));
1292 if ( h
==NULL
&& v
==NULL
)
1293 IError("hintmask invoked when there are no hints");
1294 memset(masks
,'\0',sizeof(masks
));
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);
1305 } else if ( rpos
>pos
)
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);
1318 } else if ( rpos
>pos
)
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
) {
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
) {
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
) {
1356 BasePoint temp
, rtrans
;
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
;
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 */
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
)
1383 *gb
->pt
++ = hdb
->current
.x
==temp
.x
?4: /* vmoveto */
1384 hdb
->current
.y
==temp
.y
?22: /* hmoveto */
1386 if ( r
->sc
->lsidebearing
==0x7fff )
1387 IError("Attempt to reference an unreferenceable glyph %s", r
->sc
->name
);
1390 StartNextSubroutine(gb
,hdb
);
1391 gi
->bits
[gi
->bcnt
].psub_index
= r
->sc
->lsidebearing
;
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
) {
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
;
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;
1417 for ( r
=rsc
->layers
[layer
].refs
; r
!=NULL
; r
=r
->next
) {
1418 if ( !r
->justtranslated
)
1420 if ( r
->sc
->hconflicts
|| r
->sc
->vconflicts
) {
1423 } else if ( r
->sc
->hstem
!=NULL
|| r
->sc
->vstem
!=NULL
)
1424 allwithouthints
= false;
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
);
1442 /* What is the hintmask state here? It should not matter */
1443 freeme
= NULL
; temp
= rsc
->layers
[layer
].splines
;
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
);
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
,
1488 StemInfo
*oldh
= NULL
, *oldv
= NULL
;
1490 SplineChar
*scs
[MmMax
];
1491 int round
= (flags
&ps_flag_round
)? true : false;
1492 HintMask
*hm
= NULL
;
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
&&
1505 hm
= sc
->layers
[gi
->layer
].splines
->first
->hintmask
;
1506 sc
->layers
[gi
->layer
].splines
->first
->hintmask
= NULL
;
1509 memset(&gb
,'\0',sizeof(gb
));
1513 /* store the width on the stack */
1514 if ( sc
->width
==defwid
)
1515 /* Don't need to do anything for the width */;
1517 AddNumber2(&gb
,sc
->width
-nomwid
,round
);
1519 memset(&trans
,'\0',sizeof(trans
));
1520 memset(&hdb
,'\0',sizeof(hdb
));
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 */
1537 StartNextSubroutine(&gb
,&hdb
);
1539 BreakSubroutine(&gb
,&hdb
);
1540 MoveSubrsToChar(gi
);
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
;
1552 static SplinePoint
*FFLineTo(SplinePoint
*last
, int x
, int y
) {
1553 SplinePoint
*sp
= SplinePointCreate(x
,y
);
1554 SplineMake3(last
,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 */
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
;
1595 hints
= chunkalloc(sizeof(StemInfo
));
1597 hints
->width
= stem
;
1598 hints
->next
= h
= chunkalloc(sizeof(StemInfo
));
1599 h
->start
= ymax
-stem
;
1604 /* Mark those glyphs which can live totally in subrs */
1605 static void SplineFont2FullSubrs2(int flags
,GlyphInfo
*gi
) {
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
;
1620 SplineChar dummynotdef
;
1622 memset(&gi
,0,sizeof(gi
));
1623 memset(&gi
.hashed
,-1,sizeof(gi
.hashed
));
1624 gi
.instance_count
= 1;
1629 gi
.gb
= gcalloc(cnt
,sizeof(struct glyphbits
));
1631 gi
.psubrs
= galloc(gi
.pmax
*sizeof(struct potentialsubrs
));
1632 for ( i
=0; i
<cnt
; ++i
) {
1634 if ( i
==0 && gid
==-1 ) {
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
];
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
)
1658 gi
.active
= &gi
.gb
[i
];
1659 SplineChar2PS2(sc
,NULL
,nomwid
,defwid
,NULL
,flags
,&gi
);
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
++;
1673 gi
.psubrs
[i
].idx
= -1;
1675 subrs
= gcalloc(1,sizeof(struct pschars
));
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
));
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
) {
1701 struct glyphbits
*gb
= &gi
.gb
[i
];
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
) {
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);
1714 if ( gi
.psubrs
[ gb
->bits
[j
].psub_index
].idx
==-1 )
1715 len
+= gi
.psubrs
[ gb
->bits
[j
].psub_index
].len
;
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 )
1721 else if ( si
>=-1131 && si
<=1131 )
1723 else if ( si
>=-32768 && si
<=32767 )
1727 /* space for the subroutine operator */
1732 int si
= gi
.psubrs
[ gb
->sc
->lsidebearing
].idx
;
1733 subrs
->lens
[si
] = len
+1;
1734 vals
= subrs
->values
[si
] = galloc(len
+2);
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) */
1741 for ( j
=0; j
<gb
->bcnt
; ++j
) {
1743 if ( k
!=0 || j
!=0 ) {
1744 memcpy(vals
+len
,gb
->bits
[j
].data
,gb
->bits
[j
].dlen
);
1745 len
+= gb
->bits
[j
].dlen
;
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
;
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 ) {
1762 vals
[len
++] = (si
>>8)+247;
1763 vals
[len
++] = si
&0xff;
1764 } else if ( si
>=-1131 && si
<0 ) {
1766 vals
[len
++] = (si
>>8)+251;
1767 vals
[len
++] = si
&0xff;
1768 } else if ( si
>=-32768 && si
<=32767 ) {
1770 vals
[len
++] = (si
>>8)&0xff;
1771 vals
[len
++] = si
&0xff;
1773 /* store as fixed point, then multiply by 64. Takes 8 bytes */
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 */
1787 if ( k
==1 && gb
->sc
->lsidebearing
!=0x7fff )
1791 vals
[len
++] = 11; /* return */
1794 vals
[len
++] = 14; /* endchar */
1800 GIFree(&gi
,&dummynotdef
);
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
;
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 */
1816 SplineChar dummynotdef
;
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
) {
1830 sc
->lsidebearing
= 0x7fff;
1831 if ( SCWorthOutputting(sc
))
1838 memset(&gi
,0,sizeof(gi
));
1839 memset(&gi
.hashed
,-1,sizeof(gi
.hashed
));
1840 gi
.instance_count
= 1;
1844 gi
.gb
= gcalloc(cnt
,sizeof(struct glyphbits
));
1846 gi
.psubrs
= galloc(gi
.pmax
*sizeof(struct potentialsubrs
));
1849 for ( cid
= cnt
= 0; cid
<max
; ++cid
) {
1851 for ( i
=0; i
<cidmaster
->subfontcnt
; ++i
) {
1852 sf
= cidmaster
->subfonts
[i
];
1853 if ( cid
<sf
->glyphcnt
&& SCWorthOutputting(sf
->glyphs
[cid
]) )
1856 if ( cid
!=0 && i
==cidmaster
->subfontcnt
) {
1858 } else if ( i
==cidmaster
->subfontcnt
) {
1859 /* They didn't define CID 0 */
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
);
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 */;
1878 gi
.gb
[cnt
].sc
= sc
= sf
->glyphs
[cid
];
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
);
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;
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
));
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
) {
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
;
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 )
1947 else if ( si
>=-1131 && si
<=1131 )
1949 else if ( si
>=-32768 && si
<=32767 )
1953 /* space for the subroutine operator */
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) */
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
;
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 ) {
1976 chrs
->values
[i
][len
++] = (si
>>8)+247;
1977 chrs
->values
[i
][len
++] = si
&0xff;
1978 } else if ( si
>=-1131 && si
<0 ) {
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;
1987 /* store as fixed point, then multiply by 64. Takes 8 bytes */
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;
2001 chrs
->values
[i
][len
++] = 10;
2004 chrs
->values
[i
][len
++] = 14; /* endchar */
2005 chrs
->values
[i
][len
] = '\0';
2007 GIFree(&gi
,&dummynotdef
);