w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

tottfvar.c
Go to the documentation of this file.
1 /* Copyright (C) 2000-2012 by George Williams */
2 /*
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions are met:
5 
6  * Redistributions of source code must retain the above copyright notice, this
7  * list of conditions and the following disclaimer.
8 
9  * Redistributions in binary form must reproduce the above copyright notice,
10  * this list of conditions and the following disclaimer in the documentation
11  * and/or other materials provided with the distribution.
12 
13  * The name of the author may not be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15 
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 #include "fontforge.h"
28 #include "ttf.h"
29 #include <math.h>
30 
32  struct splinecharlist *dep;
33 
34  if ( sc==NULL )
35 return( false );
36 
37  if ( sc->ttf_instrs!=NULL )
38 return( true );
39  for ( dep= sc->dependents; dep!=NULL ; dep=dep->next )
40  if ( dep->sc->ttf_instrs!=NULL )
41 return( true );
42 
43 return( false );
44 }
45 
46 static int AssignPtNumbers(MMSet *mm,int gid) {
47  /* None of the instances has fixed point numbers. Make them match */
48  int cnt=0;
49  SplineSet **ss;
50  SplinePoint **sp;
51  int i;
52  int allavg, alllines, stillmore, ret=true;
53 
54  ss = malloc((mm->instance_count+1)*sizeof(SplineSet *));
55  sp = malloc((mm->instance_count+1)*sizeof(SplinePoint *));
56  for ( i=0; i<mm->instance_count; ++i )
57  ss[i] = mm->instances[i]->glyphs[gid]->layers[ly_fore].splines;
58  ss[i] = mm->normal->glyphs[gid]->layers[ly_fore].splines;
59 
60  if ( ss[0]==NULL ) {
61  stillmore = false;
62  for ( i=0; i<=mm->instance_count; ++i )
63  if ( ss[i]!=NULL ) stillmore = true;
64  free(ss);
65  free(sp);
66  if ( stillmore )
67 return( false );
68 return( true );
69  } else {
70  stillmore = true;
71  for ( i=0; i<=mm->instance_count; ++i )
72  if ( ss[i]==NULL ) stillmore = false;
73  if ( !stillmore )
74 {
75 free(ss);
76 free(sp);
77 return( false );
78 }
79  }
80 
81  for (;;) {
82  for ( i=0; i<=mm->instance_count; ++i )
83  sp[i] = ss[i]->first;
84  for (;;) {
85  allavg = alllines = true;
86  for ( i=0; i<=mm->instance_count; ++i ) {
87  if ( !RealNear(sp[i]->me.x,(sp[i]->nextcp.x+sp[i]->prevcp.x)/2) ||
88  !RealNear(sp[i]->me.y,(sp[i]->nextcp.y+sp[i]->prevcp.y)/2) )
89  allavg = false;
90  if ( !sp[i]->nonextcp )
91  alllines = false;
92  }
93  if ( sp[0] == ss[0]->first )
94  allavg = false;
95  for ( i=0; i<=mm->instance_count; ++i ) {
96  if ( allavg )
97  sp[i]->ttfindex = 0xffff;
98  else
99  sp[i]->ttfindex = cnt;
100  }
101  if ( !allavg )
102  ++cnt;
103  for ( i=0; i<=mm->instance_count; ++i ) {
104  if ( alllines )
105  sp[i]->nextcpindex = 0xffff;
106  else
107  sp[i]->nextcpindex = cnt;
108  }
109  if ( !alllines )
110  ++cnt;
111 
112  if ( sp[0]->next==NULL ) {
113  stillmore = false;
114  for ( i=1; i<=mm->instance_count; ++i )
115  if ( sp[i]->next!=NULL )
116  stillmore = true;
117  if ( stillmore )
118  ret = false;
119  break;
120  }
121  for ( i=1; i<=mm->instance_count; ++i )
122  if ( sp[i]->next==NULL )
123  stillmore = false;
124  if ( !stillmore ) {
125  ret = false;
126  break;
127  }
128  sp[0] = sp[0]->next->to;
129  for ( i=1; i<=mm->instance_count; ++i )
130  sp[i] = sp[i]->next->to;
131  if ( sp[0]==ss[0]->first ) {
132  stillmore = false;
133  for ( i=1; i<=mm->instance_count; ++i )
134  if ( sp[i]!=ss[i]->first )
135  stillmore = true;
136  if ( stillmore )
137  ret = false;
138  break;
139  }
140  for ( i=1; i<=mm->instance_count; ++i ) {
141  if ( sp[i]==ss[i]->first )
142  stillmore = false;
143  }
144  if ( !stillmore ) {
145  ret = false;
146  break;
147  }
148  }
149  if ( !ret )
150  break;
151  stillmore = true;
152  for ( i=0; i<=mm->instance_count; ++i )
153  ss[i] = ss[i]->next;
154  if ( ss[0]==NULL ) {
155  stillmore=false;
156  for ( i=1; i<=mm->instance_count; ++i )
157  if ( ss[i]!=NULL )
158  stillmore = true;
159  if ( stillmore )
160  ret = true;
161  break;
162  }
163  for ( i=1; i<=mm->instance_count; ++i )
164  if ( ss[i]==NULL )
165  stillmore = false;
166  if ( !stillmore ) {
167  ret = true;
168  break;
169  }
170  }
171  free(ss);
172  free(sp);
173 return( ret );
174 }
175 
176 static int MatchPoints(SplineFont *sffixed, SplineFont *sfother, int gid) {
178  SplineSet *ss1, *ss2;
179  SplinePoint *sp1, *sp2;
180 
181  fixed = sffixed->glyphs[gid]; other = sfother->glyphs[gid];
182 
183  if ( PtNumbersAreSet(other)) {
184  /* Point numbers must match exactly, both are fixed */
185  for ( ss1=fixed->layers[ly_fore].splines,
186  ss2=other->layers[ly_fore].splines;
187  ss1!=NULL && ss2!=NULL ;
188  ss1 = ss1->next, ss2=ss2->next ) {
189  for ( sp1=ss1->first, sp2=ss2->first; ; ) {
190  if ( sp1->ttfindex!=sp2->ttfindex ||
191  sp1->nextcpindex!=sp2->nextcpindex )
192 return( false );
193  if ( sp1->next==NULL || sp2->next==NULL ) {
194  if ( sp1->next!=NULL || sp2->next!=NULL )
195 return( false );
196  break;
197  }
198  sp1 = sp1->next->to; sp2=sp2->next->to;
199  if ( sp1==ss1->first || sp2==ss2->first ) {
200  if ( sp1!=ss1->first || sp2!=ss2->first )
201 return( false );
202  break;
203  }
204  }
205  }
206 return( ss1==NULL && ss2==NULL );
207  } else {
208  for ( ss1=fixed->layers[ly_fore].splines,
209  ss2=other->layers[ly_fore].splines;
210  ss1!=NULL && ss2!=NULL ;
211  ss1 = ss1->next, ss2=ss2->next ) {
212  for ( sp1=ss1->first, sp2=ss2->first; ; ) {
213  if ( sp1->ttfindex!=0xffff )
214  sp2->ttfindex = sp1->ttfindex;
215  else if ( !RealNear(sp2->me.x,(sp2->nextcp.x+sp2->prevcp.x)/2) ||
216  !RealNear(sp2->me.y,(sp2->nextcp.y+sp2->prevcp.y)/2) )
217 return( false );
218  else
219  sp2->ttfindex = 0xffff;
220  if ( sp1->nextcpindex!=0xffff )
221  sp2->nextcpindex = sp1->nextcpindex;
222  else if ( !sp2->nonextcp )
223 return( false );
224  else
225  sp2->nextcpindex = 0xffff;
226  if ( sp1->next==NULL || sp2->next==NULL ) {
227  if ( sp1->next!=NULL || sp2->next!=NULL )
228 return( false );
229  break;
230  }
231  sp1 = sp1->next->to; sp2=sp2->next->to;
232  if ( sp1==ss1->first || sp2==ss2->first ) {
233  if ( sp1!=ss1->first || sp2!=ss2->first )
234 return( false );
235  break;
236  }
237  }
238  }
239 return( ss1==NULL && ss2==NULL );
240  }
241 }
242 
243 int ContourPtNumMatch(MMSet *mm, int gid) {
244  SplineFont *sf;
245  int i;
246 
247  if ( !mm->apple )
248 return( false );
249 
250  if ( gid>=mm->normal->glyphcnt )
251 return( false );
252  if ( !SCWorthOutputting(mm->normal->glyphs[gid] ) ) {
253  for ( i=0; i<mm->instance_count; ++i ) {
254  if ( gid>=mm->instances[i]->glyphcnt )
255 return( false );
256  if ( SCWorthOutputting(mm->instances[i]->glyphs[gid]))
257 return( false );
258  }
259 return( true ); /* None is not worth outputting, and that's ok, they match */
260  } else {
261  for ( i=0; i<mm->instance_count; ++i ) {
262  if ( gid>=mm->instances[i]->glyphcnt )
263 return( false );
264  if ( !SCWorthOutputting(mm->instances[i]->glyphs[gid]))
265 return( false );
266  }
267  /* All are worth outputting */
268  }
269 
270  if ( mm->normal->glyphs[gid]->layers[ly_fore].refs!=NULL && mm->normal->glyphs[gid]->layers[ly_fore].splines!=NULL )
271 return( false );
272  for ( i=0; i<mm->instance_count; ++i ) {
273  if ( mm->instances[i]->glyphs[gid]->layers[ly_fore].refs!=NULL && mm->instances[i]->glyphs[gid]->layers[ly_fore].splines!=NULL )
274 return( false );
275  }
276  if ( mm->normal->glyphs[gid]->layers[ly_fore].refs!=NULL ) {
277  RefChar *r;
278  int cnt, c;
279  for ( r=mm->normal->glyphs[gid]->layers[ly_fore].refs, cnt=0; r!=NULL; r=r->next )
280  ++cnt;
281  for ( i=0; i<mm->instance_count; ++i ) {
282  for ( r=mm->instances[i]->glyphs[gid]->layers[ly_fore].refs, c=0; r!=NULL; r=r->next )
283  ++c;
284  if ( c!=cnt )
285 return( false );
286  }
287  }
288 
289  sf = NULL;
290  if ( PtNumbersAreSet(mm->normal->glyphs[gid]) )
291  sf = mm->normal;
292  else {
293  for ( i=0; i<mm->instance_count; ++i ) {
294  if ( PtNumbersAreSet(mm->instances[i]->glyphs[gid])) {
295  sf = mm->instances[i];
296  break;
297  }
298  }
299  }
300  if ( sf==NULL )
301  /* No instance has fixed points. Make sure all fonts are consistent */
302 return( AssignPtNumbers(mm,gid));
303 
304  if ( sf!=mm->normal && !MatchPoints(sf,mm->normal,gid))
305 return( false );
306  for ( i=0; i<mm->instance_count; ++i ) if ( sf!=mm->instances[i] ) {
307  if ( !MatchPoints(sf, mm->instances[i],gid) )
308 return( false );
309  }
310 return( true );
311 }
312 
313 static int SCPointCount(SplineChar *sc) {
314  int ptcnt=0;
315  RefChar *r;
316 
317  ptcnt = SSTtfNumberPoints(sc->layers[ly_fore].splines);
318  for ( r=sc->layers[ly_fore].refs; r!=NULL ; r=r->next )
319  ++ptcnt;
320 return( ptcnt );
321 }
322 
323 int16 **SCFindDeltas(MMSet *mm, int gid, int *_ptcnt) {
324  /* When figuring out the deltas the first thing we must do is figure */
325  /* out each point's number */
326  int i, j, k, l, cnt, ptcnt;
327  int16 **deltas;
328  SplineSet *ss1, *ss2;
329  SplinePoint *sp1, *sp2;
330  RefChar *r1, *r2;
331 
332  if ( !ContourPtNumMatch(mm,gid))
333 return( NULL );
334  if ( !SCWorthOutputting(mm->normal->glyphs[gid]))
335 return( NULL );
336 
337  *_ptcnt = ptcnt = SCPointCount(mm->normal->glyphs[gid])+4;
338  deltas = malloc(2*mm->instance_count*sizeof(int16 *));
339  for ( i=0; i<2*mm->instance_count; ++i )
340  deltas[i] = calloc(ptcnt,sizeof(int16));
341  for ( i=0; i<mm->instance_count; ++i ) {
342  for ( ss1=mm->normal->glyphs[gid]->layers[ly_fore].splines,
343  ss2=mm->instances[i]->glyphs[gid]->layers[ly_fore].splines;
344  ss1!=NULL && ss2!=NULL ;
345  ss1 = ss1->next, ss2=ss2->next ) {
346  for ( sp1=ss1->first, sp2=ss2->first; ; ) {
347  if ( sp1->ttfindex!=0xffff ) {
348  deltas[2*i][sp1->ttfindex] = rint(sp2->me.x)-rint(sp1->me.x);
349  deltas[2*i+1][sp1->ttfindex] = rint(sp2->me.y)-rint(sp1->me.y);
350  }
351  if ( sp1->nextcpindex != 0xffff ) {
352  deltas[2*i][sp1->nextcpindex] = rint(sp2->nextcp.x)-rint(sp1->nextcp.x);
353  deltas[2*i+1][sp1->nextcpindex] = rint(sp2->nextcp.y)-rint(sp1->nextcp.y);
354  }
355  if ( sp1->next==NULL )
356  break;
357  sp1 = sp1->next->to; sp2 = sp2->next->to;
358  if ( sp1==ss1->first )
359  break;
360  }
361  }
362  for ( cnt=0,
363  r1=mm->normal->glyphs[gid]->layers[ly_fore].refs,
364  r2=mm->instances[i]->glyphs[gid]->layers[ly_fore].refs;
365  r1!=NULL && r2!=NULL;
366  r1=r1->next, r2=r2->next, ++cnt ) {
367  deltas[2*i][cnt] = r2->transform[4]-r1->transform[4];
368  deltas[2*i+1][cnt] = r2->transform[5]-r1->transform[5];
369  }
370  /* Phantom points */
371  deltas[2*i][ptcnt-4] = 0; deltas[2*i+1][ptcnt-4] = 0; /* lbearing */
372  deltas[2*i][ptcnt-3] = mm->instances[i]->glyphs[gid]->width -mm->normal->glyphs[gid]->width;
373  deltas[2*i+1][ptcnt-3] = 0; /* horizontal advance */
374  deltas[2*i][ptcnt-2] = 0; deltas[2*i+1][ptcnt-2] = 0; /* top bearing */
375  deltas[2*i][ptcnt-1] = 0; /* vertical advance */
376  deltas[2*i+1][ptcnt-1] = mm->instances[i]->glyphs[gid]->vwidth -mm->normal->glyphs[gid]->vwidth; /* horizontal advance */
377  }
378 
379  /* Ok, each delta now contains the difference between the instance[i] points */
380  /* and the base points. But that isn't good enough. We must subtract */
381  /* [0,1] and [1,0] from [1,1], and then subtract [1,1,0] [1,0,1] [0,1,1] */
382  /* from [1,1,1] and so on (also [-1,0] from [-1,1], etc.) */
383  for ( j=1; j<mm->axis_count; ++j ) {
384  for ( i=0; i<mm->instance_count; ++i ) {
385  for ( k=cnt=0; k<mm->axis_count; ++k )
386  if ( mm->positions[i*mm->axis_count+k]!=0 )
387  ++cnt;
388  if ( cnt==j ) {
389  for ( l = 0; l<mm->instance_count; ++l ) if ( l!=i ) {
390  for ( k=0; k<mm->axis_count; ++k )
391  if ( mm->positions[i*mm->axis_count+k]!=0 &&
392  mm->positions[l*mm->axis_count+k]!=mm->positions[i*mm->axis_count+k])
393  break;
394  if ( k==mm->axis_count ) {
395  for ( k=0; k<ptcnt; ++k ) {
396  deltas[2*l][k] -= deltas[2*i][k];
397  deltas[2*l+1][k] -= deltas[2*i+1][k];
398  }
399  }
400  }
401  }
402  }
403  }
404 
405  /* If all variants of the glyph are the same, no point in having a gvar */
406  /* entry for it */
407  for ( i=0 ; i<mm->instance_count; ++i ) {
408  for ( j=0; j<ptcnt; ++j )
409  if ( deltas[i][j]!=0 )
410  break;
411  if ( j!=ptcnt )
412  break;
413  }
414  if ( i==mm->instance_count ) {
415  /* All zeros */
416  for ( i=0 ; i<mm->instance_count; ++i )
417  free(deltas[i]);
418  free(deltas);
419 return( NULL );
420  }
421 
422 return( deltas );
423 }
424 
425 int16 **CvtFindDeltas(MMSet *mm, int *_ptcnt) {
426  int i, j, k, l, cnt, ptcnt;
427  int16 **deltas;
428  struct ttf_table *cvt, *icvt;
429  for ( cvt = mm->normal->ttf_tables; cvt!=NULL && cvt->tag!=CHR('c','v','t',' '); cvt=cvt->next );
430 
431  if ( cvt==NULL )
432 return( NULL );
433 
434  icvt = NULL;
435  for ( i=0; i<mm->instance_count; ++i )
436  if ( (icvt=mm->instances[i]->ttf_tables)!=NULL )
437  break;
438  if ( icvt==NULL ) /* No other cvt tables => no variation */
439 return( NULL );
440 
441  *_ptcnt = ptcnt = cvt->len/2;
442  deltas = calloc(mm->instance_count,sizeof(int16 *));
443  for ( i=0; i<mm->instance_count; ++i ) if ( (icvt=mm->instances[i]->ttf_tables)!=NULL ) {
444  deltas[i] = calloc(ptcnt,sizeof(int16));
445  for ( j=0; j<ptcnt; ++j )
446  deltas[i][j] = memushort(icvt->data,icvt->len, sizeof(uint16)*j)-
447  memushort(cvt->data,cvt->len, sizeof(uint16)*j);
448  }
449 
450  /* Ok, each delta now contains the difference between the instance[i] points */
451  /* and the base points. But that isn't good enough. We must subtract */
452  /* [0,1] and [1,0] from [1,1], and then subtract [1,1,0] [1,0,1] [0,1,1] */
453  /* from [1,1,1] and so on (also [-1,0] from [-1,1], etc.) */
454  for ( j=1; j<mm->axis_count; ++j ) {
455  for ( i=0; i<mm->instance_count; ++i ) if ( deltas[i]!=NULL ) {
456  for ( k=cnt=0; k<mm->axis_count; ++k )
457  if ( mm->positions[i*mm->axis_count+k]!=0 )
458  ++cnt;
459  if ( cnt==j ) {
460  for ( l = 0; l<mm->instance_count; ++l ) if ( l!=i && deltas[l]!=NULL ) {
461  for ( k=0; k<mm->axis_count; ++k )
462  if ( mm->positions[i*mm->axis_count+k]!=0 &&
463  mm->positions[l*mm->axis_count+k]!=mm->positions[i*mm->axis_count+k])
464  break;
465  if ( k==mm->axis_count ) {
466  for ( k=0; k<ptcnt; ++k )
467  deltas[l][k] -= deltas[i][k];
468  }
469  }
470  }
471  }
472  }
473 
474  /* If all variants of the cvt are the same, no point in having a gvar */
475  /* entry for it */
476  for ( i=0 ; i<mm->instance_count; ++i ) if ( deltas[i]!=NULL ) {
477  for ( j=0; j<ptcnt; ++j )
478  if ( deltas[i][j]!=0 )
479  break;
480  if ( j==ptcnt ) {
481  free(deltas[i]);
482  deltas[i] = NULL;
483  }
484  }
485  for ( i=0 ; i<mm->instance_count; ++i )
486  if ( deltas[i]!=NULL )
487  break;
488  if ( i==mm->instance_count ) {
489  /* All zeros */
490  free(deltas);
491 return( NULL );
492  }
493 
494 return( deltas );
495 }
496 
497 static void ttf_dumpcvar(struct alltabs *at, MMSet *mm) {
498  int16 **deltas;
499  int ptcnt, cnt, pcnt;
500  int i,j,rj,big;
501  int tuple_size;
502  uint32 start, end;
503  uint16 *pts;
504 
505  deltas = CvtFindDeltas(mm,&ptcnt);
506  if ( deltas == NULL ) return;
507  for ( i=cnt=0; i<mm->instance_count; ++i )
508  if ( deltas[i]!=NULL )
509  ++cnt;
510  if ( cnt==0 ) {
511  free(deltas);
512 return;
513  }
514 
515  tuple_size = 4+2*mm->axis_count;
516  at->cvar = tmpfile2();
517  putlong( at->cvar, 0x00010000 ); /* Format */
518  putshort( at->cvar, cnt ); /* Number of instances with cvt tables (tuple count of interesting tuples) */
519  putshort( at->cvar, 8+cnt*tuple_size ); /* Offset to data */
520 
521  for ( i=0; i<mm->instance_count; ++i ) if ( deltas[i]!=NULL ) {
522  putshort( at->cvar, 0 ); /* tuple data size, figure out later */
523  putshort( at->cvar, 0xa000 ); /* tuple coords follow, private points in data */
524  for ( j=0; j<mm->axis_count; ++j )
525  putshort( at->cvar, rint(16384*mm->positions[i*mm->axis_count+j]) );
526  }
527  if ( ftell( at->cvar )!=8+cnt*tuple_size )
528  IError( "Data offset wrong" );
529 
530  for ( i=cnt=0; i<mm->instance_count; ++i ) if ( deltas[i]!=NULL ) {
531  start = ftell(at->cvar);
532  for ( j=pcnt=0; j<ptcnt; ++j )
533  if ( deltas[i][j]!=0 )
534  ++pcnt;
535  pts = malloc(pcnt*sizeof(uint16));
536  for ( j=pcnt=0; j<ptcnt; ++j )
537  if ( deltas[i][j]!=0 )
538  pts[pcnt++]=j;
539 
540  if ( pcnt>0x7f ) {
541  putc(0x80|(pcnt>>8), at->cvar );
542  putc(pcnt&0xff, at->cvar);
543  } else
544  putc(pcnt, at->cvar);
545  for ( j=0; j<pcnt; ) {
546  big = pts[j]>=0x80 ? 0x80 : 0;
547  for ( rj=j+1 ; rj<j+0x80 && rj<pcnt && !big; ++rj )
548  if ( pts[rj]-pts[rj-1]>=0x80 )
549  big = 0x80;
550 
551  putc((rj-j-1)|big,at->cvar);
552  if ( big ) {
553  putshort(at->cvar,pts[j]);
554  for ( ++j; j<rj; ++j )
555  putshort(at->cvar,pts[j]-pts[j-1]);
556  } else {
557  putc(pts[j],at->cvar);
558  for ( ++j; j<rj; ++j )
559  putc(pts[j]-pts[j-1],at->cvar);
560  }
561  }
562  /* Now output the corresponding deltas for those points */
563  for ( j=0; j<pcnt; ) {
564  if ( deltas[i][j]>0x7f || deltas[i][j]<0x80 ) {
565  for ( rj=j+1; rj<j+0x40 && rj<pcnt; ++rj ) {
566  if ( deltas[i][pts[rj]]>0x7f || deltas[i][pts[rj]]<0x80 ||
567  (rj+1<j+0x40 && rj+1<pcnt && (deltas[i][pts[rj+1]]>0x7f || deltas[i][pts[rj+1]]<0x80)) )
568  /* Keep going with a big run */;
569  else
570  break;
571  }
572  putc( (rj-j-1)|0x40,at->cvar );
573  for ( ; j<rj ; ++j )
574  putshort( at->cvar, deltas[i][pts[j]] );
575  } else {
576  for ( rj=j+1; rj<j+0x40 && rj<pcnt; ++rj ) {
577  if ( deltas[i][pts[rj]]>0x7f || deltas[i][pts[rj]]<0x80 )
578  break;
579  }
580  putc( rj-j-1,at->cvar );
581  for ( ; j<rj ; ++j )
582  putc( deltas[i][pts[j]], at->cvar );
583  }
584  }
585  free(pts);
586  end = ftell(at->cvar);
587  fseek(at->cvar, 8+cnt*tuple_size, SEEK_SET);
588  putshort(at->cvar,end-start);
589  fseek(at->cvar, end, SEEK_SET);
590  ++cnt;
591  }
592 
593  for ( i=0; i<mm->instance_count; ++i )
594  free( deltas[i] );
595  free(deltas);
596 
597  at->cvarlen = ftell(at->cvar);
598  if ( at->cvarlen&1 )
599  putc('\0',at->cvar );
600  if ( ftell(at->cvar)&2 )
601  putshort(at->cvar,0);
602 }
603 
604 static void dumpdeltas(struct alltabs *at,int16 *deltas,int ptcnt) {
605  int j,rj;
606 
607  for ( j=0; j<ptcnt; ) {
608  for ( rj=j; rj<ptcnt && rj<j+0x40 && deltas[rj]==0; ++rj );
609  if ( rj!=j ) {
610  putc((rj-j-1)|0x80,at->gvar);
611  j = rj;
612  continue;
613  }
614  if ( deltas[j]>0x7f || deltas[j]<0x80 ) {
615  for ( rj=j+1; rj<j+0x40 && rj<ptcnt; ++rj ) {
616  if ( deltas[rj]>0x7f || deltas[rj]<0x80 ||
617  (rj+1<j+0x40 && rj+1<ptcnt && (deltas[rj+1]>0x7f || deltas[rj+1]<0x80)) )
618  /* Keep going with a big run */;
619  else
620  break;
621  }
622  putc( (rj-j-1)|0x40,at->gvar );
623  for ( ; j<rj ; ++j )
624  putshort( at->gvar, deltas[j] );
625  } else {
626  for ( rj=j+1; rj<j+0x40 && rj<ptcnt; ++rj ) {
627  if ( deltas[rj]>0x7f || deltas[rj]<0x80 ||
628  (deltas[rj]==0 && rj+1<j+0x40 && rj+1<ptcnt &&
629  deltas[rj+1]<=0x7f && deltas[rj+1]>=0x80 && deltas[rj+1]!=0 ))
630  break;
631  }
632  putc( rj-j-1,at->gvar );
633  for ( ; j<rj ; ++j )
634  putc( deltas[j], at->gvar );
635  }
636  }
637 }
638 
639 static void ttf_dumpgvar(struct alltabs *at, MMSet *mm) {
640  int i,j, last;
641  uint32 gcoordoff, glyphoffs, start, here, tupledataend, tupledatastart;
642  int16 **deltas;
643  int ptcnt;
644 
645  at->gvar = tmpfile2();
646  putlong( at->gvar, 0x00010000 ); /* Format */
647  putshort( at->gvar, mm->axis_count );
648  putshort( at->gvar, mm->instance_count ); /* Number of global tuples */
649  gcoordoff = ftell(at->gvar);
650  putlong( at->gvar, 0 ); /* Offset to global tuples, fix later */
651  putshort( at->gvar,at->maxp.numGlyphs );
652  putshort( at->gvar, 1 ); /* always output 32bit offsets */
653  putlong( at->gvar, ftell(at->gvar)+4 + (at->maxp.numGlyphs+1)*4);
654  glyphoffs = ftell(at->gvar);
655  for ( i=0; i<=at->maxp.numGlyphs; ++i )
656  putlong( at->gvar,0 );
657 
658  start = ftell( at->gvar );
659  last = -1;
660  for ( i=0; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
661  deltas = SCFindDeltas(mm,at->gi.bygid[i],&ptcnt);
662  if ( deltas==NULL )
663  continue;
664  here = ftell(at->gvar);
665  fseek(at->gvar,glyphoffs+(last+1)*4,SEEK_SET);
666  for ( ; last< i; ++last )
667  putlong(at->gvar,here-start);
668  fseek(at->gvar,here,SEEK_SET);
669  putshort(at->gvar,mm->instance_count);
670  putshort(at->gvar,4+4*mm->instance_count); /* offset to data */
671  for ( j=0; j<mm->instance_count; ++j ) {
672  putshort(at->gvar,0); /* tuple data size, fix later */
673  putshort(at->gvar,0x2000|j); /* private points, tuple i */
674  }
675  for ( j=0; j<mm->instance_count; ++j ) {
676  tupledatastart = ftell(at->gvar);
677  putc('\0',at->gvar); /* Point list, all points */
678  dumpdeltas(at,deltas[2*j],ptcnt);
679  dumpdeltas(at,deltas[2*j+1],ptcnt);
680  tupledataend = ftell(at->gvar);
681  fseek(at->gvar,here+4+4*j,SEEK_SET);
682  putshort( at->gvar,tupledataend-tupledatastart);
683  fseek(at->gvar,tupledataend,SEEK_SET);
684  free(deltas[2*j]); free(deltas[2*j+1]);
685  }
686  free(deltas);
687  }
688  here = ftell(at->gvar);
689  fseek(at->gvar,glyphoffs+(last+1)*4,SEEK_SET);
690  for ( ; last< at->maxp.numGlyphs; ++last )
691  putlong(at->gvar,here-start);
692  fseek(at->gvar,gcoordoff,SEEK_SET);
693  putlong(at->gvar,here);
694  fseek(at->gvar,here,SEEK_SET);
695  for ( j=0; j<mm->instance_count; ++j ) {
696  for ( i=0; i<mm->axis_count; ++i )
697  putshort(at->gvar,rint(16384*mm->positions[j*mm->axis_count+i]));
698  }
699 
700  at->gvarlen = ftell(at->gvar);
701  if ( at->gvarlen&1 )
702  putc('\0',at->gvar );
703  if ( ftell(at->gvar)&2 )
704  putshort(at->gvar,0);
705 }
706 
707 
708 static void ttf_dumpavar(struct alltabs *at, MMSet *mm) {
709  int i,j;
710 
711  for ( i=0; i<mm->axis_count; ++i ) {
712  if ( mm->axismaps[i].points>3 )
713  break;
714  }
715  if ( i==mm->axis_count ) /* We only have simple axes */
716 return; /* No need for a variation table */
717 
718  at->avar = tmpfile2();
719  putlong( at->avar, 0x00010000 ); /* Format */
720  putlong( at->avar, mm->axis_count );
721  for ( i=0; i<mm->axis_count; ++i ) {
722  putshort( at->avar, mm->axismaps[i].points );
723  for ( j=0; j<mm->axismaps[i].points; ++j ) {
724  if ( mm->axismaps[i].designs[j]<mm->axismaps[i].def )
725  putshort( at->avar, (mm->axismaps[i].designs[j]-mm->axismaps[i].def)*16384/
726  (mm->axismaps[i].def-mm->axismaps[i].min));
727  else
728  putshort( at->avar, (mm->axismaps[i].designs[j]-mm->axismaps[i].def)*16384/
729  (mm->axismaps[i].max-mm->axismaps[i].def));
730  putshort( at->avar, mm->axismaps[i].blends[j]*16384);
731  }
732  }
733 
734  at->avarlen = ftell(at->avar);
735  if ( at->avarlen&2 )
736  putshort(at->avar,0);
737 }
738 
739 static uint32 AxisNameToTag(char *name) {
740  char buf[4];
741  int i;
742 
743  if ( strmatch(name,"Weight")==0 )
744 return( CHR('w','g','h','t'));
745  if ( strmatch(name,"Width")==0 )
746 return( CHR('w','d','t','h'));
747  if ( strmatch(name,"OpticalSize")==0 )
748 return( CHR('o','p','s','z'));
749  if ( strmatch(name,"Slant")==0 )
750 return( CHR('s','l','n','t'));
751 
752  memset(buf,0,sizeof(buf));
753  for ( i=0; i<4 && name[i]!='\0'; ++i )
754  buf[i] = name[i];
755 return( CHR(buf[0],buf[1],buf[2],buf[3]));
756 }
757 
758 static int AllocateStrId(struct alltabs *at,struct macname *mn) {
759  struct other_names *on;
760 
761  if ( mn==NULL )
762 return( 0 );
763 
764  on = chunkalloc(sizeof(struct other_names));
765  on->strid = at->next_strid++;
766  on->mn = mn;
767  on->next = at->other_names;
768  at->other_names = on;
769 return( on->strid );
770 }
771 
772 static void ttf_dumpfvar(struct alltabs *at, MMSet *mm) {
773  int i,j;
774 
775  at->fvar = tmpfile2();
776  putlong( at->fvar, 0x00010000 ); /* Format */
777  putshort( at->fvar, 16 ); /* Offset to first axis data */
778  putshort( at->fvar, 2 ); /* Size count pairs */
779  putshort( at->fvar, mm->axis_count );
780  putshort( at->fvar, 20 ); /* Size of each axis record */
781  putshort( at->fvar, mm->named_instance_count );
782  putshort( at->fvar, 4+4*mm->axis_count );
783 
784  /* For each axis ... */
785  for ( i=0; i<mm->axis_count; ++i ) {
786  putlong( at->fvar, AxisNameToTag(mm->axes[i]) );
787  putlong( at->fvar, rint(mm->axismaps[i].min*65536));
788  putlong( at->fvar, rint(mm->axismaps[i].def*65536));
789  putlong( at->fvar, rint(mm->axismaps[i].max*65536));
790  putshort(at->fvar, 0 ); /* No flags defined for axes */
791  putshort(at->fvar, AllocateStrId(at,mm->axismaps[i].axisnames));
792  }
793 
794  /* For each named font ... */
795  for ( i=0; i<mm->named_instance_count; ++i ) {
797  putshort(at->fvar, 0 ); /* No flags here either */
798  for ( j=0; j<mm->axis_count; ++j )
799  putlong(at->fvar, rint(65536*mm->named_instances[i].coords[j]));
800  }
801 
802  at->fvarlen = ftell(at->fvar);
803  if ( at->fvarlen&2 ) /* I don't think this is ever hit */
804  putshort(at->fvar,0);
805 }
806 
808  MMSet *mm = sf->mm;
809  int i,j;
810 
811  for ( j=0; j<sf->glyphcnt; ++j ) if ( sf->glyphs[j]!=NULL ) {
812  for ( i=0; i<mm->instance_count; ++i ) if ( mm->instances[i]->glyphs[j]!=NULL )
813  mm->instances[i]->glyphs[j]->ttf_glyph = sf->glyphs[j]->ttf_glyph;
814  }
815 
816  ttf_dumpfvar(at,mm);
817  ttf_dumpgvar(at,mm);
818  ttf_dumpcvar(at,mm);
819  ttf_dumpavar(at,mm);
820 }
double __cdecl rint(double _X)
static bool strmatch(char *str, char *txt, UInt32 len)
Definition: Compiler.cpp:322
#define sc
Definition: aptex-macros.h:57
#define name
#define next(a)
Definition: aptex-macros.h:924
static uint32_t cvt(uint32_t val)
#define free(a)
Definition: decNumber.cpp:310
#define fseek
Definition: xxstdio.h:30
#define ftell
Definition: xxstdio.h:31
#define putlong
Definition: dvips.h:265
FILE * tmpfile2()
Definition: tmpfile2.cpp:51
#define sp1
#define r1
#define r2
#define c(n)
Definition: gpos-common.c:150
static void putshort(int w)
Definition: gsftopk.c:1904
int deltas[13]
Definition: gsftopk.c:1503
#define putc
Definition: jbib.h:20
#define SEEK_SET
Definition: jmemansi.c:26
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p scientific i
Definition: afcover.h:80
voidp calloc()
#define buf
static int ret
Definition: convert.c:72
#define malloc
Definition: alloca.c:91
unsigned short uint16
Definition: tiff.h:62
short int16
Definition: tiff.h:61
unsigned long uint32
Definition: tiff.h:68
@ other
Definition: mtxline.h:22
int k
Definition: otp-parser.c:70
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
static int cnt
Definition: pkout.c:166
static int32_t last
Definition: ppagelist.c:29
static int32_t first
Definition: ppagelist.c:29
int r
Definition: ppmqvga.c:68
bstring c int memset(void *s, int c, int length)
le_int32 fixed
Definition: sfnt.h:144
int memushort(uint8 *data, int len, int offset)
Definition: parsettfatt.c:29
int SSTtfNumberPoints(SplineSet *ss)
Definition: splinechar.c:149
int RealNear(float a, float b)
Definition: splineutil2.c:112
@ ly_fore
Definition: splinefont.h:1209
#define chunkalloc(size)
Definition: splinefont.h:1947
#define IError
Definition: uiinterface.h:124
#define SCWorthOutputting(a)
Definition: splinefont.h:2357
Definition: ttf.h:566
struct maxp maxp
Definition: ttf.h:571
struct glyphinfo gi
Definition: ttf.h:682
FILE * cvar
Definition: ttf.h:657
int cvarlen
Definition: ttf.h:658
int fvarlen
Definition: ttf.h:656
int gvarlen
Definition: ttf.h:654
FILE * gvar
Definition: ttf.h:653
struct other_names * other_names
Definition: ttf.h:688
FILE * avar
Definition: ttf.h:659
FILE * fvar
Definition: ttf.h:655
int avarlen
Definition: ttf.h:660
int next_strid
Definition: ttf.h:685
float x
Definition: splinefont.h:70
float y
Definition: splinefont.h:71
Definition: dep.h:55
struct dep * next
Definition: dep.h:56
int gcnt
Definition: ttf.h:544
const int * bygid
Definition: splinesave.c:128
Definition: sh5.c:97
RefChar * refs
Definition: splinefont.h:1202
SplinePointList * splines
Definition: splinefont.h:1201
uint16 numGlyphs
Definition: ttf.h:415
double * designs
Definition: splinefont.h:1677
double * blends
Definition: splinefont.h:1676
SplineFont * normal
Definition: splinefont.h:1858
int axis_count
Definition: splinefont.h:1854
struct axismap * axismaps
Definition: splinefont.h:1862
int instance_count
Definition: splinefont.h:1856
unsigned int apple
Definition: splinefont.h:1867
float * positions
Definition: splinefont.h:1859
int named_instance_count
Definition: splinefont.h:1864
SplineFont ** instances
Definition: splinefont.h:1857
struct named_instance * named_instances
Definition: splinefont.h:1865
char * axes[4]
Definition: splinefont.h:1855
float * coords
Definition: splinefont.h:1843
struct macname * names
Definition: splinefont.h:1844
int strid
Definition: ttf.h:561
struct other_names * next
Definition: ttf.h:563
struct macname * mn
Definition: ttf.h:562
Definition: tfmaux.c:31
SplinePoint * to
Definition: splinefont.h:1038
int16 width
Definition: splinefont.h:1329
int16 vwidth
Definition: splinefont.h:1329
Layer * layers
Definition: splinefont.h:1337
struct ttf_table * ttf_tables
Definition: splinefont.h:1750
SplineChar ** glyphs
Definition: splinefont.h:1690
BasePoint me
Definition: splinefont.h:953
struct spline * next
Definition: splinefont.h:979
uint16 ttfindex
Definition: splinefont.h:974
unsigned int nonextcp
Definition: splinefont.h:956
BasePoint nextcp
Definition: splinefont.h:954
BasePoint prevcp
Definition: splinefont.h:955
uint16 nextcpindex
Definition: splinefont.h:978
struct splinepointlist * next
Definition: splinefont.h:1073
SplinePoint * first
Definition: splinefont.h:1072
uint32 len
Definition: splinefont.h:1644
uint8 * data
Definition: splinefont.h:1645
#define CHR(x)
Definition: sysdep.h:200
int j
Definition: t4ht.c:1589
#define sp
Definition: stack.c:11
static int AllocateStrId(struct alltabs *at, struct macname *mn)
Definition: tottfvar.c:758
static void ttf_dumpcvar(struct alltabs *at, MMSet *mm)
Definition: tottfvar.c:497
static int MatchPoints(SplineFont *sffixed, SplineFont *sfother, int gid)
Definition: tottfvar.c:176
static int SCPointCount(SplineChar *sc)
Definition: tottfvar.c:313
static void ttf_dumpfvar(struct alltabs *at, MMSet *mm)
Definition: tottfvar.c:772
static int AssignPtNumbers(MMSet *mm, int gid)
Definition: tottfvar.c:46
static int PtNumbersAreSet(SplineChar *sc)
Definition: tottfvar.c:31
static uint32 AxisNameToTag(char *name)
Definition: tottfvar.c:739
static void ttf_dumpavar(struct alltabs *at, MMSet *mm)
Definition: tottfvar.c:708
static void ttf_dumpgvar(struct alltabs *at, MMSet *mm)
Definition: tottfvar.c:639
static void dumpdeltas(struct alltabs *at, int16 *deltas, int ptcnt)
Definition: tottfvar.c:604
int16 ** CvtFindDeltas(MMSet *mm, int *_ptcnt)
Definition: tottfvar.c:425
void ttf_dumpvariations(struct alltabs *at, SplineFont *sf)
Definition: tottfvar.c:807
int16 ** SCFindDeltas(MMSet *mm, int gid, int *_ptcnt)
Definition: tottfvar.c:323
int ContourPtNumMatch(MMSet *mm, int gid)
Definition: tottfvar.c:243
@ start
Definition: preamble.c:52
#define end(cp)
Definition: zic.c:71