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 #ifndef FONTFORGE_SPLINEFONT_H
29 #define FONTFORGE_SPLINEFONT_H
30 
31 #include "basics.h"
32 #include "dlist.h"
33 #include "gwwiconv.h"
34 #include "ustring.h"
35 
36 #include <locale.h>
37 
38 #ifndef _NO_LIBSPIRO
39 # include <spiroentrypoints.h>
40 #else
41 # define SPIRO_OPEN_CONTOUR	'{'
42 # define SPIRO_CORNER		'v'
43 # define SPIRO_G4		'o'
44 # define SPIRO_G2		'c'
45 # define SPIRO_LEFT		'['
46 # define SPIRO_RIGHT		']'
47 # define SPIRO_END		'z'
48 typedef struct {			/* Taken from spiro.h because I want */
49     double x;				/*  to be able to compile for spiro */
50     double y;				/*  even on a system without it */
51     char ty;
52 } spiro_cp;
53 #endif
54 
55 #ifdef FONTFORGE_CONFIG_USE_DOUBLE
56 # define real		double
57 # define bigreal	double
58 #else
59 # define real		float
60 # define bigreal	double
61 #endif
62 
63 #define extended	double
64 	/* Solaris wants to define extended to be unsigned [3] unless we do this*/
65 #define _EXTENDED
66 
67 #define CHR(ch1,ch2,ch3,ch4) (((ch1)<<24)|((ch2)<<16)|((ch3)<<8)|(ch4))
68 
69 #define MmMax		16	/* PS says at most this many instances for type1/2 mm fonts */
70 #define AppleMmMax	26	/* Apple sort of has a limit of 4095, but we only support this many */
71 
72 
73 /* The maximum number of layers allowed in a normal font (this includes the */
74 /*  default foreground and background layers) -- this does not limit type3  */
75 /*  fonts */
76 #define BACK_LAYER_MAX 256
77 
78 
79 typedef struct ipoint {
80     int x;
81     int y;
82 } IPoint;
83 
84 #define IPOINT_EMPTY { 0, 0 }
85 
86 
87 typedef struct basepoint {
88     real x;
89     real y;
90 } BasePoint;
91 
92 #define BASEPOINT_EMPTY { (real)0.0, (real)0.0 }
93 
94 
95 typedef struct dbasepoint {
96     bigreal x;
97     bigreal y;
98 } DBasePoint;
99 
100 #define DBASEPOINT_EMPTY { (bigreal)0.0, (bigreal)0.0 }
101 
102 
103 typedef struct dbounds {
104     real minx, maxx;
105     real miny, maxy;
106 } DBounds;
107 
108 #define DBOUNDS_EMPTY { (real)0.0, (real)0.0, (real)0.0, (real)0.0 }
109 
110 
111 typedef struct ibounds {
112     int minx, maxx;
113     int miny, maxy;
114 } IBounds;
115 
116 #define IBOUNDS_EMPTY { 0, 0, 0, 0 }
117 
118 
119 enum val_type { v_int, v_real, v_str, v_unicode, v_lval, v_arr, v_arrfree,
120 		v_void };
121 
122 enum val_flags {
123     vf_none = 0,
124     vf_dontfree = (1 << 1)
125 };
126 
127 typedef struct val {
128     enum val_type type;
129     enum val_flags flags;
130     union {
131 	int ival;
132 	real fval;
133 	char *sval;
134 	struct val *lval;
135 	struct array *aval;
136     } u;
137 } Val;		/* Used by scripting */
138 
139 struct psdict {
140     int cnt;		/* *key[0..cnt] and *values[0..cnt] currently available */
141     int next;		/* **key[0..next] and **values[0..next] currently used  */
142     char **keys;
143     char **values;
144 };
145 
146 struct pschars {
147     int cnt, next;
148     char **keys;
149     uint8 **values;
150     int *lens;
151     int bias;		/* for type2 strings */
152 };
153 
154 enum linejoin {
155     lj_miter,		/* Extend lines until they meet */
156     lj_round,		/* connect with arc (not w/ stroking - see "nib") */
157     lj_bevel,		/* Straight line between the ends of next and prev */
158     lj_miterclip,	/* Extend lines until they meet */
159     lj_nib,		/* Join with the nib shape */
160     lj_arcs,
161     lj_inherited
162 };
163 enum linecap {
164     lc_butt,		/* Finish with line perpendicular to end tangent */
165     lc_round,		/* semi-circle (not w/ stroking - see "nib") */
166     lc_square,		/* Not used w/ stroking - use lc_butt w/ extend */
167     lc_nib,		/* cap with the nib shape */
168     lc_bevel,		/* Just join endpoints with a line */
169     lc_inherited
170 };
171 enum stroke_rmov {
172     srmov_layer = 0,
173     srmov_contour = 1,
174     srmov_none = 2
175 };
176 enum stroke_arclimit {
177     sal_auto = 0,
178     sal_svg2 = 1,
179     sal_ratio = 2
180 };
181 enum spreadMethod {
182     sm_pad, sm_reflect, sm_repeat
183 };
184 
185 #define COLOR_INHERITED	0xfffffffe
186 
187 struct grad_stops {
188     real offset;
189     uint32 col;
190     real opacity;
191 };
192 
193 struct gradient {
194     BasePoint start;	/* focal of a radial gradient, start of a linear */
195     BasePoint stop;	/* center of a radial gradient, end of a linear */
196     real radius;	/* 0=>linear gradient, else radius of a radial gradient */
197     enum spreadMethod sm;
198     int stop_cnt;
199     struct grad_stops *grad_stops;
200 };
201 
202 struct pattern {
203     char *pattern;
204     real width, height;		/* Pattern is scaled to be repeated every width/height (in user coordinates) */
205     real transform[6];
206     /* Used during rasterization process */
207     struct bdfchar *pat;
208     real invtrans[6];
209     int bminx, bminy, bwidth, bheight;	/* of the pattern at bdfchar scale */
210 };
211 
212 struct brush {
213     uint32 col;
214     float opacity;		/* number between [0,1], only for svg/pdf */
215     struct pattern *pattern;	/* A pattern to be tiled */
216     struct gradient *gradient;	/* A gradient fill */
217 };
218 #define WIDTH_INHERITED	(-1)
219 #define DASH_INHERITED	255	/* if the dashes[0]==0 && dashes[1]==DASH_INHERITED */
220 #define DASH_MAX	8
221 typedef unsigned char DashType;
222 struct pen {
223     struct brush brush;
224     uint8 linejoin;
225     uint8 linecap;
226     float width;
227     real trans[4];
228     DashType dashes[DASH_MAX];
229 };
230 
231 #define JLIMIT_INHERITED (-1)
232 
233 struct spline;
234 enum si_type { si_round, si_calligraphic, si_nib, si_centerline };
235 /* If you change this structure you may need to update MakeStrokeDlg */
236 /*  and cvpalettes.c -- both contain statically initialized StrokeInfos */
237 typedef struct strokeinfo {
238     bigreal width;			/* or major axis of pen */
239     enum linejoin join;
240     enum linecap cap;
241     enum si_type stroke_type;
242     enum stroke_rmov rmov;
243     enum stroke_arclimit al;
244     // Could be bits but the python interface would be annoying
245     int removeinternal, removeexternal, simplify, extrema;
246     int leave_users_center, jlrelative, ecrelative;
247     bigreal penangle, height, extendcap, joinlimit, accuracy_target;
248     struct splinepointlist *nib;
249 /* For freehand tool, not currently used in practice */
250     real radius2;
251     int pressure1, pressure2;
252     void *data;
253     bigreal (*factor)(void *data,struct spline *spline,real t);
254 /* End freehand */
255 } StrokeInfo;
256 
257 extern StrokeInfo *InitializeStrokeInfo(StrokeInfo *sip);
258 extern void SITranslatePSArgs(StrokeInfo *sip, enum linejoin lj,
259                               enum linecap lc);
260 
261 enum overlap_type { over_remove, over_rmselected, over_intersect, over_intersel,
262 	over_exclude, over_findinter, over_fisel };
263 
264 enum simpify_flags { sf_cleanup=-1, sf_normal=0, sf_ignoreslopes=1,
265 	sf_ignoreextremum=2, sf_smoothcurves=4, sf_choosehv=8,
266 	sf_forcelines=0x10, sf_nearlyhvlines=0x20,
267 	sf_mergelines=0x40, sf_setstart2extremum=0x80,
268 	sf_rmsingletonpoints=0x100 };
269 struct simplifyinfo {
270     int flags;
271     bigreal err;
272     bigreal tan_bounds;
273     bigreal linefixup;
274     bigreal linelenmax;		/* Don't simplify any straight lines longer than this */
275     int set_as_default;
276     int check_selected_contours;
277 };
278 
279 struct hsquash { double lsb_percent, stem_percent, counter_percent, rsb_percent; };
280 
281 enum serif_type { srf_flat, srf_simpleslant, srf_complexslant };
282 /* |    | (flat)    |   | (simple)     |    | (complex) */
283 /* |    |           |  /               |   /            */
284 /* |    |           | /                |  /             */
285 /* +----+           |/                 \ /              */
286 
287 typedef struct italicinfo {
288     double italic_angle;
289     double xheight_percent;
290     struct hsquash lc, uc, neither;
291     enum serif_type secondary_serif;
292 
293     unsigned int transform_bottom_serifs: 1;
294     unsigned int transform_top_xh_serifs: 1;	/* Those at x-height */
295     unsigned int transform_top_as_serifs: 1;	/* Those at ascender-height */
296     unsigned int transform_diagon_serifs: 1;	/* Those at baseline/xheight */
297 
298     unsigned int a_from_d: 1;		/* replace the "a" glyph with the variant which looks like a "d" without an ascender */
299   /* When I say "f" I also mean "f_f" ligature, "longs", cyrillic phi and other things shaped like "f" */
300     unsigned int f_long_tail: 1;	/* Some Italic fonts have the "f" grow an extension of the main stem below the baseline */
301     unsigned int f_rotate_top: 1;	/* Most Italic fonts take the top curve of the "f", rotate it 180 and attach to the bottom */
302     unsigned int pq_deserif: 1;		/* Remove a serif from the descender of p or q and replace with a secondary serif as above */
303 
304   /* Unsupported */
305     /* e becomes rounder, cross bar slightly slanted */
306     /* g closed counter at bottom */
307     /* k closed counter at top */
308     /* v-z diagonal stems become more curvatious */
309 
310     unsigned int cyrl_phi: 1;		/* Gains an "f" like top, bottom treated like "f" */
311     unsigned int cyrl_i: 1;		/* Turns into a latin u */
312     unsigned int cyrl_pi: 1;		/* Turns into a latin n */
313     unsigned int cyrl_te: 1;		/* Turns into a latin m */
314     unsigned int cyrl_sha: 1;		/* Turns into a latin m rotated 180 */
315     unsigned int cyrl_dje: 1;		/* Turns into a latin smallcaps T */
316     unsigned int cyrl_dzhe: 1;		/* Turns into a latin u */
317 		    /* Is there a difference between dzhe and i? both look like u to me */
318 
319   /* Unsupported */
320     /* u432 curved B */
321     /* u433 strange gamma */
322     /* u434 normal delta */
323     /* u436 */
324     /* u43b lambda ? */
325     /* u43c */
326     /* u446 */
327     /* u449 */
328     /* u449 */
329     /* u44a */
330 
331 /* This half of the structure gets filled in later - see ITALICINFO_REMAINDER */
332     double tan_ia;
333     double x_height;
334     double pq_depth;
335     double ascender_height;
336     double emsize;
337     int order2;
338     struct splinefont *sf;
339     int layer;
340     double serif_extent, serif_height;
341     struct splinepoint *f_start, *f_end;		/* start has next pointing into the f head and up */
342     struct splinepoint *ff_start1, *ff_end1, *ff_start2, *ff_end2;
343     double f_height, ff_height;
344 } ItalicInfo;
345 
346 #define ITALICINFO_REMAINDER 0, 0, 0, 0, 0, 0, NULL, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0
347 
348 
349 typedef struct bluedata {
350     real xheight, xheighttop;		/* height of "x" and "o" (u,v,w,x,y,z) */
351     real caph, caphtop;			/* height of "I" and "O" */
352     real base, basebelow;		/* bottom of "I" and "O" */
353     real ascent;			/* height of "l" */
354     real descent;			/* depth of "p" */
355     real numh, numhtop;			/* height of "7" and "8" */ /* numbers with ascenders */
356     int bluecnt;			/* If the private dica contains bluevalues... */
357     real blues[12][2];			/* 7 pairs from bluevalues, 5 from otherblues */
358 } BlueData;
359 
360 #define BLUEDATA_EMPTY { \
361     0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, \
362     { { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 }, \
363       { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 }  \
364     } \
365 }
366 
367 
368 typedef struct bdffloat {
369     int16 xmin,xmax,ymin,ymax;
370     int16 bytes_per_line;
371     unsigned int byte_data:1;
372     uint8 depth;
373     uint8 *bitmap;
374 } BDFFloat;
375 
376 /* OpenType does not document 'dflt' as a language, but we'll use it anyway. */
377 /* (Adobe uses it too) we'll turn it into a default entry when we output it. */
378 #define DEFAULT_LANG		CHR('d','f','l','t')
379 /* The OpenType spec says in one place that the default script is 'dflt' and */
380 /*  in another that it is 'DFLT'. 'DFLT' is correct */
381 #define DEFAULT_SCRIPT		CHR('D','F','L','T')
382 #define REQUIRED_FEATURE	CHR(' ','R','Q','D')
383 
384 enum otlookup_type {
385     ot_undef = 0,			/* Not a lookup type */
386     gsub_start	       = 0x000,		/* Not a lookup type */
387     gsub_single        = 0x001,
388     gsub_multiple      = 0x002,
389     gsub_alternate     = 0x003,
390     gsub_ligature      = 0x004,
391     gsub_context       = 0x005,
392     gsub_contextchain  = 0x006,
393      /* GSUB extension 7 */
394     gsub_reversecchain = 0x008,
395     /* mac state machines */
396     morx_indic	       = 0x0fd,
397     morx_context       = 0x0fe,
398     morx_insert        = 0x0ff,
399     /* ********************* */
400     gpos_start         = 0x100,		/* Not a lookup type */
401 
402     gpos_single        = 0x101,
403     gpos_pair          = 0x102,
404     gpos_cursive       = 0x103,
405     gpos_mark2base     = 0x104,
406     gpos_mark2ligature = 0x105,
407     gpos_mark2mark     = 0x106,
408     gpos_context       = 0x107,
409     gpos_contextchain  = 0x108,
410     /* GPOS extension 9 */
411     kern_statemachine  = 0x1ff
412 
413     /* otlookup&0xff == lookup type for the appropriate table */
414     /* otlookup>>8:     0=>GSUB, 1=>GPOS */
415 };
416 
417 enum otlookup_typemasks {
418     gsub_single_mask        = 0x00001,
419     gsub_multiple_mask      = 0x00002,
420     gsub_alternate_mask     = 0x00004,
421     gsub_ligature_mask      = 0x00008,
422     gsub_context_mask       = 0x00010,
423     gsub_contextchain_mask  = 0x00020,
424     gsub_reversecchain_mask = 0x00040,
425     morx_indic_mask         = 0x00080,
426     morx_context_mask       = 0x00100,
427     morx_insert_mask        = 0x00200,
428     /* ********************* */
429     gpos_single_mask        = 0x00400,
430     gpos_pair_mask          = 0x00800,
431     gpos_cursive_mask       = 0x01000,
432     gpos_mark2base_mask     = 0x02000,
433     gpos_mark2ligature_mask = 0x04000,
434     gpos_mark2mark_mask     = 0x08000,
435     gpos_context_mask       = 0x10000,
436     gpos_contextchain_mask  = 0x20000,
437     kern_statemachine_mask  = 0x40000
438 };
439 
440 #define MAX_LANG 		4	/* If more than this we allocate more_langs in chunks of MAX_LANG */
441 struct scriptlanglist {
442     uint32 script;
443     uint32 langs[MAX_LANG];
444     uint32 *morelangs;
445     int lang_cnt;
446     struct scriptlanglist *next;
447 };
448 
449 extern struct opentype_feature_friendlynames {
450     uint32 tag;
451     char *tagstr;
452     char *friendlyname;
453     int masks;
454 } friendlies[];
455 
456 #define OPENTYPE_FEATURE_FRIENDLYNAMES_EMPTY { 0, NULL, NULL, 0 }
457 
458 
459 typedef struct featurescriptlanglist {
460     uint32 featuretag;
461     struct scriptlanglist *scripts;
462     struct featurescriptlanglist *next;
463     unsigned int ismac: 1;	/* treat the featuretag as a mac feature/setting */
464 } FeatureScriptLangList;
465 
466 enum pst_flags { pst_r2l=1, pst_ignorebaseglyphs=2, pst_ignoreligatures=4,
467 	pst_ignorecombiningmarks=8, pst_usemarkfilteringset=0x10,
468 	pst_markclass=0xff00, pst_markset=0xffff0000 };
469 
470 struct lookup_subtable {
471     char *subtable_name;
472     char *suffix;			/* for gsub_single, used to find a default replacement */
473     int16 separation, minkern;	/* for gpos_pair, used to guess default kerning values */
474     struct otlookup *lookup;
475     unsigned int unused: 1;
476     unsigned int per_glyph_pst_or_kern: 1;
477     unsigned int anchor_classes: 1;
478     unsigned int vertical_kerning: 1;
479     unsigned int ticked: 1;
480     unsigned int kerning_by_touch: 1;	/* for gpos_pair, calculate kerning so that glyphs will touch */
481     unsigned int onlyCloser: 1;		/* for kerning classes */
482     unsigned int dontautokern: 1;		/* for kerning classes */
483     struct kernclass *kc;
484     struct generic_fpst *fpst;
485     struct generic_asm  *sm;
486     /* Each time an item is added to a lookup we must place it into a */
487     /*  subtable. If it's a kerning class, fpst or state machine it has */
488     /*  a subtable all to itself. If it's an anchor class it can share */
489     /*  a subtable with other anchor classes (merge with). If it's a glyph */
490     /*  PST it may share a subtable with other PSTs */
491     /* Note items may only be placed in lookups in which they fit. Can't */
492     /*  put kerning data in a gpos_single lookup, etc. */
493     struct lookup_subtable *next;
494     int32 subtable_offset;
495     int32 *extra_subtables;
496     /* If a kerning subtable has too much stuff in it, we are prepared to */
497     /*  break it up into several smaller subtables, each of which has */
498     /*  an offset in this list (extra-subtables[0]==subtable_offset) */
499     /*  the list is terminated by an entry of -1 */
500 };
501 
502 typedef struct otlookup {
503     struct otlookup *next;
504     enum otlookup_type lookup_type;
505     uint32 lookup_flags;		/* Low order: traditional flags, High order: markset index, only meaningful if pst_usemarkfilteringset set */
506     char *lookup_name;
507     FeatureScriptLangList *features;
508     struct lookup_subtable *subtables;
509     unsigned int unused: 1;	/* No subtable is used (call SFFindUnusedLookups before examining) */
510     unsigned int empty: 1;	/* No subtable is used, and no anchor classes are used */
511     unsigned int store_in_afm: 1;	/* Used for ligatures, some get stored */
512     					/*  'liga' generally does, but 'frac' doesn't */
513     unsigned int needs_extension: 1;	/* Used during opentype generation */
514     unsigned int temporary_kern: 1;	/* Used when decomposing kerning classes into kern pairs for older formats */
515     unsigned int def_lang_checked: 1;
516     unsigned int def_lang_found: 1;
517     unsigned int ticked: 1;
518     unsigned int in_gpos: 1;
519     unsigned int in_jstf: 1;
520     unsigned int only_jstf: 1;
521     int16 subcnt;		/* Actual number of subtables we will output */
522 				/* Some of our subtables may contain no data */
523 			        /* Some may be too big and need to be broken up.*/
524 			        /* So this field may be different than just counting the subtables */
525     int lookup_index;		/* used during opentype generation */
526     uint32 lookup_offset;
527     uint32 lookup_length;
528     char *tempname;
529 } OTLookup;
530 
531 #define LOOKUP_SUBTABLE_EMPTY { NULL, NULL, 0, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, 0, NULL }
532 #define OTLOOKUP_EMPTY { NULL, 0, 0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }
533 
534 
535 typedef struct devicetab {
536     uint16 first_pixel_size, last_pixel_size;		/* A range of point sizes to which this table applies */
537     int8 *corrections;					/* a set of pixel corrections, one for each point size */
538 } DeviceTable;
539 
540 typedef struct valdev {		/* Value records can have four associated device tables */
541     DeviceTable xadjust;
542     DeviceTable yadjust;
543     DeviceTable xadv;
544     DeviceTable yadv;
545 } ValDevTab;
546 
547 enum anchorclass_type { act_mark, act_mkmk, act_curs, act_mklg, act_unknown };
548 typedef struct anchorclass {
549     char *name;			/* in utf8 */
550     struct lookup_subtable *subtable;
551     uint8 type;		/* anchorclass_type */
552     uint8 has_base;
553     uint8 processed, has_mark, matches, ac_num;
554     uint8 ticked;
555     struct anchorclass *next;
556 } AnchorClass;
557 
558 enum anchor_type { at_mark, at_basechar, at_baselig, at_basemark, at_centry, at_cexit, at_max };
559 typedef struct anchorpoint {
560     AnchorClass *anchor;
561     BasePoint me;
562     DeviceTable xadjust, yadjust;
563     unsigned int type: 4;
564     unsigned int selected: 1;
565     unsigned int ticked: 1;
566     unsigned int has_ttf_pt: 1;
567     uint16 ttf_pt_index;
568     int16  lig_index;
569     struct anchorpoint *next;
570 } AnchorPoint;
571 
572 typedef struct kernpair {
573     // Note that the left character in the pair has the reference to the kerning pair, which in turn references the right character.
574     struct lookup_subtable *subtable;
575     struct splinechar *sc;
576     int16 off;
577     uint16 kcid;			/* temporary value */
578     DeviceTable *adjust;		/* Only adjustment in one dimen, if more needed use pst */
579     struct kernpair *next;
580 } KernPair;
581 
582 #define FF_KERNCLASS_FLAG_NATIVE 2 // If set, the class goes into groups.plist or kerning.plist.
583 #define FF_KERNCLASS_FLAG_FEATURE 4 // If set, the class or rule goes into the feature file. In the present configuration, this ought to be zero always.
584 #define FF_KERNCLASS_FLAG_NAMETYPE 8 // If unset (default), the class has a standard name, which translates to a U. F. O. name starting in public.kern, which may be illegal in the feature file. If set, it has a name like @MMK_.
585 #define FF_KERNCLASS_FLAG_NAMELEGACY 16 // If set, the class has a U. F. O. name starting in @kc as FontForge liked to do in the past.
586 #define FF_KERNCLASS_FLAG_VIRTUAL 32 // If unset (default), the class is a real character class and does not conflict with same-sided classes. If set, FontForge mostly ignores the class except for U. F. O. input/output.
587 #define FF_KERNCLASS_FLAG_FLATTEN 64 // If unset (default), the class gets exported as a class. If set, it gets exported as its first member (in order to support class-character kerns).
588 #define FF_KERNCLASS_FLAG_SINGLECHAR (FF_KERNCLASS_FLAG_VIRTUAL | FF_KERNCLASS_FLAG_FLATTEN) // We expect to see these used together.
589 
590 typedef struct kernclass {
591     int first_cnt, second_cnt;		/* Count of classes for first and second chars */
592     char **firsts;			/* list of a space separated list of char names */
593     char **seconds;			/*  one entry for each class. Entry 0 is null */
594     					/*  and means everything not specified elsewhere */
595     char **firsts_names; // We need to track the names of the classes in order to round-trip U. F. O. data.
596     char **seconds_names;
597     int *firsts_flags; // This tracks the storage format of the class in U. F. O. (groups.plist or features.fea) and whether it's a single-character class.
598     int *seconds_flags; // We also track the name format (@MMK or public.kern).
599     struct lookup_subtable *subtable;
600     uint16 kcid;			/* Temporary value, used for many things briefly */
601     int16 *offsets;			/* array of first_cnt*second_cnt entries with 0 representing no data */
602     int *offsets_flags;
603     DeviceTable *adjusts;		/* array of first_cnt*second_cnt entries representing resolution-specific adjustments */
604     struct kernclass *next;		// Note that, in most cases, a typeface needs only one struct kernclass since it can contain all classes.
605     int feature; // This indicates whether the kerning class came from a feature file. This is important during export.
606 } KernClass;
607 
608 enum possub_type { pst_null, pst_position, pst_pair,
609 	pst_substitution, pst_alternate,
610 	pst_multiple, pst_ligature,
611 	pst_lcaret /* must be pst_max-1, see charinfo.c*/,
612 	pst_max,
613 	/* These are not psts but are related so it's handly to have values for them */
614 	pst_kerning = pst_max, pst_vkerning, pst_anchors,
615 	/* And these are fpsts */
616 	pst_contextpos, pst_contextsub, pst_chainpos, pst_chainsub,
617 	pst_reversesub, fpst_max,
618 	/* And these are used to specify a kerning pair where the current */
619 	/*  char is the final glyph rather than the initial one */
620 	/* A kludge used when cutting and pasting features */
621 	pst_kernback, pst_vkernback
622 	};
623 
624 struct vr {
625     int16 xoff, yoff, h_adv_off, v_adv_off;
626     ValDevTab *adjust;
627 };
628 
629 typedef struct generic_pst {
630     unsigned int ticked: 1;
631     unsigned int temporary: 1;		/* Used in afm ligature closure */
632     /* enum possub_type*/ uint8 type;
633     struct lookup_subtable *subtable;
634     struct generic_pst *next;
635     union {
636 	struct vr pos;
637 	struct { char *paired; struct vr *vr; } pair;
638 	struct { char *variant; } subs;
639 	struct { char *components; } mult, alt;
640 	struct { char *components; struct splinechar *lig; } lig;
641 	struct { int16 *carets; int cnt; } lcaret;	/* Ligature caret positions */
642     } u;
643 } PST;
644 
645 typedef struct liglist {
646     PST *lig;
647     struct splinechar *first;		/* First component */
648     struct splinecharlist *components;	/* Other than the first */
649     struct liglist *next;
650     int ccnt;				/* Component count. (includes first component) */
651 } LigList;
652 
653 enum fpossub_format { pst_glyphs, pst_class, pst_coverage,
654 		    pst_reversecoverage, pst_formatmax };
655 
656 struct seqlookup {
657     int seq;
658     struct otlookup *lookup;
659 };
660 
661 struct fpg { char *names, *back, *fore; };
662 struct fpc { int ncnt, bcnt, fcnt; uint16 *nclasses, *bclasses, *fclasses, *allclasses; };
663 struct fpv { int ncnt, bcnt, fcnt; char **ncovers, **bcovers, **fcovers; };
664 struct fpr { int always1, bcnt, fcnt; char **ncovers, **bcovers, **fcovers; char *replacements; };
665 
666 struct fpst_rule {
667     union {
668 	/* Note: Items in backtrack area are in reverse order because that's how the OT wants them */
669 	/*  they need to be reversed again to be displayed to the user */
670 	struct fpg glyph;
671 	struct fpc class;
672 	struct fpv coverage;
673 	struct fpr rcoverage;
674     } u;
675     int lookup_cnt;
676     struct seqlookup *lookups;
677 };
678 
679 typedef struct generic_fpst {
680     uint16 /*enum possub_type*/ type;
681     uint16 /*enum fpossub_format*/ format;
682     struct lookup_subtable *subtable;
683     struct generic_fpst *next;
684     uint16 nccnt, bccnt, fccnt;
685     uint16 rule_cnt;
686     char **nclass, **bclass, **fclass;
687     struct fpst_rule *rules;
688     uint8 ticked;
689     uint8 effectively_by_glyphs;
690     char **nclassnames, **bclassnames, **fclassnames;
691 } FPST;
692 
693 enum asm_type { asm_indic, asm_context, asm_lig, asm_simple=4, asm_insert,
694 	asm_kern=0x11 };
695 enum asm_flags { asm_vert=0x8000, asm_descending=0x4000, asm_always=0x2000 };
696 
697 struct asm_state {
698     uint16 next_state;
699     uint16 flags;
700     union {
701 	struct {
702 	    struct otlookup *mark_lookup;	/* for contextual glyph subs (tag of a nested lookup) */
703 	    struct otlookup *cur_lookup;	/* for contextual glyph subs */
704 	} context;
705 	struct {
706 	    char *mark_ins;
707 	    char *cur_ins;
708 	} insert;
709 	struct {
710 	    int16 *kerns;
711 	    int kcnt;
712 	} kern;
713     } u;
714 };
715 
716 typedef struct generic_asm {		/* Apple State Machine */
717     struct generic_asm *next;
718     uint16 /*enum asm_type*/ type;
719     struct lookup_subtable *subtable;	/* Lookup contains feature setting info */
720     uint16 flags;	/* 0x8000=>vert, 0x4000=>r2l, 0x2000=>hor&vert */
721     uint8 ticked;
722 
723     uint16 class_cnt, state_cnt;
724     char **classes;
725     struct asm_state *state;
726 } ASM;
727 /* State Flags:
728  Indic:
729 	0x8000	mark current glyph as first in rearrangement
730 	0x4000	don't advance to next glyph
731 	0x2000	mark current glyph as last
732 	0x000f	verb
733 		0 = no change		8 = AxCD => CDxA
734 		1 = Ax => xA		9 = AxCD => DCxA
735 		2 = xD => Dx		a = ABxD => DxAB
736 		3 = AxD => DxA		b = ABxD => DxBA
737 		4 = ABx => xAB		c = ABxCD => CDxAB
738 		5 = ABx => xBA		d = ABxCD => CDxBA
739 		6 = xCD => CDx		e = ABxCD => DCxAB
740 		7 = xCD => DCx		f = ABxCD => DCxBA
741  Contextual:
742 	0x8000	mark current glyph
743 	0x4000	don't advance to next glyph
744  Insert:
745 	0x8000	mark current glyph
746 	0x4000	don't advance to next glyph
747 	0x2000	current is Kashida like
748 	0x1000	mark is Kashida like
749 	0x0800	current insert before
750 	0x0400	mark insert before
751 	0x03e0	count of chars to be inserted at current (31 max)
752 	0x001f	count of chars to be inserted at mark (31 max)
753  Kern:
754 	0x8000	add current glyph to kerning stack
755 	0x4000	don't advance to next glyph
756 	0x3fff	value offset
757 */
758 
759 struct jstf_prio {
760     OTLookup **enableShrink;	/* Points to an array of lookups (GSUB or GPOS)*/
761     OTLookup **disableShrink;	/* NULL terminated */
762     OTLookup **maxShrink;	/* Array of GPOS like lookups */
763     OTLookup **enableExtend;
764     OTLookup **disableExtend;
765     OTLookup **maxExtend;
766 };
767 
768 struct jstf_lang {
769     uint32 lang;
770     struct jstf_lang *next;
771     int cnt;
772     struct jstf_prio *prios;
773 };
774 
775 typedef struct jstf_script {
776     uint32 script;
777     struct jstf_script *next;
778     char *extenders;		/* list of glyph names */
779     struct jstf_lang *langs;
780 } Justify;
781 
782 struct opentype_str {
783     struct splinechar *sc;
784     struct vr vr;		/* Scaled and rounded gpos modifications (device table info included in xoff, etc. not in adjusts) */
785     struct kernpair *kp;
786     struct kernclass *kc;
787     unsigned int prev_kc0: 1;
788     unsigned int next_kc0: 1;
789     int16 advance_width;	/* Basic advance, modifications in vr, scaled and rounded */
790 	/* Er... not actually set by ApplyLookups, but somewhere the caller */
791 	/*  can stash info. (Extract width from hinted bdf if possible, tt */
792 	/*  instructions can change it from the expected value) */
793     int16 kc_index;
794     int16 lig_pos;		/* when skipping marks to form a ligature keep track of what ligature element a mark was attached to */
795     int16 context_pos;		/* When doing a contextual match remember which glyphs are used, and where in the match they occur. Skipped glyphs have -1 */
796     int32 orig_index;
797     void *fl;
798     unsigned int line_break_after: 1;
799     unsigned int r2l: 1;
800     int16 bsln_off;
801 };
802 
803 struct macname {
804     struct macname *next;
805     uint16 enc;		/* Platform specific encoding. 0=>mac roman, 1=>sjis, 7=>russian */
806     uint16 lang;	/* Mac languages 0=>english, 1=>french, 2=>german */
807     char *name;		/* Not a unicode string, uninterpreted mac encoded string */
808 };
809 
810 /* Wow, the GPOS 'size' feature stores a string in the name table just as mac */
811 /*  features do */
812 /* And now (OTF 1.6) GSUB 'ss01'-'ss20' do too */
813 struct otfname {
814     struct otfname *next;
815     uint16 lang;	/* windows language code */
816     char *name;		/* utf8 */
817 };
818 
819 struct otffeatname {
820     uint32 tag;			/* Feature tag */
821     struct otfname *names;
822     struct otffeatname *next;
823     uint16 nid;			/* temporary value */
824 };
825 
826 struct macsetting {
827     struct macsetting *next;
828     uint16 setting;
829     uint16 strid;
830     struct macname *setname;
831     unsigned int initially_enabled: 1;
832 };
833 
834 typedef struct macfeat {
835     struct macfeat *next;
836     uint16 feature;
837     uint8 ismutex;
838     uint8 default_setting;		/* Apple's docs say both that this is a byte and a short. It's a byte */
839     uint16 strid;			/* Temporary value, used when reading in */
840     struct macname *featname;
841     struct macsetting *settings;
842 } MacFeat;
843 
844 typedef struct refbdfc {
845     unsigned int checked: 1;
846     unsigned int selected: 1;
847     int8 xoff;
848     int8 yoff;
849     uint16 gid;
850     struct refbdfc *next;
851     struct bdfchar *bdfc;
852 } BDFRefChar;
853 
854 struct bdfcharlist {
855     struct bdfchar *bc;
856     struct bdfcharlist *next;
857 };
858 
859 typedef struct bdfchar {
860     struct splinechar *sc;
861     int16 xmin,xmax,ymin,ymax;
862     int16 width;
863     int16 bytes_per_line;
864     uint8 *bitmap;
865     struct refbdfc *refs;
866     int orig_pos;
867     int16 pixelsize;                    /* for undoes */
868     struct bitmapview *views;
869     struct undoes *undoes;
870     struct undoes *redoes;
871     unsigned int changed: 1;
872     unsigned int byte_data: 1;	/* for anti-aliased chars entries are grey-scale bytes not bw bits */
873     unsigned int widthgroup: 1;	/* for ttf bitmap output */
874     unsigned int isreference: 1;	/* for ttf bitmap input, */
875     unsigned int ticked: 1;
876     uint8 depth;			/* for ttf bitmap output */
877     uint16 vwidth;
878     BDFFloat *selection;
879     BDFFloat *backup;
880     struct bdfcharlist *dependents;
881 } BDFChar;
882 
883 enum undotype { ut_none=0, ut_state, ut_tstate, ut_statehint, ut_statename,
884 		ut_statelookup,
885 		ut_anchors,
886 		ut_width, ut_vwidth, ut_lbearing, ut_rbearing, ut_possub,
887 		ut_hints, ut_bitmap, ut_bitmapsel, ut_composit, ut_multiple, ut_layers,
888 		ut_noop };
889 
890 #define UNDO_LAYER_UNKNOWN -1
891 
892 typedef struct undoes {
893     struct undoes *next;
894     enum undotype undotype;
895     unsigned int was_modified: 1;
896     unsigned int was_order2: 1;
897     int layer; /* the layer the undo is assoicated with or -1 if unknown */
898     union {
899 	struct {
900 	    int16 width, vwidth;
901 	    int16 lbearingchange;
902 	    int unicodeenc;			/* only for ut_statename */
903 	    char *charname;			/* only for ut_statename */
904 	    char *comment;			/* in utf8 */
905 	    PST *possub;			/* only for ut_statename */
906 	    struct splinepointlist *splines;
907 	    struct refchar *refs;
908 
909 	    struct imagelist *images;
910 	    void *hints;			/* ut_statehint, ut_statename */
911 	    uint8 *instrs;
912 	    int instrs_len;
913 	    AnchorPoint *anchor;
914 	    struct brush fill_brush;
915 	    struct pen stroke_pen;
916 	    unsigned int dofill: 1;
917 	    unsigned int dostroke: 1;
918 	    unsigned int fillfirst: 1;
919 	} state;
920 	int width;	/* used by both ut_width and ut_vwidth */
921 	int lbearing;	/* used by ut_lbearing */
922 	int rbearing;	/* used by ut_rbearing */
923 	BDFChar bmpstate;
924 	struct {		/* copy contains an outline state and a set of bitmap states */
925 	    struct undoes *state;
926 	    struct undoes *bitmaps;
927 	} composit;
928 	struct {
929 	    struct undoes *mult; /* copy contains several sub copies (composits, or states or widths or...) */
930 		/* Also used for ut_layers, each sub copy is a state (first is ly_fore, next ly_fore+1...) */
931 	} multiple;
932 	struct {
933 	    enum possub_type pst;
934 	    char **data;		/* First 4 bytes is tag, then space then data */
935 	    struct undoes *more_pst;
936 	    short cnt,max;		/* Not always set */
937 	} possub;
938 	uint8 *bitmap;
939     } u;
940     struct splinefont *copied_from;
941 } Undoes;
942 
943 enum sfundotype
944 {
945     sfut_none=0,
946     sfut_lookups,
947     sfut_lookups_kerns,
948     sfut_fontinfo,
949     sfut_noop
950 };
951 
952 /**
953  * A spline font level undo stack. undoes are doubly linked using the
954  * 'ln' member and carry some user presentable description of what the
955  * undo relates to in 'msg'.
956  *
957  * The sfdchunk is a pointer to an SFD fragment which will apply the
958  * undo to the current state. For example, it might contain
959  * information about the old value of kerning pairs which can be used
960  * to restore state to how it was. Note that the sfdchunk might only
961  * be partial, containing only enough information to restore the state
962  * which changed when the undo was created.
963  */
964 typedef struct sfundoes {
965     struct dlistnode ln;
966     char* msg;
967     enum sfundotype type;
968     union {
969 	int dummy;
970     } u;
971     char* sfdchunk;
972 } SFUndoes;
973 
974 
975 typedef struct enc {
976     char *enc_name;
977     int char_cnt;	/* Size of the next two arrays */
978     int32 *unicode;	/* unicode value for each encoding point */
979     char **psnames;	/* optional postscript name for each encoding point */
980     struct enc *next;
981     unsigned int builtin: 1;
982     unsigned int hidden: 1;
983     unsigned int only_1byte: 1;
984     unsigned int has_1byte: 1;
985     unsigned int has_2byte: 1;
986     unsigned int is_unicodebmp: 1;
987     unsigned int is_unicodefull: 1;
988     unsigned int is_custom: 1;
989     unsigned int is_original: 1;
990     unsigned int is_compact: 1;
991     unsigned int is_japanese: 1;
992     unsigned int is_korean: 1;
993     unsigned int is_tradchinese: 1;
994     unsigned int is_simplechinese: 1;
995     char iso_2022_escape[8];
996     int iso_2022_escape_len;
997     int low_page, high_page;
998     char *iconv_name;	/* For compatibility to old versions we might use a different name from that used by iconv. */
999     iconv_t *tounicode;
1000     iconv_t *fromunicode;
1001     int (*tounicode_func)(int);
1002     int (*fromunicode_func)(int);
1003     unsigned int is_temporary: 1;	/* freed when the map gets freed */
1004     int char_max;			/* Used by temporary encodings */
1005 } Encoding;
1006 
1007 struct renames { char *from; char *to; };
1008 
1009 typedef struct namelist {
1010     struct namelist *basedon;
1011     char *title;
1012     const char ***unicode[17];
1013     struct namelist *next;
1014     struct renames *renames;
1015     int uses_unicode;
1016     char *a_utf8_name;
1017 } NameList;
1018 
1019 enum uni_interp { ui_unset= -1, ui_none, ui_adobe, ui_greek, ui_japanese,
1020 	ui_trad_chinese, ui_simp_chinese, ui_korean, ui_ams };
1021 
1022 struct remap { uint32 firstenc, lastenc; int32 infont; };
1023 
1024 typedef struct encmap {		/* A per-font map of encoding to glyph id */
1025     int32 *map;			/* Map from encoding to glyphid */
1026     int32 *backmap;		/* Map from glyphid to encoding */
1027     int enccount;		/* used size of the map array */
1028     				/*  strictly speaking this might include */
1029 			        /*  glyphs that are not encoded, but which */
1030 			        /*  are displayed after the proper encoding */
1031     int encmax;			/* allocated size of the map array */
1032     int backmax;		/* allocated size of the backmap array */
1033     struct remap *remap;
1034     Encoding *enc;
1035     unsigned int ticked: 1;
1036 } EncMap;
1037 
1038 enum property_type { prt_string, prt_atom, prt_int, prt_uint, prt_property=0x10 };
1039 
1040 typedef struct bdfprops {
1041     char *name;		/* These include both properties (like SLANT) and non-properties (like FONT) */
1042     int type;
1043     union {
1044 	char *str;
1045 	char *atom;
1046 	int val;
1047     } u;
1048 } BDFProperties;
1049 
1050 typedef struct bdffont {
1051     struct splinefont *sf;
1052     int glyphcnt, glyphmax;	/* used & allocated sizes of glyphs array */
1053     BDFChar **glyphs;		/* an array of charcnt entries */
1054     int16 pixelsize;
1055     int16 ascent, descent;
1056     int16 layer;		/* for piecemeal fonts */
1057     unsigned int piecemeal: 1;
1058     unsigned int bbsized: 1;
1059     unsigned int ticked: 1;
1060     unsigned int unhinted_freetype: 1;
1061     unsigned int recontext_freetype: 1;
1062     struct bdffont *next;
1063     struct clut *clut;
1064     char *foundry;
1065     int res;
1066     void *freetype_context;
1067     uint16 truesize;		/* for bbsized fonts */
1068     int16 prop_cnt;
1069     int16 prop_max;		/* only used within bdfinfo dlg */
1070     BDFProperties *props;
1071     uint16 ptsize, dpi;		/* for piecemeal fonts */
1072 } BDFFont;
1073 
1074 #define HntMax	96		/* PS says at most 96 hints */
1075 typedef uint8 HintMask[HntMax/8];
1076 
1077 enum pointtype { pt_curve, pt_corner, pt_tangent, pt_hvcurve };
1078 typedef struct splinepoint {
1079     BasePoint me;
1080     BasePoint nextcp;		/* control point */
1081     BasePoint prevcp;		/* control point */
1082     unsigned int nonextcp:1;
1083     unsigned int noprevcp:1;
1084     unsigned int nextcpdef:1;
1085     unsigned int prevcpdef:1;
1086     unsigned int selected:1;	/* for UI */
1087     unsigned int nextcpselected: 2; /* Is the next BCP selected */
1088     unsigned int prevcpselected: 2; /* Is the prev BCP selected */
1089     unsigned int pointtype:2;
1090     unsigned int isintersection: 1;
1091     unsigned int flexy: 1;	/* When "freetype_markup" is on in charview.c:DrawPoint */
1092     unsigned int flexx: 1;	/* flexy means select nextcp, and flexx means draw circle around nextcp */
1093     unsigned int roundx: 1;	/* For true type hinting */
1094     unsigned int roundy: 1;	/* For true type hinting */
1095     unsigned int dontinterpolate: 1;	/* in ttf, don't imply point by interpolating between cps */
1096     unsigned int ticked: 1;
1097     unsigned int watched: 1;
1098 	/* 1 bits left... */
1099     uint16 ptindex;		/* Temporary value used by metafont routine */
1100     uint16 ttfindex;		/* Truetype point index */
1101 	/* Special values 0xffff => point implied by averaging control points */
1102 	/*		  0xfffe => point created with no real number yet */
1103 	/* (or perhaps point in context where no number is possible as in a glyph with points & refs) */
1104     uint16 nextcpindex;		/* Truetype point index */
1105     struct spline *next;
1106     struct spline *prev;
1107     HintMask *hintmask;
1108 	char* name;
1109 } SplinePoint;
1110 
1111 enum linelist_flags { cvli_onscreen=0x1, cvli_clipped=0x2 };
1112 
1113 typedef struct linelist {
1114     IPoint here;
1115     struct linelist *next;
1116     /* The first two fields are constant for the linelist, the next ones */
1117     /*  refer to a particular screen. If some portion of the line from */
1118     /*  this point to the next one is on the screen then set cvli_onscreen */
1119     /*  if this point needs to be clipped then set cvli_clipped */
1120     /*  asend and asstart are the actual screen locations where this point */
1121     /*  intersects the clip edge. */
1122     enum linelist_flags flags;
1123     IPoint asend, asstart;
1124 } LineList;
1125 
1126 typedef struct linearapprox {
1127     real scale;
1128     unsigned int oneline: 1;
1129     unsigned int onepoint: 1;
1130     unsigned int any: 1;		/* refers to a particular screen */
1131     struct linelist *lines;
1132     struct linearapprox *next;
1133 } LinearApprox;
1134 
1135 typedef struct spline1d {
1136     real a, b, c, d;
1137 } Spline1D;
1138 
1139 /**
1140  *
1141  * 2013Note: If you are altering from->me.x and y then you will
1142  *           probably have to modify splines[] to match your change.
1143  *           eg, moving both ends of a spline up/down by changing their
1144  *           to/from will also probably need an update to splines[ 0 | 1 ].d to
1145  *           match.
1146  */
1147 typedef struct spline {
1148     unsigned int islinear: 1;		/* No control points */
1149     unsigned int isquadratic: 1;	/* probably read in from ttf */
1150     unsigned int isticked: 1;
1151     unsigned int isneeded: 1;		/* Used in remove overlap */
1152     unsigned int isunneeded: 1;		/* Used in remove overlap */
1153     unsigned int exclude: 1;		/* Used in remove overlap varient: exclude */
1154     unsigned int ishorvert: 1;
1155     unsigned int knowncurved: 1;	/* We know that it curves */
1156     unsigned int knownlinear: 1;	/* it might have control points, but still traces out a line */
1157 	/* If neither knownlinear nor curved then we haven't checked */
1158     unsigned int order2: 1;		/* It's a bezier curve with only one cp */
1159     unsigned int touched: 1;
1160     unsigned int leftedge: 1;
1161     unsigned int rightedge: 1;
1162     unsigned int acceptableextrema: 1;	/* This spline has extrema, but we don't care */
1163     SplinePoint *from;
1164     SplinePoint *to;
1165     Spline1D splines[2];		/* splines[0] is the x spline, splines[1] is y */
1166     struct linearapprox *approx;
1167     /* Posible optimizations:
1168 	Precalculate bounding box
1169 	Precalculate min/max/ points of inflection
1170     */
1171 } Spline;
1172 
1173 typedef struct splinepointlist {
1174     SplinePoint *first, *last;
1175     struct splinepointlist *next;
1176     spiro_cp *spiros;
1177     uint16 spiro_cnt, spiro_max;
1178 	/* These could be bit fields, but bytes are easier to access and we */
1179 	/*  don't need the space (yet) */
1180     uint8 ticked;
1181     uint8 beziers_need_optimizer;	/* If the spiros have changed in spiro mode, then reverting to bezier mode might, someday, run a simplifier */
1182     uint8 is_clip_path;			/* In type3/svg fonts */
1183     int start_offset; // This indicates which point is the canonical first for purposes of outputting to U. F. O..
1184     char *contour_name;
1185 } SplinePointList, SplineSet;
1186 
1187 typedef struct imagelist {
1188     struct gimage *image;
1189     real xoff, yoff;		/* position in character space of upper left corner of image */
1190     real xscale, yscale;	/* scale to convert one pixel of image to one unit of character space */
1191     DBounds bb;
1192     struct imagelist *next;
1193     unsigned int selected: 1;
1194 } ImageList;
1195 
1196 struct guidelineset;
1197 typedef struct guidelineset {
1198     // This is a UFO construct. We implement it only for round-tripping.
1199     // The FontForge way is to have a global "grid".
1200     // If it is necessary to have per-character guides, one would use a background layer.
1201     // Having per glyph-layer guides is sort of ridiculous.
1202     // Life is much easier the FontForge way.
1203     char *name;
1204     char *identifier; // Duplicative, but in the UFO specification.
1205     BasePoint point;
1206     real angle;
1207     uint32 color; // Red, green, blue, and alpha, 8 bits apiece.
1208     int flags; // 0x20 means that the color is set. 0x10 means that the point was imported clean (one numeric parameter).
1209     struct guidelineset *next;
1210 } GuidelineSet;
1211 
1212 struct reflayer {
1213     unsigned int background: 1;
1214     unsigned int order2: 1;
1215     unsigned int anyflexes: 1;
1216     unsigned int dofill: 1;
1217     unsigned int dostroke: 1;
1218     unsigned int fillfirst: 1;
1219     struct brush fill_brush;
1220     struct pen stroke_pen;
1221     SplinePointList *splines;
1222     ImageList *images;			/* Only in background or type3 layer(s) */
1223 };
1224 
1225 typedef struct refchar {
1226     unsigned int checked: 1;
1227     unsigned int selected: 1;
1228     unsigned int point_match: 1;	/* match_pt* are point indexes */
1229 					/*  and need to be converted to a */
1230 			                /*  translation after truetype readin */
1231     unsigned int encoded: 1;		/* orig_pos is actually an encoded value, used for old sfd files */
1232     unsigned int justtranslated: 1;	/* The transformation matrix specifies a translation (or is identity) */
1233     unsigned int use_my_metrics: 1;	/* Retain the ttf "use_my_metrics" info. */
1234 	/* important for glyphs with instructions which change the width used */
1235 	/* inside composites */
1236     unsigned int round_translation_to_grid: 1;	/* Retain the ttf "round_to_grid" info. */
1237     unsigned int point_match_out_of_date: 1;	/* Someone has edited a base glyph */
1238     int16 adobe_enc;
1239     int orig_pos;
1240     int unicode_enc;		/* used by paste */
1241     real transform[6];		/* transformation matrix (first 2 rows of a 3x3 matrix, missing row is 0,0,1) */
1242     struct reflayer *layers;
1243     int layer_cnt;
1244     struct refchar *next;
1245     DBounds bb;
1246     struct splinechar *sc;
1247     BasePoint top;
1248     uint16 match_pt_base, match_pt_ref;
1249 } RefChar;
1250 
1251 /* Some stems may appear, disappear, reapear several times */
1252 /* Serif stems on I which appear at 0, disappear, reappear at top */
1253 /* Or the major vertical stems on H which disappear at the cross bar */
1254 typedef struct hintinstance {
1255     real begin;			/* location in the non-major direction*/
1256     real end;				/* width/height in non-major direction*/
1257     unsigned int closed: 1;
1258     short int counternumber;
1259     struct hintinstance *next;
1260 } HintInstance;
1261 
1262 enum hinttypes { ht_unspecified=0, ht_h, ht_v, ht_d };
1263 typedef real _MMArray[2][MmMax];
1264 
1265 typedef struct steminfo {
1266     struct steminfo *next;
1267     unsigned int hinttype: 2;	/* Only used by undoes */
1268     unsigned int ghost: 1;	/* this is a ghost stem hint. As such truetype should ignore it, type2 output should negate it, and type1 should use as is */
1269 		    /* stored width will be either 20 or 21 */
1270 		    /* Type2 says: -20 is "width" of top edge, -21 is "width" of bottom edge, type1 accepts either */
1271     unsigned int haspointleft:1;
1272     unsigned int haspointright:1;
1273     unsigned int hasconflicts:1;/* Does this stem have conflicts within its cluster? */
1274     unsigned int used: 1;	/* Temporary for counter hints or hint substitution */
1275     unsigned int tobeused: 1;	/* Temporary for counter hints or hint substitution */
1276     unsigned int active: 1;	/* Currently active hint in Review Hints dlg */
1277 				/*  displayed differently in char display */
1278     unsigned int enddone: 1;	/* Used by ttf instructing, indicates a prev */
1279 				/*  hint had the same end as this one (so */
1280 			        /*  the points on the end line have been */
1281 			        /*  instructed already */
1282     unsigned int startdone: 1;	/* Used by ttf instructing */
1283     /*unsigned int backwards: 1;*/	/* If we think this hint is better done with a negative width */
1284     unsigned int reordered: 1;	/* In AutoHinting. Means we changed the start of the hint, need to test for out of order */
1285     unsigned int pendingpt: 1;	/* A pending stem creation, not a true stem */
1286     unsigned int linearedges: 1;/* If we have a nice rectangle then we aren't */
1287 				/*  interested in the orientation which is */
1288 			        /*  wider than long */
1289     int16 hintnumber;		/* when dumping out hintmasks we need to know */
1290 				/*  what bit to set for this hint */
1291     union {
1292 	int mask;		/* Mask of all references that use this hint */
1293 				/*  in type2 output */
1294 	_MMArray *unblended /*[2][MmMax]*/;	/* Used when reading in type1 mm hints */
1295     } u;
1296     real start;			/* location at which the stem starts */
1297     real width;			/* or height */
1298     HintInstance *where;	/* location(s) in the other coord */
1299 } StemInfo;
1300 
1301 typedef struct dsteminfo {
1302     struct dsteminfo *next;	/* First two fields match those in steminfo */
1303     unsigned int hinttype: 2;	/* Only used by undoes */
1304     unsigned int used: 1;	/* used only by tottf.c:gendinstrs, metafont.c to mark a hint that has been dealt with */
1305     BasePoint left, right, unit;
1306     HintInstance *where;	/* location(s) along the unit vector */
1307 } DStemInfo;
1308 
1309 typedef struct minimumdistance {
1310     /* If either point is NULL it will be assumed to mean either the origin */
1311     /*  or the width point (depending on which is closer). This allows user */
1312     /*  to control metrics... */
1313     SplinePoint *sp1, *sp2;
1314     unsigned int x: 1;
1315     unsigned int done: 1;
1316     struct minimumdistance *next;
1317 } MinimumDistance;
1318 
1319 typedef struct layer /* : reflayer */{
1320     unsigned int background: 1;
1321     unsigned int order2: 1;
1322     unsigned int anyflexes: 1;
1323     unsigned int dofill: 1;
1324     unsigned int dostroke: 1;
1325     unsigned int fillfirst: 1;
1326     struct brush fill_brush;
1327     struct pen stroke_pen;
1328     SplinePointList *splines;
1329     ImageList *images;			/* Only in background or type3 layer(s) */
1330     RefChar *refs;			/* Only in foreground layer(s) */
1331     GuidelineSet *guidelines;		/* Only in UFO imports, we hope. Inefficient otherwise. */
1332     Undoes *undoes;
1333     Undoes *redoes;
1334     uint32 validation_state;
1335     uint32 old_vs;
1336     void *python_persistent;		/* If python this will hold a python object, if not python this will hold a string containing a pickled object. We do nothing with it (if not python) except save it back out unchanged */
1337     int python_persistent_has_lists;
1338 } Layer;
1339 
1340 enum layer_type { ly_all=-2, ly_grid= -1, ly_back=0, ly_fore=1,
1341     /* Possibly other foreground layers for type3 things */
1342     /* Possibly other background layers for normal fonts */
1343 	ly_none = -3
1344     };
1345 
1346 struct gv_part {
1347     char *component;
1348     unsigned int is_extender: 1;	/* This component may be skipped or repeated */
1349     uint16 startConnectorLength;
1350     uint16 endConnectorLength;
1351     uint16 fullAdvance;
1352 };
1353 
1354 /* For the 'MATH' table (and for TeX) */
1355 struct glyphvariants {
1356     char *variants;	/* Space separated list of glyph names */
1357 /* Glyph assembly */
1358     int16 italic_correction;	/* Of the composed glyph */
1359     DeviceTable *italic_adjusts;
1360     int part_cnt;
1361     struct gv_part *parts;
1362 };
1363 
1364 struct mathkerndata {
1365     int16 height,kern;
1366     DeviceTable *height_adjusts;
1367     DeviceTable *kern_adjusts;
1368 };
1369 
1370 /* For the 'MATH' table */
1371 struct mathkernvertex {
1372     int cnt;		/* There is one more kern entry than height entry */
1373 	    /* So the last mkd should have its height ignored */
1374 	    /* The MATH table stores the height count, I think the kern count */
1375 	    /*  is more useful (and that's what I use here). They differ by 1 */
1376     struct mathkerndata *mkd;
1377 };
1378 
1379 struct mathkern {
1380     struct mathkernvertex top_right;
1381     struct mathkernvertex top_left;
1382     struct mathkernvertex bottom_right;
1383     struct mathkernvertex bottom_left;
1384 };
1385 
1386 enum privatedict_state {
1387     pds_odd        = 0x1,	/* Odd number of entries */
1388     pds_outoforder = 0x2,	/* Bluevalues should be listed in order */
1389     pds_toomany    = 0x4,	/* arrays are of limited sizes */
1390     pds_tooclose   = 0x8,	/* adjacent zones must not be within 2*bluefuzz+1 (or 3, if bluefuzz omitted) */
1391     pds_notintegral= 0x10,	/* Must be integers */
1392     pds_toobig     = 0x20,	/* within pair difference have some relation to BlueScale but the docs make no sense to me */
1393     pds_shift	   = 8,		/* BlueValues/OtherBlues, unshifted, FamilyBlues/FamilyOtherBlues shifted once */
1394 
1395     pds_missingblue  = 0x010000,
1396     pds_badbluefuzz  = 0x020000,
1397     pds_badbluescale = 0x040000,
1398     pds_badstdhw     = 0x080000,
1399     pds_badstdvw     = 0x100000,
1400     pds_badstemsnaph = 0x200000,
1401     pds_badstemsnapv = 0x400000,
1402     pds_stemsnapnostdh = 0x0800000,
1403     pds_stemsnapnostdv = 0x1000000,
1404     pds_badblueshift   = 0x2000000
1405 
1406 };
1407 
1408 enum validation_state { vs_unknown = 0,
1409 	vs_known=0x01,				/* It has been validated */
1410 	vs_opencontour=0x02,
1411 	vs_selfintersects=0x04,
1412 	vs_wrongdirection=0x08,
1413 	vs_flippedreferences=0x10,		/* special case of wrong direction */
1414 	vs_missingextrema=0x20,
1415 	vs_missingglyphnameingsub=0x40,
1416 	    /* Next few are postscript only */
1417 	vs_toomanypoints=0x80,
1418 	vs_toomanyhints=0x100,
1419 	vs_badglyphname=0x200,
1420 	    /* Next few are only for fontlint */
1421 	    /* These are relative to maxp values which ff would fix on generating a font */
1422 	vs_maxp_toomanypoints    =0x400,
1423 	vs_maxp_toomanypaths     =0x800,
1424 	vs_maxp_toomanycomppoints=0x1000,
1425 	vs_maxp_toomanycomppaths =0x2000,
1426 	vs_maxp_instrtoolong     =0x4000,
1427 	vs_maxp_toomanyrefs      =0x8000,
1428 	vs_maxp_refstoodeep      =0x10000,
1429 	/* vs_maxp_prepfpgmtoolong=0x20000, */	/* I think I was wrong about this "error" */
1430 	    /* Oops, we need another one, two, for the glyphs */
1431 	vs_pointstoofarapart	= 0x40000,
1432 	vs_nonintegral		= 0x80000,	/* This will never be interesting in a real font, but might be in an sfd file */
1433 	vs_missinganchor	= 0x100000,
1434 	vs_dupname		= 0x200000,
1435 	vs_dupunicode		= 0x400000,
1436 	vs_overlappedhints	= 0x800000,
1437 
1438 	vs_last = vs_overlappedhints,
1439 	vs_maskps = 0x3fe | vs_pointstoofarapart | vs_missinganchor | vs_dupname | vs_dupunicode | vs_overlappedhints,
1440 	vs_maskcid = 0x1fe | vs_pointstoofarapart | vs_missinganchor | vs_dupname | vs_overlappedhints,
1441 	vs_maskttf = 0x7e | vs_pointstoofarapart | vs_nonintegral | vs_missinganchor | vs_dupunicode,
1442 	vs_maskfindproblems = 0x1be | vs_pointstoofarapart | vs_nonintegral | vs_missinganchor | vs_overlappedhints
1443 	};
1444 
1445 struct splinecharlist { struct splinechar *sc; struct splinecharlist *next;};
1446 
1447 struct altuni { struct altuni *next; int32 unienc, vs; uint32 fid; };
1448 	/* vs is the "variation selector" a unicode codepoint which modifieds */
1449 	/*  the code point before it. If vs is -1 then unienc is just an */
1450 	/*  alternate encoding (greek Alpha and latin A), but if vs is one */
1451 	/*  of unicode's variation selectors then this glyph is somehow a */
1452 	/*  variant shape. The specifics depend on the selector and script */
1453 	/*  fid is currently unused, but may, someday, be used to do ttcs */
1454 	/* NOTE: GlyphInfo displays vs==-1 as vs==0, and fixes things up */
1455 
1456 typedef struct splinechar {
1457     char *name;
1458     int unicodeenc;
1459     int orig_pos;		/* Original position in the glyph list */
1460     int16 width, vwidth;
1461     int16 lsidebearing;		/* only used when reading in a type1 font */
1462 				/*  Or an otf font where it is the subr number of a refered character */
1463 			        /*  or a ttf font without bit 1 of head.flags set */
1464 			        /*  or (once upon a time, but no longer) a ttf font with vert metrics where it is the ymax value when we had a font-wide vertical offset */
1465 			        /*  or when generating morx where it is the mask of tables in which the glyph occurs */
1466 				/* Always a temporary value */
1467     int ttf_glyph;		/* only used when writing out a ttf or otf font */
1468     Layer *layers;		/* layer[0] is background, layer[1] foreground */
1469 	/* In type3 fonts 2-n are also foreground, otherwise also background */
1470     int layer_cnt;
1471     StemInfo *hstem;		/* hstem hints have a vertical offset but run horizontally */
1472     StemInfo *vstem;		/* vstem hints have a horizontal offset but run vertically */
1473     DStemInfo *dstem;		/* diagonal hints for ttf */
1474     MinimumDistance *md;
1475     struct charviewbase *views;
1476     struct charinfo *charinfo;
1477     struct splinefont *parent;
1478     unsigned int changed: 1;
1479     unsigned int changedsincelasthinted: 1;
1480     unsigned int manualhints: 1;
1481     unsigned int ticked: 1;	/* For reference character processing */
1482 				/* And fontview processing */
1483     unsigned int changed_since_autosave: 1;
1484     unsigned int widthset: 1;	/* needed so an emspace char doesn't disappear */
1485     unsigned int vconflicts: 1;	/* Any hint overlaps in the vstem list? */
1486     unsigned int hconflicts: 1;	/* Any hint overlaps in the hstem list? */
1487     unsigned int searcherdummy: 1;
1488     unsigned int changed_since_search: 1;
1489     unsigned int wasopen: 1;
1490     unsigned int namechanged: 1;
1491     unsigned int blended: 1;	/* An MM blended character */
1492     unsigned int ticked2: 1;
1493     unsigned int glyph_class: 3; /* 0=> fontforge determines class automagically, else one more than the class value in gdef so 2+1=>lig, 3+1=>mark */
1494     unsigned int numberpointsbackards: 1;
1495     unsigned int instructions_out_of_date: 1;
1496     unsigned int complained_about_ptnums: 1;
1497     unsigned int vs_open: 1;
1498     unsigned int unlink_rm_ovrlp_save_undo: 1;
1499     unsigned int inspiro: 1;
1500     unsigned int lig_caret_cnt_fixed: 1;
1501     unsigned int suspendMetricsViewEventPropagation: 1; /* rect tool might do this while drawing */
1502     /* 5 bits left (one more if we ignore compositionunit below) */
1503 #if HANYANG
1504     unsigned int compositionunit: 1;
1505     int16 jamo, varient;
1506 #endif
1507     struct splinecharlist *dependents;
1508 	    /* The dependents list is a list of all characters which refenence*/
1509 	    /*  the current character directly */
1510     KernPair *kerns; // Note that the left character in the pair has the reference to the kerning pair, which in turn references the right character.
1511     KernPair *vkerns;
1512     PST *possub;		/* If we are a ligature then this tells us what */
1513 				/*  It may also contain a bunch of other stuff now */
1514     LigList *ligofme;		/* If this is the first character of a ligature then this gives us the list of possible ones */
1515 				/*  this field must be regenerated before the font is saved */
1516     char *comment;			/* in utf8 */
1517     uint32 /*Color*/ color;
1518     AnchorPoint *anchor;
1519     uint8 *ttf_instrs;
1520     int16 ttf_instrs_len;
1521     int16 countermask_cnt;
1522     HintMask *countermasks;
1523     struct altuni *altuni;
1524 /* for TeX */
1525     int16 tex_height, tex_depth;
1526 /* TeX also uses italic_correction and glyph variants below */
1527 /* For the 'MATH' table (and for TeX) */
1528     unsigned int is_extended_shape: 1;
1529     int16 italic_correction;
1530     int16 top_accent_horiz;		/* MATH table allows you to specific a*/
1531 		/* horizontal anchor for accent attachments, vertical */
1532 		/* positioning is done elsewhere */
1533     DeviceTable *italic_adjusts;
1534     DeviceTable *top_accent_adjusts;
1535     struct glyphvariants *vert_variants;
1536     struct glyphvariants *horiz_variants;
1537     struct mathkern *mathkern;
1538 /* End of MATH/TeX fields */
1539 #ifndef _NO_PYTHON
1540     void *python_sc_object;
1541     void *python_temporary;
1542 #endif
1543 #if 0
1544     // Python persistent data is now in the layers.
1545     void *python_persistent;		/* If python this will hold a python object, if not python this will hold a string containing a pickled object. We do nothing with it (if not python) except save it back out unchanged */
1546     int python_persistent_has_lists;
1547 #endif // 0
1548 	/* If the glyph is used as a tile pattern, then the next two values */
1549 	/*  determine the amount of white space around the tile. If extra is*/
1550 	/*  non-zero then we add it to the max components of the bbox and   */
1551 	/*  subtract it from the min components. If extra is 0 then tile_bounds*/
1552 	/*  will be used. If tile_bounds is all zeros then the glyph's bbox */
1553 	/*  will be used. */
1554     real tile_margin;			/* If the glyph is used as a tile */
1555     DBounds tile_bounds;
1556     char * glif_name; // This stores the base name of the glyph when saved to U. F. O..
1557     unichar_t* user_decomp; // User decomposition for building this character
1558 } SplineChar;
1559 
1560 #define TEX_UNDEF 0x7fff
1561 
1562 enum ttfnames { ttf_copyright=0, ttf_family, ttf_subfamily, ttf_uniqueid,
1563     ttf_fullname, ttf_version, ttf_postscriptname, ttf_trademark,
1564     ttf_manufacturer, ttf_designer, ttf_descriptor, ttf_venderurl,
1565     ttf_designerurl, ttf_license, ttf_licenseurl, ttf_idontknow/*reserved*/,
1566     ttf_preffamilyname, ttf_prefmodifiers, ttf_compatfull, ttf_sampletext,
1567     ttf_cidfindfontname, ttf_wwsfamily, ttf_wwssubfamily, ttf_namemax };
1568 struct ttflangname {
1569     int lang;
1570     char *names[ttf_namemax];			/* in utf8 */
1571     int frommac[(ttf_namemax+31)/32];		/* Used when parsing the 'name' table */
1572     struct ttflangname *next;
1573 };
1574 
1575 struct MATH {
1576 /* From the MATH Constants subtable (constants for positioning glyphs. Not PI)*/
1577     int16 ScriptPercentScaleDown;
1578     int16 ScriptScriptPercentScaleDown;
1579     uint16 DelimitedSubFormulaMinHeight;
1580     uint16 DisplayOperatorMinHeight;
1581     int16 MathLeading;
1582     DeviceTable *MathLeading_adjust;
1583     int16 AxisHeight;
1584     DeviceTable *AxisHeight_adjust;
1585     int16 AccentBaseHeight;
1586     DeviceTable *AccentBaseHeight_adjust;
1587     int16 FlattenedAccentBaseHeight;
1588     DeviceTable *FlattenedAccentBaseHeight_adjust;
1589     int16 SubscriptShiftDown;
1590     DeviceTable *SubscriptShiftDown_adjust;
1591     int16 SubscriptTopMax;
1592     DeviceTable *SubscriptTopMax_adjust;
1593     int16 SubscriptBaselineDropMin;
1594     DeviceTable *SubscriptBaselineDropMin_adjust;
1595     int16 SuperscriptShiftUp;
1596     DeviceTable *SuperscriptShiftUp_adjust;
1597     int16 SuperscriptShiftUpCramped;
1598     DeviceTable *SuperscriptShiftUpCramped_adjust;
1599     int16 SuperscriptBottomMin;
1600     DeviceTable *SuperscriptBottomMin_adjust;
1601     int16 SuperscriptBaselineDropMax;
1602     DeviceTable *SuperscriptBaselineDropMax_adjust;
1603     int16 SubSuperscriptGapMin;
1604     DeviceTable *SubSuperscriptGapMin_adjust;
1605     int16 SuperscriptBottomMaxWithSubscript;
1606     DeviceTable *SuperscriptBottomMaxWithSubscript_adjust;
1607     int16 SpaceAfterScript;
1608     DeviceTable *SpaceAfterScript_adjust;
1609     int16 UpperLimitGapMin;
1610     DeviceTable *UpperLimitGapMin_adjust;
1611     int16 UpperLimitBaselineRiseMin;
1612     DeviceTable *UpperLimitBaselineRiseMin_adjust;
1613     int16 LowerLimitGapMin;
1614     DeviceTable *LowerLimitGapMin_adjust;
1615     int16 LowerLimitBaselineDropMin;
1616     DeviceTable *LowerLimitBaselineDropMin_adjust;
1617     int16 StackTopShiftUp;
1618     DeviceTable *StackTopShiftUp_adjust;
1619     int16 StackTopDisplayStyleShiftUp;
1620     DeviceTable *StackTopDisplayStyleShiftUp_adjust;
1621     int16 StackBottomShiftDown;
1622     DeviceTable *StackBottomShiftDown_adjust;
1623     int16 StackBottomDisplayStyleShiftDown;
1624     DeviceTable *StackBottomDisplayStyleShiftDown_adjust;
1625     int16 StackGapMin;
1626     DeviceTable *StackGapMin_adjust;
1627     int16 StackDisplayStyleGapMin;
1628     DeviceTable *StackDisplayStyleGapMin_adjust;
1629     int16 StretchStackTopShiftUp;
1630     DeviceTable *StretchStackTopShiftUp_adjust;
1631     int16 StretchStackBottomShiftDown;
1632     DeviceTable *StretchStackBottomShiftDown_adjust;
1633     int16 StretchStackGapAboveMin;
1634     DeviceTable *StretchStackGapAboveMin_adjust;
1635     int16 StretchStackGapBelowMin;
1636     DeviceTable *StretchStackGapBelowMin_adjust;
1637     int16 FractionNumeratorShiftUp;
1638     DeviceTable *FractionNumeratorShiftUp_adjust;
1639     int16 FractionNumeratorDisplayStyleShiftUp;
1640     DeviceTable *FractionNumeratorDisplayStyleShiftUp_adjust;
1641     int16 FractionDenominatorShiftDown;
1642     DeviceTable *FractionDenominatorShiftDown_adjust;
1643     int16 FractionDenominatorDisplayStyleShiftDown;
1644     DeviceTable *FractionDenominatorDisplayStyleShiftDown_adjust;
1645     int16 FractionNumeratorGapMin;
1646     DeviceTable *FractionNumeratorGapMin_adjust;
1647     int16 FractionNumeratorDisplayStyleGapMin;
1648     DeviceTable *FractionNumeratorDisplayStyleGapMin_adjust;
1649     int16 FractionRuleThickness;
1650     DeviceTable *FractionRuleThickness_adjust;
1651     int16 FractionDenominatorGapMin;
1652     DeviceTable *FractionDenominatorGapMin_adjust;
1653     int16 FractionDenominatorDisplayStyleGapMin;
1654     DeviceTable *FractionDenominatorDisplayStyleGapMin_adjust;
1655     int16 SkewedFractionHorizontalGap;
1656     DeviceTable *SkewedFractionHorizontalGap_adjust;
1657     int16 SkewedFractionVerticalGap;
1658     DeviceTable *SkewedFractionVerticalGap_adjust;
1659     int16 OverbarVerticalGap;
1660     DeviceTable *OverbarVerticalGap_adjust;
1661     int16 OverbarRuleThickness;
1662     DeviceTable *OverbarRuleThickness_adjust;
1663     int16 OverbarExtraAscender;
1664     DeviceTable *OverbarExtraAscender_adjust;
1665     int16 UnderbarVerticalGap;
1666     DeviceTable *UnderbarVerticalGap_adjust;
1667     int16 UnderbarRuleThickness;
1668     DeviceTable *UnderbarRuleThickness_adjust;
1669     int16 UnderbarExtraDescender;
1670     DeviceTable *UnderbarExtraDescender_adjust;
1671     int16 RadicalVerticalGap;
1672     DeviceTable *RadicalVerticalGap_adjust;
1673     int16 RadicalDisplayStyleVerticalGap;
1674     DeviceTable *RadicalDisplayStyleVerticalGap_adjust;
1675     int16 RadicalRuleThickness;
1676     DeviceTable *RadicalRuleThickness_adjust;
1677     int16 RadicalExtraAscender;
1678     DeviceTable *RadicalExtraAscender_adjust;
1679     int16 RadicalKernBeforeDegree;
1680     DeviceTable *RadicalKernBeforeDegree_adjust;
1681     int16 RadicalKernAfterDegree;
1682     DeviceTable *RadicalKernAfterDegree_adjust;
1683     uint16 RadicalDegreeBottomRaisePercent;
1684 /* Global constants from other subtables */
1685     uint16 MinConnectorOverlap;			/* in the math variants sub-table */
1686 };
1687 
1688 enum backedup_state { bs_dontknow=0, bs_not=1, bs_backedup=2 };
1689 enum loadvalidation_state {
1690 	lvs_bad_ps_fontname    = 0x001,
1691 	lvs_bad_glyph_table    = 0x002,
1692 	lvs_bad_cff_table      = 0x004,
1693 	lvs_bad_metrics_table  = 0x008,
1694 	lvs_bad_cmap_table     = 0x010,
1695 	lvs_bad_bitmaps_table  = 0x020,
1696 	lvs_bad_gx_table       = 0x040,
1697 	lvs_bad_ot_table       = 0x080,
1698 	lvs_bad_os2_version    = 0x100,
1699 	lvs_bad_sfnt_header    = 0x200
1700     };
1701 
1702 typedef struct layerinfo {
1703     char *name;
1704     unsigned int background: 1;			/* Layer is to be treated as background: No width, images, not worth outputting */
1705     unsigned int order2: 1;			/* Layer's data are order 2 bezier splines (truetype) rather than order 3 (postscript) */
1706 						/* In all glyphs in the font */
1707     unsigned int ticked: 1;
1708     char * ufo_path;
1709 } LayerInfo;
1710 
1711 /* Baseline data from the 'BASE' table */
1712 struct baselangextent {
1713     uint32 lang;		/* also used for feature tag */
1714     struct baselangextent *next;
1715     int16 ascent, descent;
1716     struct baselangextent *features;
1717 };
1718 
1719 struct basescript {
1720     uint32 script;
1721     struct basescript *next;
1722     int    def_baseline;	/* index [0-baseline_cnt) */
1723     int16 *baseline_pos;	/* baseline_cnt of these */
1724     struct baselangextent *langs;	/* Language specific extents (may be NULL) */
1725 				/* The default one has the tag DEFAULT_LANG */
1726 };
1727 
1728 struct Base {
1729     int baseline_cnt;
1730     uint32 *baseline_tags;
1731     /* A font does not need to provide info on all baselines, but if one script */
1732     /*  talks about a baseline, then all must. So the set of baselines is global*/
1733     struct basescript *scripts;
1734 };
1735 
1736 struct pfminfo {		/* A misnomer now. OS/2 info would be more accurate, but that's stuff in here from all over ttf files */
1737     unsigned int pfmset: 1;
1738     unsigned int winascent_add: 1;
1739     unsigned int windescent_add: 1;
1740     unsigned int hheadascent_add: 1;
1741     unsigned int hheaddescent_add: 1;
1742     unsigned int typoascent_add: 1;
1743     unsigned int typodescent_add: 1;
1744     unsigned int subsuper_set: 1;
1745     unsigned int panose_set: 1;
1746     unsigned int hheadset: 1;
1747     unsigned int vheadset: 1;
1748     unsigned int hascodepages: 1;
1749     unsigned int hasunicoderanges: 1;
1750     unsigned char pfmfamily;
1751     int16 weight;
1752     int16 width;
1753     char panose[10];
1754     /* A subset of OS/2 fsSelection, used for style mapping. */
1755     /* Must agree with macStyle per otspec, takes precedence. */
1756     /* Can't use macStyle because it doesn't have a "regular" bit unlike the OS/2 component. */
1757     int16 stylemap;
1758     int16 fstype;
1759     int16 linegap;		/* from hhea */
1760     int16 vlinegap;		/* from vhea */
1761     int16 hhead_ascent, hhead_descent;
1762     int16 os2_typoascent, os2_typodescent, os2_typolinegap;
1763     int16 os2_winascent, os2_windescent;
1764     int16 os2_subxsize, os2_subysize, os2_subxoff, os2_subyoff;
1765     int16 os2_supxsize, os2_supysize, os2_supxoff, os2_supyoff;
1766     int16 os2_strikeysize, os2_strikeypos;
1767     int16 os2_capheight, os2_xheight;
1768     char os2_vendor[4];
1769     int16 os2_family_class;
1770     uint32 codepages[2];
1771     uint32 unicoderanges[4];
1772 };
1773 
1774 struct ttf_table {
1775     uint32 tag;
1776     uint32 len, maxlen;
1777     uint8 *data;
1778     struct ttf_table *next;
1779     FILE *temp;	/* Temporary storage used during generation */
1780 };
1781 
1782 enum texdata_type { tex_unset, tex_text, tex_math, tex_mathext };
1783 
1784 struct texdata {
1785     enum texdata_type type;
1786     int32 params[22];		/* param[6] has different meanings in normal and math fonts */
1787 };
1788 
1789 struct gasp {
1790     uint16 ppem;
1791     uint16 flags;
1792 };
1793 
1794 struct ff_glyphclasses {
1795     // This matches struct glyphclasses from featurefile.c for now. We may make the references numeric in the future.
1796     // There may be a matching entry as a class elsewhere. For now, the output driver is responsible for eliminating duplicates.
1797     // In the interest of preserving orderings, we shall output from here, checking for value overrides from kerning classes on each kerning group entry.
1798     char *classname, *glyphs;
1799     struct ff_glyphclasses *next;
1800 };
1801 
1802 struct ff_rawoffsets {
1803     // This stores raw offsets as read from kerning.plist.
1804     // FontForge shall output these after native data and shall output only those for which it has not emitted native data.
1805     char *left;
1806     char *right;
1807     int offset;
1808     struct ff_rawoffsets *next;
1809 };
1810 
1811 typedef struct splinefont {
1812     char *fontname, *fullname, *familyname, *weight;
1813     char *familyname_with_timestamp;
1814     char *copyright;
1815     char *filename;				/* sfd name. NULL if we open a font, that's origname */
1816     char *defbasefilename;
1817     char *version;
1818     real italicangle, upos, uwidth;		/* In font info */
1819     int ascent, descent, invalidem; // If invalidem, then we use the format-specific ascent and descent on export.
1820     int uniqueid;				/* Not copied when reading in!!!! */
1821     int glyphcnt, glyphmax;			/* allocated size of glyphs array */
1822     SplineChar **glyphs;
1823     unsigned int changed: 1;
1824     unsigned int changed_since_autosave: 1;
1825     unsigned int changed_since_xuidchanged: 1;
1826     unsigned int display_antialias: 1;
1827     unsigned int display_bbsized: 1;
1828     unsigned int dotlesswarn: 1;		/* User warned that font doesn't have a dotless i character */
1829     unsigned int onlybitmaps: 1;		/* it's a bdf editor, not a postscript editor */
1830     unsigned int serifcheck: 1;			/* Have we checked to see if we have serifs? */
1831     unsigned int issans: 1;			/* We have no serifs */
1832     unsigned int isserif: 1;			/* We have serifs. If neither set then we don't know. */
1833     unsigned int hasvmetrics: 1;		/* We've got vertical metric data and should output vhea/vmtx/VORG tables */
1834     unsigned int loading_cid_map: 1;
1835     unsigned int dupnamewarn: 1;		/* Warn about duplicate names when loading bdf font */
1836     unsigned int encodingchanged: 1;		/* Font's encoding has changed since it was loaded */
1837     unsigned int multilayer: 1;			/* only applies if TYPE3 is set, means this font can contain strokes & fills */
1838 						/*  I leave it in so as to avoid cluttering up code with #ifdefs */
1839     unsigned int strokedfont: 1;
1840     unsigned int new: 1;			/* A new and unsaved font */
1841     unsigned int compacted: 1;			/* only used when opening a font */
1842     unsigned int backedup: 2;			/* 0=>don't know, 1=>no, 2=>yes */
1843     unsigned int use_typo_metrics: 1;		/* The standard says to. But MS */
1844     						/* seems to feel that isn't good */
1845 			                        /* enough and has created a bit */
1846 			                        /* to mean "really use them" */
1847     unsigned int weight_width_slope_only: 1;	/* This bit seems stupid to me */
1848     unsigned int save_to_dir: 1;		/* Loaded from an sfdir collection rather than a simple sfd file */
1849     unsigned int head_optimized_for_cleartype: 1;/* Bit in the 'head' flags field, if unset "East Asian fonts in the Windows Presentation Framework (Avalon) will not be hinted" */
1850     unsigned int ticked: 1;
1851     unsigned int internal_temp: 1;		/* Internal temporary font to be passed to freetype for rasterizing. Don't complain about oddities. Don't generate GPOS/GSUB tables, etc. */
1852     unsigned int complained_about_spiros: 1;
1853     unsigned int use_xuid: 1;			/* Adobe has deprecated these two */
1854     unsigned int use_uniqueid: 1;		/* fields. Mostly we don't want to use them */
1855 	/* 2 bits left */
1856     struct fontviewbase *fv;
1857     struct metricsview *metrics;
1858     enum uni_interp uni_interp;
1859     NameList *for_new_glyphs;
1860     EncMap *map;		/* only used when opening a font to provide original default encoding */
1861     Layer grid;
1862     BDFFont *bitmaps;
1863     char *origname;		/* filename of font file (ie. if not an sfd) */
1864     char *autosavename;
1865     int display_size;		/* a val <0 => Generate our own images from splines, a value >0 => find a bdf font of that size */
1866     struct psdict *private;	/* read in from type1 file or provided by user */
1867     char *xuid;
1868     struct pfminfo pfminfo;
1869     struct ttflangname *names;
1870     char *cidregistry, *ordering;
1871     int supplement;
1872     int subfontcnt;
1873     struct splinefont **subfonts;
1874     struct splinefont *cidmaster;		/* Top level cid font */
1875     float cidversion;
1876 #if HANYANG
1877     struct compositionrules *rules;
1878 #endif
1879     char *comments;	/* Used to be restricted to ASCII, now utf8 */
1880     char *fontlog;
1881     int tempuniqueid;
1882     int top_enc;
1883     uint16 desired_row_cnt, desired_col_cnt;
1884     struct glyphnamehash *glyphnames;
1885     struct ttf_table *ttf_tables, *ttf_tab_saved;
1886 	/* We copy: fpgm, prep, cvt, maxp (into ttf_tables) user can ask for others, into saved*/
1887     char **cvt_names;
1888     /* The end of this array is marked by a special entry: */
1889 #define END_CVT_NAMES ((char *) (~(intpt) 0))
1890     struct instrdata *instr_dlgs;	/* Pointer to all table and character instruction dlgs in this font */
1891     struct shortview *cvt_dlg;
1892     struct kernclasslistdlg *kcld, *vkcld;
1893     struct kernclassdlg *kcd;
1894     struct texdata texdata;
1895     OTLookup *gsub_lookups, *gpos_lookups;
1896     /* Apple morx subtables become gsub, and kern subtables become gpos */
1897     AnchorClass *anchor;
1898     KernClass *kerns, *vkerns;
1899     FPST *possub;
1900     ASM *sm;				/* asm is a keyword */
1901     MacFeat *features;
1902     char *chosenname;			/* Set for files with multiple fonts in them */
1903     struct mmset *mm;			/* If part of a multiple master set */
1904     int16 macstyle;
1905     char *fondname;			/* For use in generating mac families */
1906     /* from the GPOS 'size' feature. design_size, etc. are measured in tenths of a point */
1907     /*  bottom is exclusive, top is inclusive */
1908     /*  if any field is 0, it is undefined. All may be undefined, All may be */
1909     /*  defined, or design_size may be defined without any of the others */
1910     /*  but we can't define the range without defining the other junk */
1911     /*  Name must contain an English language name, may contain others */
1912     uint16 design_size;
1913     uint16 fontstyle_id;
1914     struct otfname *fontstyle_name;
1915     uint16 design_range_bottom, design_range_top;
1916     struct otffeatname *feat_names;
1917     real strokewidth;
1918 /* For GDEF Mark Attachment Class -- used in lookup flags */
1919 /* As usual, class 0 is unused */
1920     int mark_class_cnt;
1921     char **mark_classes;		/* glyph name list */
1922     char **mark_class_names;		/* used within ff, utf8 (the name we've given to this class of marks) */
1923 /* For GDEF Mark Attachment Sets -- used in lookup flags */
1924 /* but here, set 0 is meaningful, since pst_usemarkfilteringset tells us */
1925     int mark_set_cnt;
1926     char **mark_sets;			/* glyph name list */
1927     char **mark_set_names;		/* used within ff, utf8 (the name we've given to this class of marks) */
1928     struct ff_glyphclasses *groups; // This stores arbitrary named character lists for use in kerning or in the feature file.
1929     struct ff_rawoffsets *groupkerns;
1930     struct ff_rawoffsets *groupvkerns;
1931     long long creationtime;		/* seconds since 1970 */
1932     long long modificationtime;
1933     short os2_version;			/* 0 means default rather than the real version 0 */
1934     short compression;			/* If we opened a compressed sfd file, then save it out compressed too */
1935     short gasp_version;			/* 0/1 currently */
1936     short gasp_cnt;
1937     struct gasp *gasp;
1938     struct MATH *MATH;
1939     float sfd_version;			/* Used only when reading in an sfd file */
1940     struct gfi_data *fontinfo;
1941     struct val_data *valwin;
1942 #if !defined(_NO_PYTHON)
1943     void *python_temporary;
1944 #endif
1945     void *python_persistent;		/* If python this will hold a python object, if not python this will hold a string containing a pickled object. We do nothing with it (if not python) except save it back out unchanged */
1946     int python_persistent_has_lists; // This affects whether arrays exist as tuples or as lists (thus allowing us to use tuples for foreign data).
1947     enum loadvalidation_state loadvalidation_state;
1948     LayerInfo *layers;
1949     int layer_cnt;
1950     int display_layer;
1951     struct Base *horiz_base, *vert_base;
1952     Justify *justify;
1953     int extrema_bound;			/* Splines do not count for extrema complaints when the distance between the endpoints is less than or equal to this */
1954     int width_separation;
1955     int sfntRevision;
1956 #define sfntRevisionUnset	0x44445555
1957     int woffMajor;
1958 #define woffUnset		0x4455
1959     int woffMinor;
1960     char *woffMetadata;
1961     real ufo_ascent, ufo_descent;	/* I don't know what these mean, they don't seem to correspond to any other ascent/descent pair, but retain them so round-trip ufo input/output leaves them unchanged */
1962 	    /* ufo_descent is negative */
1963     char *styleMapFamilyName;
1964     struct sfundoes *undoes;
1965     int preferred_kerning; // 1 for U. F. O. native, 2 for feature file, 0 undefined. Input functions shall flag 2, I think. This is now in S. F. D. in order to round-trip U. F. O. consistently.
1966 } SplineFont;
1967 
1968 struct axismap {
1969     int points;	/* size of the next two arrays */
1970     real *blends;	/* between [0,1] ordered so that blend[0]<blend[1]<... */
1971     real *designs;	/* between the design ranges for this axis, typically [1,999] or [6,72] */
1972     real min, def, max;		/* For mac */
1973     struct macname *axisnames;	/* For mac */
1974 };
1975 
1976 struct named_instance {	/* For mac */
1977     real *coords;	/* array[axis], these are in user units */
1978     struct macname *names;
1979 };
1980 
1981 /* I am going to simplify my life and not encourage intermediate designs */
1982 /*  this means I can easily calculate ConvertDesignVector, and don't have */
1983 /*  to bother the user with specifying it. */
1984 /* (NormalizeDesignVector is fairly basic and shouldn't need user help ever) */
1985 /*  (As long as they want piecewise linear) */
1986 /* I'm not going to support intermediate designs at all for apple var tables */
1987 typedef struct mmset {
1988     int axis_count;
1989     char *axes[4];
1990     int instance_count;
1991     SplineFont **instances;
1992     SplineFont *normal;
1993     real *positions;	/* array[instance][axis] saying where each instance lies on each axis */
1994     real *defweights;	/* array[instance] saying how much of each instance makes the normal font */
1995 			/* for adobe */
1996     struct axismap *axismaps;	/* array[axis] */
1997     char *cdv, *ndv;	/* for adobe */
1998     int named_instance_count;
1999     struct named_instance *named_instances;
2000     unsigned int changed: 1;
2001     unsigned int apple: 1;
2002 } MMSet;
2003 
2004 /* mac styles. Useful idea we'll just steal it */
2005 enum style_flags { sf_bold = 1, sf_italic = 2, sf_underline = 4, sf_outline = 8,
2006 	sf_shadow = 0x10, sf_condense = 0x20, sf_extend = 0x40 };
2007 
2008 struct sflist {
2009     SplineFont *sf;
2010     int32 *sizes;
2011     FILE *tempttf;		/* For ttf */
2012     int id;			/* For ttf */
2013     int* ids;			/* One for each size */
2014     BDFFont **bdfs;		/* Ditto */
2015     EncMap *map;
2016     struct sflist *next;
2017     char **former_names;
2018     int len;
2019 };
2020 
2021     /* Used for drawing text with mark to base anchors */
2022 typedef struct anchorpos {
2023     SplineChar *sc;		/* This is the mark being positioned */
2024     int x,y;			/* Its origin should be shifted this much relative to that of the original base char */
2025     AnchorPoint *apm;		/* The anchor point in sc used to position it */
2026     AnchorPoint *apb;		/* The anchor point in the base character against which we are positioned */
2027     int base_index;		/* Index in this array to the base character (-1=> original base char) */
2028     unsigned int ticked: 1;	/* Used as a mark to mark */
2029 } AnchorPos;
2030 
2031 enum ttf_flags {
2032     ttf_flag_shortps           = 1 <<  0,
2033     ttf_flag_nohints           = 1 <<  1,
2034     ttf_flag_applemode         = 1 <<  2,
2035     ttf_flag_pfed_comments     = 1 <<  3,
2036     ttf_flag_pfed_colors       = 1 <<  4,
2037     ttf_flag_otmode            = 1 <<  5,
2038     ttf_flag_glyphmap          = 1 <<  6,
2039     ttf_flag_TeXtable          = 1 <<  7,
2040     ttf_flag_ofm               = 1 <<  8,
2041     ttf_flag_oldkern           = 1 <<  9, // never set in conjunction with applemode
2042     ttf_flag_noFFTMtable       = 1 << 10,
2043     ttf_flag_pfed_lookupnames  = 1 << 11,
2044     ttf_flag_pfed_guides       = 1 << 12,
2045     ttf_flag_pfed_layers       = 1 << 13,
2046     ttf_flag_symbol            = 1 << 14,
2047     ttf_flag_dummyDSIG         = 1 << 15,
2048     ttf_native_kern            = 1 << 16, // This applies mostly to U. F. O. right now.
2049     ttf_flag_oldkernmappedonly = 1 << 29, // Allow only mapped glyphs in the old-style "kern" table, required for Windows compatibility
2050     ttf_flag_nomacnames        = 1 << 30  // Don't autogenerate mac name entries
2051 };
2052 enum ttc_flags { ttc_flag_trymerge=0x1, ttc_flag_cff=0x2 };
2053 enum openflags { of_fstypepermitted=1, /*of_askcmap=2,*/ of_all_glyphs_in_ttc=4,
2054 	of_fontlint=8, of_hidewindow=0x10, of_all_tables=0x20 };
2055 enum ps_flags { ps_flag_nohintsubs = 0x10000, ps_flag_noflex=0x20000,
2056 		    ps_flag_nohints = 0x40000, ps_flag_restrict256=0x80000,
2057 		    ps_flag_afm = 0x100000, ps_flag_pfm = 0x200000,
2058 		    ps_flag_tfm = 0x400000,
2059 		    ps_flag_round = 0x800000,
2060 /* CFF fonts are wrapped up in some postscript sugar -- unless they are to */
2061 /*  go into a pdf file or an otf font */
2062 		    ps_flag_nocffsugar = 0x1000000,
2063 /* in type42 cid fonts we sometimes want an identity map from gid to cid */
2064 		    ps_flag_identitycidmap = 0x2000000,
2065 		    ps_flag_afmwithmarks = 0x4000000,
2066 		    ps_flag_noseac = 0x8000000,
2067 		    ps_flag_outputfontlog = 0x10000000,
2068 		    ps_flag_mask = (ps_flag_nohintsubs|ps_flag_noflex|
2069 			ps_flag_afm|ps_flag_pfm|ps_flag_tfm|ps_flag_round)
2070 		};
2071 
2072 struct compressors { char *ext, *decomp, *recomp; };
2073 #define COMPRESSORS_EMPTY { NULL, NULL, NULL }
2074 extern struct compressors compressors[];
2075 
2076 enum archive_list_style { ars_tar, ars_zip };
2077 
2078 struct archivers {
2079     char *ext, *unarchive, *archive, *listargs, *extractargs, *appendargs;
2080     enum archive_list_style ars;
2081 };
2082 #define ARCHIVERS_EMPTY { NULL, NULL, NULL, NULL, NULL, NULL, 0 }
2083 
2084 struct fontdict;
2085 struct pschars;
2086 struct findsel;
2087 struct charprocs;
2088 struct enc;
2089 
2090 #define chunkalloc(size)	calloc(1,size)
2091 #define chunkfree(item,size)	free(item)
2092 
2093 extern char *strconcat(const char *str, const char *str2);
2094 
2095 extern void SFApplyFeatureFile(SplineFont *sf,FILE *file,char *filename);
2096 /* Any additions to this enum should be accounted for in
2097  * splinechar.c:VSMaskFromFormat() . There are also tables
2098  * indexed by values of this enum scattered throughout the
2099  * code
2100  */
2101 enum fontformat { ff_pfa, ff_pfb, ff_pfbmacbin, ff_multiple, ff_mma, ff_mmb,
2102 	ff_ptype3, ff_ptype0, ff_cid, ff_cff, ff_cffcid,
2103 	ff_type42, ff_type42cid,
2104 	ff_ttf, ff_ttfsym, ff_ttfmacbin, ff_ttc, ff_ttfdfont, ff_otf, ff_otfdfont,
2105 	ff_otfcid, ff_otfciddfont, ff_svg, ff_ufo, ff_ufo2, ff_ufo3, ff_woff, ff_woff2, ff_none };
2106 #define isttf_ff(ff) ((ff)>=ff_ttf && (ff)<=ff_ttfdfont)
2107 #define isttflike_ff(ff) (((ff)>=ff_ttf && (ff)<=ff_otfdfont) || (ff)==ff_woff2)
2108 extern struct pschars *SplineFont2ChrsSubrs(SplineFont *sf, int iscjk,
2109 	struct pschars *subrs,int flags,enum fontformat format,int layer);
2110 struct cidbytes;
2111 struct fd2data;
2112 struct ttfinfo;
2113 struct alltabs;
2114 
2115 typedef struct growbuf {
2116     unsigned char *pt;
2117     unsigned char *base;
2118     unsigned char *end;
2119 } GrowBuf;
2120 extern void GrowBuffer(GrowBuf *gb);
2121 
2122 struct glyphdata;
2123 extern struct pschars *CID2ChrsSubrs(SplineFont *cidmaster,struct cidbytes *cidbytes,int flags,int layer);
2124 enum bitmapformat { bf_bdf, bf_ttf, bf_sfnt_dfont, bf_sfnt_ms, bf_otb,
2125 	bf_nfntmacbin, /*bf_nfntdfont, */bf_fon, bf_fnt, bf_palm,
2126 	bf_ptype3,
2127 	bf_none };
2128 extern const char *GetAuthor(void);
2129 extern int WriteUFOFont(const char *fontname, SplineFont *sf, enum fontformat format, int flags, const EncMap *enc,int layer, int version);
2130 extern int SLIContainsR2L(SplineFont *sf,int sli);
2131 extern void SFFindNearTop(SplineFont *);
2132 extern void SFRestoreNearTop(SplineFont *);
2133 extern const char *_GetModifiers(const char *fontname, const char *familyname, const char *weight);
2134 extern const char *SFGetModifiers(const SplineFont *sf);
2135 extern const unichar_t *_uGetModifiers(const unichar_t *fontname, const unichar_t *familyname,
2136 	const unichar_t *weight);
2137 extern void ttfdumpbitmap(SplineFont *sf,struct alltabs *at,int32 *sizes);
2138 extern void SplineFontSetUnChanged(SplineFont *sf);
2139 
2140 extern bool RealNear(real a,real b);
2141 
2142 
2143 extern void UndoesFree(Undoes *undo);
2144 extern void StemInfosFree(StemInfo *h);
2145 extern void StemInfoFree(StemInfo *h);
2146 extern void SCOrderAP(SplineChar *sc);
2147 extern int AnchorClassesNextMerge(AnchorClass *ac);
2148 extern void AnchorClassMerge(SplineFont *sf,AnchorClass *into,AnchorClass *from);
2149 extern void SCInsertPST(SplineChar *sc,PST *new_);
2150 extern void PSTFree(PST *lig);
2151 extern uint16 PSTDefaultFlags(enum possub_type type,SplineChar *sc );
2152 extern StemInfo *StemInfoCopy(StemInfo *h);
2153 extern void SPChangePointType(SplinePoint *sp, int pointtype);
2154 
2155 struct lookup_cvt { OTLookup *from, *to; int old;};
2156 struct sub_cvt { struct lookup_subtable *from, *to; int old;};
2157 struct ac_cvt { AnchorClass *from, *to; int old;};
2158 
2159 struct sfmergecontext {
2160     SplineFont *sf_from, *sf_to;
2161     int lcnt;
2162     struct lookup_cvt *lks;
2163     int scnt;
2164     struct sub_cvt *subs;
2165     int acnt;
2166     struct ac_cvt *acs;
2167     char *prefix;
2168     int preserveCrossFontKerning;
2169     int lmax;
2170 };
2171 extern void AltUniRemove(SplineChar *sc,int uni);
2172 extern void AltUniAdd(SplineChar *sc,int uni);
2173 extern void AltUniAdd_DontCheckDups(SplineChar *sc,int uni);
2174 extern SplineChar *SplineCharCreate(int layer_cnt);
2175 extern void SCAddRef(SplineChar *sc,SplineChar *rsc,int layer, real xoff, real yoff);
2176 extern void SplineCharFree(SplineChar *sc);
2177 extern void ScriptLangListFree(struct scriptlanglist *sl);
2178 
2179 enum pconvert_flags {
2180 	// Point selection (mutually exclusive)
2181 	pconvert_flag_none = 0x01,
2182 	pconvert_flag_all = 0x02,
2183 	pconvert_flag_smooth = 0x04,
2184 	pconvert_flag_incompat = 0x08,
2185 	// Conversion modes (mutually exclusive)
2186 	pconvert_flag_by_geom = 0x100,
2187 	pconvert_flag_force_type = 0x200,
2188 	pconvert_flag_downgrade = 0x400,
2189 	pconvert_flag_check_compat = 0x0800,
2190 	// Additional
2191 	pconvert_flag_hvcurve = 0x4000
2192 };
2193 
2194 #if 1
2195 // These relate to experimental support for U. F. O. groups.
2196 #define GROUP_NAME_KERNING_UFO 1
2197 #define GROUP_NAME_KERNING_FEATURE 2
2198 #define GROUP_NAME_VERTICAL 4 // Otherwise horizontal.
2199 #define GROUP_NAME_RIGHT 8 // Otherwise left (or above).
2200 #endif // 1
2201 extern void MMSetFree(MMSet *mm);
2202 extern void SFRemoveUndoes(SplineFont *sf,uint8 *selected,EncMap *map);
2203 extern void SplineRefigure(Spline *spline);
2204 extern void SPLCategorizePoints(SplinePointList *spl);
2205 extern int _SPLCategorizePoints(SplinePointList *spl, int flags);
2206 extern SplinePointList *SplinePointListCopy(const SplinePointList *base);
2207 /* The order of the enum elements below doesn't make much sense, but it's done*/
2208 /*  this way to preserve binary compatibility */
2209 enum transformPointType { tpt_OnlySelected, tpt_AllPoints, tpt_OnlySelectedInterpCPs };
2210 /*
2211  * As SplinePointListTransform() does a few things, this is a mask to selectively be
2212  * able to disable some of them.
2213  */
2214 enum transformPointMask {
2215     tpmask_dontFixControlPoints = 1 << 1,
2216     tpmask_operateOnSelectedBCP = 1 << 2,
2217     tpmask_dontTrimValues = 1 << 3
2218 };
2219 extern SplinePointList *SplinePointListTransform(SplinePointList *base, real transform[6], enum transformPointType allpoints );
2220 extern void SCReinstanciateRef(SplineChar *sc,SplineChar *rsc,int layer);
2221 extern SplineChar *MakeDupRef(SplineChar *base, int local_enc, int uni_enc);
2222 extern void BDFClut(BDFFont *bdf, int linear_scale);
2223 struct xlfd_components {
2224     char foundry[80];
2225     char family[100];
2226     char weight[80];
2227     char slant[40];
2228     char setwidth[50];
2229     char add_style[50];
2230     int pixel_size;
2231     int point_size;
2232     int res_x;
2233     int res_y;
2234     char spacing[40];
2235     int avg_width;
2236     char cs_reg[80];		/* encoding */
2237     char cs_enc[80];		/* encoding version? */
2238     int char_cnt;
2239 };
2240 struct std_bdf_props {
2241     const char *name;
2242     int type;
2243     int defaultable;
2244 };
2245 #define STD_BDF_PROPS_EMPTY { NULL, 0, 0 }
2246 
2247 extern int CubicSolve(const Spline1D *sp,bigreal sought,extended ts[3]);
2248 /* Uses an algebraic solution */
2249 extern extended SplineSolve(const Spline1D *sp, real tmin, real tmax, extended sought_y);
2250 /* Tries to fixup rounding errors that crept in to the solution */
2251 extern extended SplineSolveFixup(const Spline1D *sp, real tmin, real tmax, extended sought_y);
2252 /* Uses an iterative approximation */
2253 /* Uses an iterative approximation and then tries to fix things up */
2254 
2255 
2256 #define CURVATURE_ERROR	INFINITY
2257 
2258 extern bigreal SplineLength(Spline *spline);
2259 extern int SplineIsLinear(Spline *spline);
2260 extern void SFOrderBitmapList(SplineFont *sf);
2261 
2262 extern Spline *SplineMake(SplinePoint *from, SplinePoint *to, int order2);
2263 extern Spline *SFSplineMake(SplineFont *sf,SplinePoint *from, SplinePoint *to);
2264 
2265 
2266 extern double BlueScaleFigure(struct psdict *private_,real bluevalues[], real otherblues[]);
2267 
2268 typedef struct bluezone {
2269     real base;
2270     int cvtindex;
2271     real family_base;      /* NaN if none */
2272     int family_cvtindex;
2273     real overshoot;        /* relative to baseline, NOT to base */
2274     int highest;           /* used in autoinstructing for HStem positioning */
2275     int lowest;            /* as above */
2276 } BlueZone;
2277 
2278 typedef struct stdstem {
2279     real width;            /* -1 if none */
2280     int cvtindex;
2281     struct stdstem *snapto;/* NULL means stem isn't snapped to any other */
2282     int stopat;            /* at which ppem stop snapping to snapto */
2283 } StdStem;
2284 
2285 typedef struct globalinstrct {
2286     SplineFont *sf;
2287     int layer;
2288     BlueData *bd;
2289     double fudge;
2290 
2291     /* Did we initialize the tables needed? 'maxp' is skipped because */
2292     /* its initialization always succeeds. */
2293     int cvt_done;
2294     int fpgm_done;
2295     int prep_done;
2296 
2297     /* PS private data with truetype-specific information added */
2298     BlueZone blues[12];    /* like in BlueData */
2299     int      bluecnt;
2300     StdStem  stdhw;
2301     StdStem  *stemsnaph;   /* StdHW excluded */
2302     int      stemsnaphcnt;
2303     StdStem  stdvw;
2304     StdStem  *stemsnapv;   /* StdVW excluded */
2305     int      stemsnapvcnt;
2306 } GlobalInstrCt;
2307 
2308 extern void InitGlobalInstrCt( GlobalInstrCt *gic,SplineFont *sf,int layer,
2309 	BlueData *bd );
2310 extern void FreeGlobalInstrCt( GlobalInstrCt *gic );
2311 extern void NowakowskiSCAutoInstr( GlobalInstrCt *gic,SplineChar *sc );
2312 extern void CVT_ImportPrivate(SplineFont *sf);
2313 
2314 extern void SplineFontAutoHint( SplineFont *sf, int layer);
2315 extern int SCDrawsSomething(SplineChar *sc);
2316 extern int SCSetMetaData(SplineChar *sc,const char *name,int unienc,
2317 	const char *comment);
2318 
2319 extern char* DumpSplineFontMetadata( SplineFont *sf );
2320 
2321 
2322 enum ttfflags { ttf_onlystrikes=1, ttf_onlyonestrike=2, ttf_onlykerns=4, ttf_onlynames=8 };
2323 extern SplineFont *SFReadUFO(char *filename,int flags);
2324 extern SplineFont *LoadSplineFont(const char *filename,enum openflags);
2325 extern SplineFont *_ReadSplineFont(FILE *file, const char *filename, enum openflags openflags);
2326 extern SplineFont *ReadSplineFont(const char *filename,enum openflags);	/* Don't use this, use LoadSF instead */
2327 extern void ArchiveCleanup(char *archivedir);
2328 extern char *Unarchive(char *name, char **_archivedir);
2329 extern char *Decompress(char *name, int compression);
2330 extern uint16 MacStyleCode( SplineFont *sf, uint16 *psstyle );
2331 extern char **NamesReadUFO(char *filename);
2332 extern char *SFSubfontnameStart(char *fname);
2333 
2334 
2335 extern const char *UnicodeRange(int unienc);
2336 extern SplineChar *SCBuildDummy(SplineChar *dummy,SplineFont *sf,EncMap *map,int i);
2337 extern SplineChar *SFMakeChar(SplineFont *sf,EncMap *map,int i);
2338 extern char *AdobeLigatureFormat(char *name);
2339 extern uint32 LigTagFromUnicode(int uni);
2340 extern void SCLigCaretheck(SplineChar *sc,int clean);
2341 
2342 extern void SCUndoSetLBearingChange(SplineChar *sc,int lb);
2343 
2344 
2345 
2346 extern SplineSet *SplinePointListInterpretGlif(SplineFont *sf,char *filename,char *memory, int memlen, int em_size, int ascent,int stroked);
2347 #define UNDEFINED_WIDTH	-999999
2348 struct pscontext {
2349     int is_type2;
2350     int painttype;
2351     int instance_count;
2352     real blend_values[17];
2353     int blend_warn;
2354 };
2355 
2356 extern int NameToEncoding(SplineFont *sf,EncMap *map,const char *uname);
2357 extern SplineChar *SFGetOrMakeChar(SplineFont *sf, int unienc, const char *name );
2358 extern SplineChar *SFGetOrMakeCharFromUnicode( SplineFont *sf, EncMap *map, int ch );
2359 
2360 extern int DoAutoRecovery(int);
2361 typedef void (*DoAutoRecoveryPostRecoverFunc)(SplineFont *sf);
2362 
2363 extern int SFPrivateGuess(SplineFont *sf,int layer, struct psdict *private,
2364 	char *name, int onlyone);
2365 
2366 extern void SFRemoveLayer(SplineFont *sf,int l);
2367 extern void SFAddLayer(SplineFont *sf,char *name,int order2, int background);
2368 extern void SFLayerSetBackground(SplineFont *sf,int layer,int is_back);
2369 
2370 extern void SplineSetsRound2Int(SplineSet *spl,real factor,int inspiro,int onlysel);
2371 extern void SCRound2Int(SplineChar *sc,int layer, real factor);
2372 
2373 extern void SFFlatten(SplineFont **cidmaster);
2374 
2375 extern void SCCopyLayerToLayer(SplineChar *sc, int from, int to,int doclear);
2376 
2377 extern int hasFreeType(void);
2378 extern int hasFreeTypeDebugger(void);
2379 extern int hasFreeTypeByteCode(void);
2380 extern int FreeTypeAtLeast(int major, int minor, int patch);
2381 extern char *FreeTypeStringVersion(void);
2382 extern void doneFreeType(void);
2383 extern void *_FreeTypeFontContext(SplineFont *sf,SplineChar *sc,struct fontviewbase *fv,
2384 	int layer, enum fontformat ff,int flags,void *shared_ftc);
2385 extern void *FreeTypeFontContext(SplineFont *sf,SplineChar *sc,struct fontviewbase *fv,int layer);
2386 extern BDFFont *SplineFontFreeTypeRasterize(void *freetypecontext,int pixelsize,int depth);
2387 extern BDFChar *SplineCharFreeTypeRasterize(void *freetypecontext,int gid,
2388 	int ptsize, int dpi,int depth);
2389 extern void FreeTypeFreeContext(void *freetypecontext);
2390 extern SplineSet *FreeType_GridFitChar(void *single_glyph_context,
2391 	int enc, real ptsizey, real ptsizex, int dpi, uint16 *width,
2392 	SplineChar *sc, int depth, int scaled);
2393 extern struct freetype_raster *FreeType_GetRaster(void *single_glyph_context,
2394 	int enc, real ptsizey, real ptsizex, int dpi,int depth);
2395 extern BDFChar *SplineCharFreeTypeRasterizeNoHints(SplineChar *sc,int layer,
2396 	int ptsize, int dpi,int depth);
2397 extern BDFFont *SplineFontFreeTypeRasterizeNoHints(SplineFont *sf,int layer,
2398 	int pixelsize,int depth);
2399 extern void FreeType_FreeRaster(struct freetype_raster *raster);
2400 struct TT_ExecContextRec_;
2401 extern struct freetype_raster *DebuggerCurrentRaster(struct  TT_ExecContextRec_ *exc,int depth);
2402 
2403 
2404 extern AnchorPos *AnchorPositioning(SplineChar *sc,unichar_t *ustr,SplineChar **sstr );
2405 
2406 extern int  SF_CloseAllInstrs(SplineFont *sf);
2407 extern int  SSTtfNumberPoints(SplineSet *ss);
2408 extern int  SCNumberPoints(SplineChar *sc,int layer);
2409 extern int  SCPointsNumberedProperly(SplineChar *sc,int layer);
2410 
2411 extern int SFRenameTheseFeatureTags(SplineFont *sf, uint32 tag, int sli, int flags,
2412 	uint32 totag, int tosli, int toflags, int ismac);
2413 extern int SFRemoveUnusedNestedFeatures(SplineFont *sf);
2414 
2415 
2416 
2417 extern struct macsetting *FindMacSetting(SplineFont *sf, int feat, int set,struct macsetting **secondary);
2418 
2419 
2420 
2421 extern int BpColinear(BasePoint *first, BasePoint *mid, BasePoint *last);
2422 extern int BpWithin(BasePoint *first, BasePoint *mid, BasePoint *last);
2423     /* Colinear & between */
2424 
2425 extern char *ToAbsolute(char *filename);
2426 
2427 # if HANYANG
2428 extern void SFDDumpCompositionRules(FILE *sfd,struct compositionrules *rules);
2429 extern struct compositionrules *SFDReadCompositionRules(FILE *sfd);
2430 extern void SFModifyComposition(SplineFont *sf);
2431 extern void SFBuildSyllables(SplineFont *sf);
2432 # endif
2433 
2434 
2435 
2436 extern void SFSetModTime(SplineFont *sf);
2437 
2438 
2439 
2440 extern struct lookup_subtable *SFFindLookupSubtable(SplineFont *sf,const char *name);
2441 extern int FeatureTagInFeatureScriptList(uint32 tag, FeatureScriptLangList *fl);
2442 
2443 extern void SplinePointRound(SplinePoint *,real);
2444 
2445 extern KernClass *SFFindKernClass(SplineFont *sf,SplineChar *first,SplineChar *last,
2446 	int *index,int allow_zero);
2447 extern KernClass *SFFindVKernClass(SplineFont *sf,SplineChar *first,SplineChar *last,
2448 	int *index,int allow_zero);
2449 
2450 extern void SCClearRounds(SplineChar *sc,int layer);
2451 extern void MDReplace(MinimumDistance *md,SplineSet *old,SplineSet *rpl);
2452 extern void SCSynchronizeWidth(SplineChar *sc,real newwidth, real oldwidth,struct fontviewbase *fv);
2453 extern RefChar *HasUseMyMetrics(SplineChar *sc,int layer);
2454 extern void SCSynchronizeLBearing(SplineChar *sc,real off,int layer);
2455 extern void RevertedGlyphReferenceFixup(SplineChar *sc, SplineFont *sf);
2456 
2457 extern void SFUntickAll(SplineFont *sf);
2458 
2459 
2460 extern int _ExportGlif(FILE *glif,SplineChar *sc,int layer,int version);
2461 
2462 extern void SCCopyWidth(SplineChar *sc,enum undotype);
2463 extern void SCClearBackground(SplineChar *sc);
2464 extern void BackgroundImageTransform(SplineChar *sc, ImageList *img,real transform[6]);
2465 extern int SFIsDuplicatable(SplineFont *sf, SplineChar *sc);
2466 
2467 extern void SCClearLayer(SplineChar *sc,int layer);
2468 extern void SCClearContents(SplineChar *sc,int layer);
2469 extern void SCClearAll(SplineChar *sc,int layer);
2470 
2471 #if !defined(_NO_PYTHON)
2472 extern void FontForge_InitializeEmbeddedPython(void);
2473 extern void FontForge_FinalizeEmbeddedPython(void);
2474 extern void PyFF_ErrorString(const char *msg,const char *str);
2475 extern void PyFF_ErrorF3(const char *frmt, const char *str, int size, int depth);
2476 extern void PyFF_Stdin(void);
2477 extern void PyFF_Main(int argc,char **argv,int start);
2478 extern void PyFF_ScriptFile(struct fontviewbase *fv,SplineChar *sc,char *filename);
2479 extern void PyFF_ScriptString(struct fontviewbase *fv,SplineChar *sc,int layer,char *str);
2480 extern void PyFF_FreeFV(struct fontviewbase *fv);
2481 extern void PyFF_FreeSC(SplineChar *sc);
2482 void PyFF_FreeSCLayer(SplineChar *sc, int layer);
2483 extern void PyFF_FreeSF(SplineFont *sf);
2484 extern void PyFF_FreePythonPersistent(void *python_persistent);
2485 extern void PyFF_ProcessInitFiles(void);
2486 extern char *PyFF_PickleMeToString(void *pydata);
2487 extern void *PyFF_UnPickleMeToObjects(char *str);
2488 struct _object;		/* Python Object */
2489 extern void PyFF_CallDictFunc(struct _object *dict,const char *key,const char *argtypes, ... );
2490 #endif
2491 
2492 
2493 
2494 
2495 extern struct math_constants_descriptor {
2496     char *ui_name;
2497     char *script_name;
2498     int offset;
2499     int devtab_offset;
2500     char *message;
2501     int new_page;
2502 } math_constants_descriptor[];
2503 
2504 #define MATH_CONSTANTS_DESCRIPTOR_EMPTY { NULL, NULL, 0, 0, NULL, 0 }
2505 
2506 extern const char *knownweights[], *realweights[], **noticeweights[];
2507 
2508 extern int BPTooFar(BasePoint *bp1, BasePoint *bp2);
2509 extern StemInfo *SCHintOverlapInMask(SplineChar *sc,HintMask *hm);
2510 extern char *VSErrorsFromMask(int mask,int private_mask);
2511 extern int SCValidate(SplineChar *sc, int layer, int force);
2512 extern AnchorClass *SCValidateAnchors(SplineChar *sc);
2513 extern void SCTickValidationState(SplineChar *sc,int layer);
2514 extern int ValidatePrivate(SplineFont *sf);
2515 extern int SFValidate(SplineFont *sf, int layer, int force);
2516 extern int VSMaskFromFormat(SplineFont *sf, int layer, enum fontformat format);
2517 
2518 extern char *RandomParaFromScript(uint32 script, uint32 *lang, SplineFont *sf);
2519 
2520 extern void PatternSCBounds(SplineChar *sc,DBounds *b);
2521 
2522 extern char *SFDefaultImage(SplineFont *sf,char *filename);
2523 extern void SCClearInstrsOrMark(SplineChar *sc, int layer, int complain);
2524 extern void instrcheck(SplineChar *sc,int layer);
2525 extern void TTFPointMatches(SplineChar *sc,int layer,int top);
2526 
2527 extern bigreal SFCapHeight(SplineFont *sf, int layer, int return_error);
2528 extern bigreal SFXHeight(SplineFont *sf, int layer, int return_error);
2529 extern bigreal SFAscender(SplineFont *sf, int layer, int return_error);
2530 extern bigreal SFDescender(SplineFont *sf, int layer, int return_error);
2531 
2532 extern void SCRemoveKern(SplineChar* sc);
2533 extern void SCRemoveVKern(SplineChar* sc);
2534 
2535 /**
2536  * Return falise if the container does not contain "sought"
2537  * Return true if sought is in the container.
2538  */
2539 extern int SplinePointListContains( SplinePointList* container, SplinePointList* sought );
2540 
2541 /**
2542  * Return falise if the container does not contain the single splint point "sp",
2543  * Return true if "sp" is in the container.
2544  */
2545 extern int SplinePointListContainsPoint( SplinePointList* container, SplinePoint* sp );
2546 
2547 /**
2548  * Visitor for SPLFirstVisitSplines()
2549  */
2550 typedef void (*SPLFirstVisitSplinesVisitor)( SplinePoint* splfirst, Spline* s, void* udata );
2551 
2552 /**
2553  * Visitor Function: print debug information about each spline
2554  *
2555  * Visitor for SPLFirstVisit()
2556  */
2557 extern void SPLFirstVisitorDebug(SplinePoint* splfirst, Spline* spline, void* udata );
2558 
2559 /**
2560  * Visitor Function: print debug information about the current
2561  * selection state including the secondary BCP selection for each
2562  * spline
2563  *
2564  * Visitor for SPLFirstVisit()
2565  */
2566 extern void SPLFirstVisitorDebugSelectionState(SplinePoint* splfirst, Spline* spline, void* udata );
2567 
2568 /**
2569  * Given a SplinePointList* that you want to visit each spline in the
2570  * iteration is not as simple as it could be, so you can call this
2571  * function passing spl->first as 'splfirst' and a visitor function
2572  * which will see each spline in the splfirst colleciton.
2573  *
2574  * For debug, you can pass SPLFirstVisitorDebug which will print
2575  * information for each item in the splfirst collection.
2576  *
2577  * You can pass any arbitrary data in as udata and SPLFirstVisit()
2578  * will pass that udata to your visitor function without change. If
2579  * you want a return value from your visitor, pass a pointer to a
2580  * struct as udata. eg:
2581  *
2582  * typedef struct SPLFirstVisitorFoundSoughtDataS
2583  * {
2584  *    SplinePoint* sought;
2585  *    int found;
2586  * } SPLFirstVisitorFoundSoughtData;
2587  *
2588  * // ...
2589  *
2590  *	SPLFirstVisitorFoundSoughtData d;
2591  *	d.sought = sought;
2592  *	d.found  = 0;
2593  *	SPLFirstVisit( spl->first, SPLFirstVisitorFoundSought, &d );
2594  *	if( d.found )
2595  *           return 1;
2596  *
2597  */
2598 extern void SPLFirstVisitSplines( SplinePoint* splfirst, SPLFirstVisitSplinesVisitor f, void* udata );
2599 
2600 /**
2601  * Visitor for SPLFirstVisitPoints()
2602  */
2603 typedef void (*SPLFirstVisitPointsVisitor)( SplinePoint* splfirst, Spline* s, SplinePoint* sp, void* udata );
2604 
2605 /**
2606  * Visit all the SplinePoints on the spline starting at splfirst.
2607  */
2608 extern void SPLFirstVisitPoints( SplinePoint* splfirst, SPLFirstVisitPointsVisitor f, void* udata );
2609 
2610 
2611 
2612 /**
2613  * Applies a visitor to the container and returns false if no point in the SPL
2614  * has an x coordinate of 'x'.
2615  */
2616 extern SplinePoint* SplinePointListContainsPointAtX( SplinePointList* container, real x );
2617 extern SplinePoint* SplinePointListContainsPointAtY( SplinePointList* container, real y );
2618 extern SplinePoint* SplinePointListContainsPointAtXY( SplinePointList* container, real x, real y );
2619 
2620 
2621 /**
2622  * True if the spline with from/to is part of the guide splines.
2623  *
2624  * Handy for telling if the user has just clicked on a guide for example,
2625  * you might want to also check the active layer first with cv->b.drawmode == dm_grid
2626  */
2627 extern bool isSplinePointPartOfGuide( SplineFont *sf, SplinePoint *sp );
2628 
2629 
2630 extern void debug_printHint( StemInfo *h, char* msg );
2631 
2632 #if defined(_WIN32) || defined(__HAIKU__)
2633 #define BAD_LOCALE_HACK
2634 typedef char* locale_t;
2635 #define LC_GLOBAL_LOCALE ((locale_t)-1)
2636 #define LC_ALL_MASK LC_ALL
2637 #define LC_COLLATE_MASK LC_COLLATE
2638 #define LC_CTYPE_MASK LC_CTYPE
2639 #define LC_MONETARY_MASK LC_MONETARY
2640 #define LC_NUMERIC_MASK LC_NUMERIC
2641 #define LC_TIME_MASK LC_TIME
2642 #endif
2643 
switch_to_c_locale(locale_t * tmplocale_p,locale_t * oldlocale_p)2644 static inline void switch_to_c_locale(locale_t * tmplocale_p, locale_t * oldlocale_p) {
2645 #ifndef BAD_LOCALE_HACK
2646   *tmplocale_p = newlocale(LC_NUMERIC_MASK, "C", NULL);
2647   if (*tmplocale_p == NULL) fprintf(stderr, "Failed to create temporary locale.\n");
2648   else if ((*oldlocale_p = uselocale(*tmplocale_p)) == NULL) {
2649     fprintf(stderr, "Failed to change locale.\n");
2650     freelocale(*tmplocale_p); *tmplocale_p = NULL;
2651   }
2652 #else
2653   // Yes, it is dirty. But so is an operating system that doesn't support threaded locales.
2654   *oldlocale_p = (locale_t)copy(setlocale(LC_NUMERIC_MASK, "C"));
2655   if (*oldlocale_p == NULL) fprintf(stderr, "Failed to change locale.\n");
2656 #endif
2657 }
2658 
switch_to_old_locale(locale_t * tmplocale_p,locale_t * oldlocale_p)2659 static inline void switch_to_old_locale(locale_t * tmplocale_p, locale_t * oldlocale_p) {
2660 #ifndef BAD_LOCALE_HACK
2661   if (*oldlocale_p != NULL) { uselocale(*oldlocale_p); } else { uselocale(LC_GLOBAL_LOCALE); }
2662   *oldlocale_p = NULL; // This ends the lifecycle of the temporary old locale storage.
2663   if (*tmplocale_p != NULL) { freelocale(*tmplocale_p); *tmplocale_p = NULL; }
2664 #else
2665   if (*oldlocale_p != NULL) {
2666     setlocale(LC_NUMERIC_MASK, (char*)(*oldlocale_p));
2667     free((char*)(*oldlocale_p));
2668     *oldlocale_p = NULL;
2669   }
2670 #endif
2671 }
2672 
newlocale_hack(int category_mask,const char * locale,locale_t base)2673 static inline locale_t newlocale_hack(int category_mask, const char *locale, locale_t base) {
2674   // Note that, in the interest of minimizing the hack, we drop the category mask on Wingdows.
2675 #ifndef BAD_LOCALE_HACK
2676   return newlocale(category_mask, locale, base);
2677 #else
2678   return (locale_t)copy(locale);
2679 #endif
2680 }
2681 
uselocale_hack(locale_t dataset)2682 static inline locale_t uselocale_hack(locale_t dataset) {
2683 #ifndef BAD_LOCALE_HACK
2684   return uselocale(dataset);
2685 #else
2686   return (locale_t)copy(setlocale(LC_ALL_MASK, (char*)dataset));
2687 #endif
2688 }
2689 
freelocale_hack(locale_t dataset)2690 static inline void freelocale_hack(locale_t dataset) {
2691 #ifndef BAD_LOCALE_HACK
2692   freelocale(dataset);
2693 #else
2694   if (dataset != NULL) { free(dataset); }
2695 #endif
2696 }
2697 
2698 #if 0
2699 #define DECLARE_TEMP_LOCALE() char oldloc[25];
2700 #define SWITCH_TO_C_LOCALE() strncpy( oldloc,setlocale(LC_NUMERIC,NULL),24 ); oldloc[24]='\0'; setlocale(LC_NUMERIC,"C");
2701 #define SWITCH_TO_OLD_LOCALE() setlocale(LC_NUMERIC,oldloc);
2702 #else
2703 #define DECLARE_TEMP_LOCALE() locale_t tmplocale; locale_t oldlocale; // Declare temporary locale storage.
2704 #define SWITCH_TO_C_LOCALE() switch_to_c_locale(&tmplocale, &oldlocale); // Switch to the C locale temporarily and cache the old locale.
2705 #define SWITCH_TO_OLD_LOCALE() switch_to_old_locale(&tmplocale, &oldlocale); // Switch to the cached locale.
2706 #endif
2707 
2708 
2709 
2710 #endif /* FONTFORGE_SPLINEFONT_H */
2711