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)  

splinefont.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 
28 #include "fontforgevw.h"
29 
30 /* Use URW 4 letter abbreviations */
31 const char *knownweights[] = { "Demi", "Bold", "Regu", "Medi", "Book", "Thin",
32  "Ligh", "Heav", "Blac", "Ultr", "Nord", "Norm", "Gras", "Stan", "Halb",
33  "Fett", "Mage", "Mitt", "Buch", NULL };
34 const char *realweights[] = { "Demi", "Bold", "Regular", "Medium", "Book", "Thin",
35  "Light", "Heavy", "Black", "Ultra", "Nord", "Normal", "Gras", "Standard", "Halbfett",
36  "Fett", "Mager", "Mittel", "Buchschrift", NULL};
37 
38 static const char *modifierlist[] = { "Ital", "Obli", "Kursive", "Cursive", "Slanted",
39  "Expa", "Cond", NULL };
40 static const char *modifierlistfull[] = { "Italic", "Oblique", "Kursive", "Cursive", "Slanted",
41  "Expanded", "Condensed", NULL };
42 static const char **mods[] = { knownweights, modifierlist, NULL };
43 static const char **fullmods[] = { realweights, modifierlistfull, NULL };
44 
45 const char *_GetModifiers(const char *fontname, const char *familyname, const char *weight) {
46  const char *pt, *fpt;
47  static char space[20];
48  int i, j;
49 
50  /* URW fontnames don't match the familyname */
51  /* "NimbusSanL-Regu" vs "Nimbus Sans L" (note "San" vs "Sans") */
52  /* so look for a '-' if there is one and use that as the break point... */
53 
54  if ( (fpt=strchr(fontname,'-'))!=NULL ) {
55  ++fpt;
56  if ( *fpt=='\0' )
57  fpt = NULL;
58  } else if ( familyname!=NULL ) {
59  for ( pt = fontname, fpt=familyname; *fpt!='\0' && *pt!='\0'; ) {
60  if ( *fpt == *pt ) {
61  ++fpt; ++pt;
62  } else if ( *fpt==' ' )
63  ++fpt;
64  else if ( *pt==' ' )
65  ++pt;
66  else if ( *fpt=='a' || *fpt=='e' || *fpt=='i' || *fpt=='o' || *fpt=='u' )
67  ++fpt; /* allow vowels to be omitted from family when in fontname */
68  else
69  break;
70  }
71  if ( *fpt=='\0' && *pt!='\0' )
72  fpt = pt;
73  else
74  fpt = NULL;
75  }
76 
77  if ( fpt == NULL ) {
78  for ( i=0; mods[i]!=NULL; ++i ) for ( j=0; mods[i][j]!=NULL; ++j ) {
79  pt = strstr(fontname,mods[i][j]);
80  if ( pt!=NULL && (fpt==NULL || pt<fpt))
81  fpt = pt;
82  }
83  }
84  if ( fpt!=NULL ) {
85  for ( i=0; mods[i]!=NULL; ++i ) for ( j=0; mods[i][j]!=NULL; ++j ) {
86  if ( strcmp(fpt,mods[i][j])==0 ) {
87  strncpy(space,fullmods[i][j],sizeof(space)-1);
88 return(space);
89  }
90  }
91  if ( strcmp(fpt,"BoldItal")==0 )
92 return( "BoldItalic" );
93  else if ( strcmp(fpt,"BoldObli")==0 )
94 return( "BoldOblique" );
95 
96 return( fpt );
97  }
98 
99 return( weight==NULL || *weight=='\0' ? "Regular": weight );
100 }
101 
102 const char *SFGetModifiers(const SplineFont *sf) {
103 return( _GetModifiers(sf->fontname,sf->familyname,sf->weight));
104 }
105 
107 
108 static bigreal SPLMaxHeight(SplineSet *spl, enum flatness *isflat) {
109  enum flatness f = mt_unknown;
110  bigreal max = -1.0e23;
111  Spline *s, *first;
112  extended ts[2];
113  int i;
114 
115  for ( ; spl!=NULL; spl=spl->next ) {
116  first = NULL;
117  for ( s = spl->first->next; s!=first && s!=NULL; s=s->to->next ) {
118  if ( first==NULL ) first = s;
119  if ( s->from->me.y >= max ||
120  s->to->me.y >= max ||
121  s->from->nextcp.y > max ||
122  s->to->prevcp.y > max ) {
123  if ( !s->knownlinear ) {
124  if ( s->from->me.y > max ) {
125  f = mt_round;
126  max = s->from->me.y;
127  }
128  if ( s->to->me.y > max ) {
129  f = mt_round;
130  max = s->to->me.y;
131  }
132  SplineFindExtrema(&s->splines[1],&ts[0],&ts[1]);
133  for ( i=0; i<2; ++i ) if ( ts[i]!=-1 ) {
134  bigreal y = ((s->splines[1].a*ts[i]+s->splines[1].b)*ts[i]+s->splines[1].c)*ts[i]+s->splines[1].d;
135  if ( y>max ) {
136  f = mt_round;
137  max = y;
138  }
139  }
140  } else if ( s->from->me.y == s->to->me.y ) {
141  if ( s->from->me.y >= max ) {
142  max = s->from->me.y;
143  f = mt_flat;
144  }
145  } else {
146  if ( s->from->me.y > max ) {
147  f = mt_pointy;
148  max = s->from->me.y;
149  }
150  if ( s->to->me.y > max ) {
151  f = mt_pointy;
152  max = s->to->me.y;
153  }
154  }
155  }
156  }
157  }
158  *isflat = f;
159 return( max );
160 }
161 
162 static bigreal SCMaxHeight(SplineChar *sc, int layer, enum flatness *isflat) {
163  /* Find the max height of this layer of the glyph. Also find whether that */
164  /* max is flat (as in "z", curved as in "o" or pointy as in "A") */
165  enum flatness f = mt_unknown, curf;
166  bigreal max = -1.0e23, test;
167  RefChar *r;
168 
169  max = SPLMaxHeight(sc->layers[layer].splines,&curf);
170  f = curf;
171  for ( r = sc->layers[layer].refs; r!=NULL; r=r->next ) {
172  test = SPLMaxHeight(r->layers[0].splines,&curf);
173  if ( test>max || (test==max && curf==mt_flat)) {
174  max = test;
175  f = curf;
176  }
177  }
178  *isflat = f;
179 return( max );
180 }
181 
182 static bigreal SPLMinHeight(SplineSet *spl, enum flatness *isflat) {
183  enum flatness f = mt_unknown;
184  bigreal min = 1.0e23;
185  Spline *s, *first;
186  extended ts[2];
187  int i;
188 
189  for ( ; spl!=NULL; spl=spl->next ) {
190  first = NULL;
191  for ( s = spl->first->next; s!=first && s!=NULL; s=s->to->next ) {
192  if ( first==NULL ) first = s;
193  if ( s->from->me.y <= min ||
194  s->to->me.y <= min ||
195  s->from->nextcp.y < min ||
196  s->to->prevcp.y < min ) {
197  if ( !s->knownlinear ) {
198  if ( s->from->me.y < min ) {
199  f = mt_round;
200  min = s->from->me.y;
201  }
202  if ( s->to->me.y < min ) {
203  f = mt_round;
204  min = s->to->me.y;
205  }
206  SplineFindExtrema(&s->splines[1],&ts[0],&ts[1]);
207  for ( i=0; i<2; ++i ) if ( ts[i]!=-1 ) {
208  bigreal y = ((s->splines[1].a*ts[i]+s->splines[1].b)*ts[i]+s->splines[1].c)*ts[i]+s->splines[1].d;
209  if ( y<min ) {
210  f = mt_round;
211  min = y;
212  }
213  }
214  } else if ( s->from->me.y == s->to->me.y ) {
215  if ( s->from->me.y <= min ) {
216  min = s->from->me.y;
217  f = mt_flat;
218  }
219  } else {
220  if ( s->from->me.y < min ) {
221  f = mt_pointy;
222  min = s->from->me.y;
223  }
224  if ( s->to->me.y < min ) {
225  f = mt_pointy;
226  min = s->to->me.y;
227  }
228  }
229  }
230  }
231  }
232  *isflat = f;
233 return( min );
234 }
235 
236 static bigreal SCMinHeight(SplineChar *sc, int layer, enum flatness *isflat) {
237  /* Find the min height of this layer of the glyph. Also find whether that */
238  /* min is flat (as in "z", curved as in "o" or pointy as in "A") */
239  enum flatness f = mt_unknown, curf;
240  bigreal min = 1.0e23, test;
241  RefChar *r;
242 
243  min = SPLMinHeight(sc->layers[layer].splines,&curf);
244  f = curf;
245  for ( r = sc->layers[layer].refs; r!=NULL; r=r->next ) {
246  test = SPLMinHeight(r->layers[0].splines,&curf);
247  if ( test<min || (test==min && curf==mt_flat)) {
248  min = test;
249  f = curf;
250  }
251  }
252  *isflat = f;
253 return( min );
254 }
255 
256 #define RANGE 0x40ffffff
257 
258 struct dimcnt { bigreal pos; int cnt; };
259 
260 static int dclist_insert( struct dimcnt *arr, int cnt, bigreal val ) {
261  int i;
262 
263  for ( i=0; i<cnt; ++i ) {
264  if ( arr[i].pos == val ) {
265  ++arr[i].cnt;
266 return( cnt );
267  }
268  }
269  arr[i].pos = val;
270  arr[i].cnt = 1;
271 return( i+1 );
272 }
273 
274 static bigreal SFStandardHeight(SplineFont *sf, int layer, int do_max, unichar_t *list) {
275  struct dimcnt flats[200], curves[200];
276  bigreal test;
277  enum flatness curf;
278  int fcnt=0, ccnt=0, cnt, tot, i, useit;
279  unichar_t ch, top;
280  bigreal result, bestheight, bestdiff, diff, val;
281  char *blues, *end;
282 
283  while ( *list ) {
284  ch = top = *list;
285  if ( list[1]==RANGE && list[2]!=0 ) {
286  list += 2;
287  top = *list;
288  }
289  for ( ; ch<=top; ++ch ) {
291  if ( sc!=NULL ) {
292  if ( do_max )
293  test = SCMaxHeight(sc, layer, &curf );
294  else
295  test = SCMinHeight(sc, layer, &curf );
296  if ( curf==mt_flat )
298  else if ( curf!=mt_unknown )
299  ccnt = dclist_insert(curves, ccnt, test);
300  }
301  }
302  ++list;
303  }
304 
305  /* All flat surfaces at tops of glyphs are at the same level */
306  if ( fcnt==1 )
307  result = flats[0].pos;
308  else if ( fcnt>1 ) {
309  cnt = 0;
310  for ( i=0; i<fcnt; ++i ) {
311  if ( flats[i].cnt>cnt )
312  cnt = flats[i].cnt;
313  }
314  test = 0;
315  tot = 0;
316  /* find the mode. If multiple values have the same high count, average them */
317  for ( i=0; i<fcnt; ++i ) {
318  if ( flats[i].cnt==cnt ) {
319  test += flats[i].pos;
320  ++tot;
321  }
322  }
323  result = test/tot;
324  } else if ( ccnt==0 )
325 return( do_max ? -1e23 : 1e23 ); /* We didn't find any glyphs */
326  else {
327  /* Italic fonts will often have no flat surfaces for x-height just wavies */
328  test = 0;
329  tot = 0;
330  /* find the mean */
331  for ( i=0; i<ccnt; ++i ) {
332  test += curves[i].pos;
333  ++tot;
334  }
335  result = test/tot;
336  }
337 
338  /* Do we have a BlueValues entry? */
339  /* If so, snap height to the closest alignment zone (bottom of the zone) */
340  if ( sf->private!=NULL && (blues = PSDictHasEntry(sf->private,do_max ? "BlueValues" : "OtherBlues"))!=NULL ) {
341  while ( *blues==' ' || *blues=='[' ) ++blues;
342  /* Must get at least this close, else we'll just use what we found */
343  bestheight = result; bestdiff = (sf->ascent+sf->descent)/100.0;
344  useit = true;
345  while ( *blues!='\0' && *blues!=']' ) {
346  val = strtod(blues,&end);
347  if ( blues==end )
348  break;
349  blues = end;
350  while ( *blues==' ' ) ++blues;
351  if ( useit ) {
352  if ( (diff = val-result)<0 ) diff = -diff;
353  if ( diff<bestdiff ) {
354  bestheight = val;
355  bestdiff = diff;
356  }
357  }
358  useit = !useit; /* Only interested in every other BV entry */
359  }
360  result = bestheight;
361  }
362 return( result );
363 }
364 
365 static unichar_t capheight_str[] = { 'A', RANGE, 'Z',
366  0x391, RANGE, 0x3a9,
367  0x402, 0x404, 0x405, 0x406, 0x408, RANGE, 0x40b, 0x40f, RANGE, 0x418, 0x41a, 0x42f,
368  0 };
369 static unichar_t xheight_str[] = { 'a', 'c', 'e', 'g', 'm', 'n', 'o', 'p', 'q', 'r', 's', 'u', 'v', 'w', 'x', 'y', 'z', 0x131,
370  0x3b3, 0x3b9, 0x3ba, 0x3bc, 0x3bd, 0x3c0, 0x3c3, 0x3c4, 0x3c5, 0x3c7, 0x3c8, 0x3c9,
371  0x432, 0x433, 0x438, 0x43a, RANGE, 0x43f, 0x442, 0x443, 0x445, 0x44c,0x44f, 0x459, 0x45a,
372  0 };
373 
374 bigreal SFCapHeight(SplineFont *sf, int layer, int return_error) {
376 
377  if ( result==-1e23 && !return_error )
378  result = (8*sf->ascent)/10;
379 return( result );
380 }
381 
382 bigreal SFXHeight(SplineFont *sf, int layer, int return_error) {
384 
385  if ( result==-1e23 && !return_error )
386  result = (6*sf->ascent)/10;
387 return( result );
388 }
389 
391 {
392  Spline *spline=0;
393  Spline *first=0;
394  Spline *next=0;
395 
396  if ( splfirst!=NULL )
397  {
398  first = NULL;
399  for ( spline = splfirst->next; spline!=NULL && spline!=first; spline = next )
400  {
401  next = spline->to->next;
402 
403  // callback
404  f( splfirst, spline, udata );
405 
406  if ( first==NULL )
407  {
408  first = spline;
409  }
410  }
411  }
412 }
413 
415 {
416  int use_x;
417  int use_y;
420 
421  // outputs
422  int found;
425 
427 
428 static void SPLFirstVisitorFoundSoughtXY(SplinePoint* splfirst, Spline* spline, void* udata )
429 {
431  int found = 0;
432 
433  if( d->found )
434  return;
435 
436  // printf("SPLFirstVisitorFoundSoughtXY() %f %f %f\n", d->x, spline->from->me.x, spline->to->me.x );
437  if( d->use_x )
438  {
439  if( spline->from->me.x == d->x )
440  {
441  found = 1;
442  d->spline = spline;
443  d->sp = spline->from;
444  }
445 
446  if( spline->to->me.x == d->x )
447  {
448  found = 1;
449  d->spline = spline;
450  d->sp = spline->to;
451  }
452  }
453  if( d->use_x && found && d->use_y )
454  {
455  if( d->sp->me.y != d->y )
456  {
457  found = 0;
458  }
459  }
460  else if( d->use_y )
461  {
462  if( spline->from->me.y == d->y )
463  {
464  found = 1;
465  d->spline = spline;
466  d->sp = spline->from;
467  }
468 
469  if( spline->to->me.y == d->y )
470  {
471  found = 1;
472  d->spline = spline;
473  d->sp = spline->to;
474  }
475  }
476 
477  if( found )
478  {
479  d->found = found;
480  d->spline = spline;
481  }
482  else
483  {
484  d->sp = 0;
485  }
486 }
487 
489 {
490  SplinePointList *spl;
491  for ( spl = container; spl!=NULL; spl = spl->next )
492  {
494  d.use_x = 1;
495  d.use_y = 0;
496  d.x = x;
497  d.y = 0;
498  d.found = 0;
500  if( d.found )
501  return d.sp;
502  }
503  return 0;
504 }
double __cdecl strtod(char const *_String, char **_EndPtr)
const char * fontname
Definition: afm2pl.c:186
#define sc
Definition: aptex-macros.h:57
#define next(a)
Definition: aptex-macros.h:924
double real
Definition: dvips.h:66
char * strncpy()
int strcmp()
Definition: coll.cpp:143
mpz_t * f
Definition: gen-fib.c:34
#define s
Definition: afcover.h:80
#define d(n)
Definition: gpos-common.c:151
#define strchr
Definition: gsftopk.c:59
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p scientific i
Definition: afcover.h:80
static unsigned int fcnt
Definition: ftrandom.c:101
kerning y
Definition: ttdriver.c:212
int int double double double char double char * top
Definition: gdfx.h:19
char * strstr()
static struct blues_struct * blues
Definition: type1.c:217
#define test
Definition: tie.c:129
cell * list
Definition: list_routines.h:30
const int * pos
Definition: combiners.h:905
float x
Definition: cordic.py:15
#define min(a, b)
Definition: pbmplus.h:223
#define max(a, b)
Definition: pbmto4425.c:11
char * familyname
Definition: pbmtopk.c:65
static int cnt
Definition: pkout.c:166
static int32_t first
Definition: ppagelist.c:29
int r
Definition: ppmqvga.c:68
char * PSDictHasEntry(struct psdict *dict, const char *key)
Definition: dumppfa.c:36
SplineChar * SFGetChar(SplineFont *sf, int unienc, const char *name)
Definition: fvfonts.c:175
static const char ** mods[]
Definition: splinefont.c:42
const char * _GetModifiers(const char *fontname, const char *familyname, const char *weight)
Definition: splinefont.c:45
static void SPLFirstVisitorFoundSoughtXY(SplinePoint *splfirst, Spline *spline, void *udata)
Definition: splinefont.c:428
static const char ** fullmods[]
Definition: splinefont.c:43
static double SPLMinHeight(SplineSet *spl, enum flatness *isflat)
Definition: splinefont.c:182
struct SPLFirstVisitorFoundSoughtXYDataS SPLFirstVisitorFoundSoughtXYData
static double SCMaxHeight(SplineChar *sc, int layer, enum flatness *isflat)
Definition: splinefont.c:162
static const char * modifierlistfull[]
Definition: splinefont.c:40
SplinePoint * SplinePointListContainsPointAtX(SplinePointList *container, float x)
Definition: splinefont.c:488
const char * knownweights[]
Definition: splinefont.c:31
static const char * modifierlist[]
Definition: splinefont.c:38
double SFXHeight(SplineFont *sf, int layer, int return_error)
Definition: splinefont.c:382
static double SPLMaxHeight(SplineSet *spl, enum flatness *isflat)
Definition: splinefont.c:108
const char * realweights[]
Definition: splinefont.c:34
void SPLFirstVisitSplines(SplinePoint *splfirst, SPLFirstVisitSplinesVisitor f, void *udata)
Definition: splinefont.c:390
static unichar_t capheight_str[]
Definition: splinefont.c:365
static double SFStandardHeight(SplineFont *sf, int layer, int do_max, unichar_t *list)
Definition: splinefont.c:274
flatness
Definition: splinefont.c:106
@ mt_pointy
Definition: splinefont.c:106
@ mt_unknown
Definition: splinefont.c:106
@ mt_round
Definition: splinefont.c:106
@ mt_flat
Definition: splinefont.c:106
static double SCMinHeight(SplineChar *sc, int layer, enum flatness *isflat)
Definition: splinefont.c:236
#define RANGE
Definition: splinefont.c:256
const char * SFGetModifiers(const SplineFont *sf)
Definition: splinefont.c:102
double SFCapHeight(SplineFont *sf, int layer, int return_error)
Definition: splinefont.c:374
static int dclist_insert(struct dimcnt *arr, int cnt, double val)
Definition: splinefont.c:260
static unichar_t xheight_str[]
Definition: splinefont.c:369
#define extended
Definition: splinefont.h:52
void(* SPLFirstVisitSplinesVisitor)(SplinePoint *splfirst, Spline *s, void *udata)
Definition: splinefont.h:2492
#define bigreal
Definition: splinefont.h:49
void SplineFindExtrema(const Spline1D *sp, double *_t1, double *_t2)
Definition: splineutil.c:1668
uint32 unichar_t
Definition: basics.h:51
test
Definition: parser.c:257
float x
Definition: splinefont.h:70
float y
Definition: splinefont.h:71
double pos
Definition: splinefont.c:258
int cnt
Definition: splinefont.c:258
Definition: tfmaux.c:31
SplinePoint * to
Definition: splinefont.h:1038
SplinePoint * from
Definition: splinefont.h:1037
BasePoint me
Definition: splinefont.h:953
struct spline * next
Definition: splinefont.h:979
struct splinepointlist * next
Definition: splinefont.h:1073
SplinePoint * first
Definition: splinefont.h:1072
Definition: strexpr.c:21
ch
Definition: t4ht.c:1443
int j
Definition: t4ht.c:1589
val
Definition: tex4ht.c:3227
int diff
Definition: tex4ht.c:3815
found
Definition: tex4ht.c:5000
@ flats
Definition: preamble.c:51
PATTERN * pt
Definition: vlna.c:74
#define end(cp)
Definition: zic.c:71