1 /*
2  * Copyright 2014 Adobe Systems Incorporated (http://www.adobe.com/).
3  * All Rights Reserved.
4  *
5  * This software is licensed as OpenSource, under the Apache License, Version
6  * 2.0.
7  * This license is available at: http://opensource.org/licenses/Apache-2.0.
8  */
9 
10 /* See the discussion in the function definition for:
11  control.c:Blues()
12  static void Blues()
13  */
14 
15 #ifndef AC_AC_H_
16 #define AC_AC_H_
17 
18 #include "psautohint.h"
19 
20 #include "logging.h"
21 #include "memory.h"
22 
23 
24 /* widely used definitions */
25 
26 /* values for HintSeg.sType */
27 #define sLINE (0)
28 #define sBEND (1)
29 #define sCURVE (2)
30 #define sGHOST (3)
31 
32 /* values for PathElt.type */
33 #define MOVETO (0)
34 #define LINETO (1)
35 #define CURVETO (2)
36 #define CLOSEPATH (3)
37 
38 /* values for pathelt control points */
39 #define cpStart (0)
40 #define cpCurve1 (1)
41 #define cpCurve2 (2)
42 #define cpEnd (3)
43 
44 /* widths of ghost bands */
45 #define botGhst (-21)
46 #define topGhst (-20)
47 
48 /* structures */
49 
50 /* glyph point coordinates */
51 typedef struct {
52    Fixed x, y;
53    } Cd;
54 
55 typedef struct {
56   int16_t limit;
57   Fixed feps;
58   void (*report)(Cd);
59   Cd ll, ur;
60   Fixed llx, lly;
61   } FltnRec;
62 
63 typedef struct _hintseg {
64   struct _hintseg *sNxt;
65     /* points to next HintSeg in list */
66     /* separate lists for top, bottom, left, and right segments */
67   Fixed sLoc, sMax, sMin;
68     /* sLoc is X loc for vertical seg, Y loc for horizontal seg */
69     /* sMax and sMin give Y extent for vertical seg, X extent for horizontal */
70     /* i.e., sTop=sMax, sBot=sMin, sLft=sMin, sRght=sMax. */
71   Fixed sBonus;
72     /* nonzero for segments in sol-eol subpaths */
73     /* (probably a leftover that is no longer needed) */
74   struct _hintval *sLnk;
75     /* points to the best HintVal that uses this HintSeg */
76     /* set by FindBestValForSegs in pick.c */
77   struct _pthelt *sElt;
78     /* points to the path element that generated this HintSeg */
79     /* set by AddSegment in gen.c */
80   int16_t sType;
81     /* tells what type of segment this is: sLINE sBEND sCURVE or sGHOST */
82   } HintSeg;
83 
84 typedef struct {
85   HintSeg* seg;
86   } SegLnk;
87 
88 typedef struct _seglnklst {
89   struct _seglnklst *next;
90   SegLnk* lnk;
91   } SegLnkLst;
92 
93 #if 0
94 typedef struct _hintrep {
95   Fixed vVal, vSpc, vLoc1, vLoc2;
96   struct _hintval *vBst;
97   } HintRep;
98 
99 typedef struct _hintval {
100   struct _hintval *vNxt;
101   Fixed vVal, vSpc, initVal;
102   Fixed vLoc1, vLoc2;
103     /* vBot=vLoc1, vTop=vLoc2, vLft=vLoc1, vRght=vLoc2 */
104   int16_t vGhst:8;
105   int16_t pruned:8;
106   HintSeg* vSeg1, *vSeg2;
107   struct _hintval *vBst;
108   HintRep* vRep;
109   } HintVal;
110 #else
111 typedef struct _hintval {
112   struct _hintval *vNxt;
113     /* points to next HintVal in list */
114   Fixed vVal, vSpc, initVal;
115     /* vVal is value given in eval.c */
116     /* vSpc is nonzero for "special" HintVals */
117        /* such as those with a segment in a blue zone */
118     /* initVal is the initially assigned value */
119        /* used by FndBstVal in pick.c */
120   Fixed vLoc1, vLoc2;
121     /* vLoc1 is location corresponding to vSeg1 */
122     /* vLoc2 is location corresponding to vSeg2 */
123     /* for horizontal HintVal, vBot=vLoc1 and vTop=vLoc2 */
124     /* for vertical HintVal, vLft=vLoc1 and vRght=vLoc2 */
125   unsigned int vGhst:1;  /* true iff one of the HintSegs is a sGHOST seg */
126   unsigned int pruned:1;
127     /* flag used by FindBestHVals and FindBestVVals */
128     /* and by PruneVVals and PruneHVals */
129   unsigned int merge:1;
130     /* flag used by ReplaceVals in merge.c */
131   unsigned int unused:13;
132   HintSeg *vSeg1, *vSeg2;
133     /* vSeg1 points to the left HintSeg in a vertical, bottom in a horizontal */
134     /* vSeg2 points to the right HintSeg in a vertical, top in a horizontal */
135   struct _hintval *vBst;
136     /* points to another HintVal if this one has been merged or replaced */
137   } HintVal;
138 #endif
139 
140 typedef struct _pthelt {
141   struct _pthelt *prev, *next, *conflict;
142   int16_t type;
143   SegLnkLst *Hs, *Vs;
144   bool Hcopy:1, Vcopy:1, isFlex:1, yFlex:1, newCP:1;
145   unsigned int unused:9;
146   int16_t count, newhints;
147   Fixed x, y, x1, y1, x2, y2, x3, y3;
148   } PathElt;
149 
150 typedef struct _hintpnt {
151   struct _hintpnt *next;
152   Fixed x0, y0, x1, y1;
153     /* for vstem, only interested in x0 and x1 */
154     /* for hstem, only interested in y0 and y1 */
155   PathElt *p0, *p1;
156     /* p0 is source of x0,y0; p1 is source of x1,y1 */
157   char c;
158     /* tells what kind of hinting: 'b' 'y' 'm' or 'v' */
159   bool done;
160   } HintPoint;
161 
162 typedef struct {
163   char** keys;      /* font information keys */
164   char** values;    /* font information values */
165   size_t length;    /* number of the entries */
166 } ACFontInfo;
167 
168 /* global data */
169 
170 extern ACBuffer* gBezOutput;
171 
172 extern PathElt* gPathStart, *gPathEnd;
173 extern bool gUseV, gUseH, gAutoLinearCurveFix;
174 extern bool gEditGlyph; /* whether glyph can be modified when adding hints */
175 extern bool gBandError;
176 extern bool gHasFlex, gFlexOK, gFlexStrict;
177 extern Fixed gHBigDist, gVBigDist, gInitBigDist, gMinDist, gGhostWidth,
178   gGhostLength, gBendLength, gBandMargin, gMaxFlare,
179   gMaxBendMerge, gMaxMerge, gMinHintElementLength, gFlexCand;
180 extern Fixed gPruneA, gPruneB, gPruneC, gPruneD, gPruneValue, gBonus;
181 extern float gTheta, gHBigDistR, gVBigDistR, gMaxVal, gMinVal;
182 extern int32_t gDMin, gDelta, gCPpercent, gBendTan, gSCurveTan;
183 extern HintVal *gVHinting, *gHHinting, *gVPrimary, *gHPrimary, *gValList;
184 extern HintSeg* gSegLists[4]; /* left, right, top, bot */
185 extern HintPoint* gPointList, **gPtLstArray;
186 extern int32_t gPtLstIndex, gNumPtLsts, gMaxPtLsts;
187 
188 /* global callbacks */
189 
190 /* if false, then stems defined by curves are excluded from the reporting */
191 extern unsigned int gAllStems;
192 
193 extern AC_REPORTSTEMPTR gAddHStemCB;
194 extern AC_REPORTSTEMPTR gAddVStemCB;
195 
196 extern AC_REPORTZONEPTR gAddGlyphExtremesCB;
197 extern AC_REPORTZONEPTR gAddStemExtremesCB;
198 
199 extern AC_RETRYPTR gReportRetryCB;
200 
201 extern void* gAddStemUserData;
202 extern void* gAddExtremesUserData;
203 extern void* gReportRetryUserData;
204 
205 void AddStemExtremes(Fixed bot, Fixed top);
206 
207 #define leftList (gSegLists[0])
208 #define rightList (gSegLists[1])
209 #define topList (gSegLists[2])
210 #define botList (gSegLists[3])
211 
212 #define MAXFLEX (PSDist(20))
213 #define MAXBLUES (20)
214 #define MAXSERIFS (5)
215 extern Fixed gTopBands[MAXBLUES], gBotBands[MAXBLUES], gSerifs[MAXSERIFS];
216 extern int32_t gLenTopBands, gLenBotBands, gNumSerifs;
217 #define MAXSTEMS (20)
218 extern Fixed gVStems[MAXSTEMS], gHStems[MAXSTEMS];
219 extern int32_t gNumVStems, gNumHStems;
220 extern char *gHHintList[], *gVHintList[];
221 extern int32_t gNumHHints, gNumVHints;
222 extern bool gWriteHintedBez;
223 extern Fixed gBlueFuzz;
224 extern bool gDoAligns, gDoStems;
225 extern bool gRoundToInt;
226 extern bool gAddHints;
227 
228 #define MAX_GLYPHNAME_LEN 64
229 /* defined in read.c; set from the glyph name at the start of the bex file. */
230 extern char gGlyphName[MAX_GLYPHNAME_LEN];
231 
232 /* macros */
233 
234 #define FixOne (0x100)
235 #define FixTwo (0x200)
236 #define FixHalf (0x80)
237 #define FixQuarter (0x40)
238 
239 #define FIXED_MAX INT32_MAX
240 #define FIXED_MIN INT32_MIN
241 #define FixInt(i) (((int32_t)(i)) * FixOne)
242 #define FixReal(i) ((int32_t)((i) * (float)FixOne))
243 int32_t FRnd(int32_t x);
244 #define FHalfRnd(x) ((int32_t)(((x)+(1<<7)) & ~0xFF))
245 #define FracPart(x) ((int32_t)(x) & 0xFF)
246 #define FTrunc(x) (((int32_t)(x)) / FixOne)
247 #define FIXED2FLOAT(x) (x / (float)FixOne)
248 
249 #define FixHalfMul(f) (2*((f) >> 2)) /* DEBUG 8 BIT. Revert this to ((f) >>1) once I am confident that there are not bugs from the update to 8 bits for the Fixed fraction. */
250 #define FixTwoMul(f) ((f) << 1)
251 #define PSDist(d) ((FixInt(d)))
252 #define IsVertical(x1,y1,x2,y2) (VertQuo(x1,y1,x2,y2) > 0)
253 #define IsHorizontal(x1,y1,x2,y2) (HorzQuo(x1,y1,x2,y2) > 0)
254 #define SFACTOR (20)
255    /* SFACTOR must be < 25 for Gothic-Medium-22 c08 */
256 #define spcBonus (1000)
257 #define ProdLt0(f0, f1) (((f0) < 0 && (f1) > 0) || ((f0) > 0 && (f1) < 0))
258 #define ProdGe0(f0, f1) (!ProdLt0(f0, f1))
259 
260 #define DEBUG_ROUND(val) { val = ( val >=0 ) ? (2*(val/2)) : (2*((val - 1)/2));}
261 
262 /* DEBUG_ROUND is used to force calculations to come out the same as the previous version, where coordinates used 7 bits for the Fixed fraction, rather than the current 8 bits. Once I am confident that there are no bugs in the update, I will remove all occurences of this macro, and accept the differences due to more exact division */
263 /* procedures */
264 
265 /* The fix to float and float to fixed procs are different for ac because it
266    uses 24 bit of int32_t and 8 bits of fraction. */
267 void acfixtopflt(Fixed x, float* pf);
268 Fixed acpflttofix(float* pf);
269 
270 void *Alloc(int32_t sz); /* Sub-allocator */
271 
272 int AddCounterHintGlyphs(char* charlist, char* HintList[]);
273 bool FindNameInList(char* nm, char** lst);
274 void PruneElementHintSegs(void);
275 int TestHintLst(SegLnkLst* lst, HintVal* hintList, bool flg, bool doLst);
276 HintVal* CopyHints(HintVal* lst);
277 void AutoExtraHints(bool movetoNewHints);
278 int32_t SpecialGlyphType(void);
279 bool VHintGlyph(void);
280 bool HHintGlyph(void);
281 bool NoBlueGlyph(void);
282 bool MoveToNewHints(void);
283 bool GetInflectionPoint(Fixed, Fixed, Fixed, Fixed, Fixed, Fixed, Fixed, Fixed, Fixed *);
284 void CheckSmooth(void);
285 void CheckBBoxEdge(PathElt* e, bool vrt, Fixed lc, Fixed* pf, Fixed* pl);
286 bool CheckSmoothness(Fixed x0, Fixed cy0, Fixed x1, Fixed cy1, Fixed x2,
287                      Fixed y2, Fixed* pd);
288 void CheckForDups(void);
289 void AddHintPoint(Fixed x0, Fixed y0, Fixed x1, Fixed y1, char ch, PathElt* p0,
290                    PathElt* p1);
291 void AddHPair(HintVal* v, char ch);
292 void AddVPair(HintVal* v, char ch);
293 void XtraHints(PathElt* e);
294 bool AutoHintGlyph(const char* srcglyph, bool extrahint);
295 void EvalV(void);
296 void EvalH(void);
297 void GenVPts(int32_t specialGlyphType);
298 void CheckTfmVal(HintSeg* hSegList, Fixed* bandList, int32_t length);
299 void CheckVals(HintVal* vlst, bool vert);
300 bool FindLineSeg(Fixed loc, HintSeg* sL);
301 void FltnCurve(Cd c0, Cd c1, Cd c2, Cd c3, FltnRec* pfr);
302 bool InBlueBand(Fixed loc, int32_t n, Fixed* p);
303 void GenHPts(void);
304 void PreGenPts(void);
305 PathElt* GetDest(PathElt* cldest);
306 PathElt* GetClosedBy(PathElt* clsdby);
307 void GetEndPoint(PathElt* e, Fixed* x1p, Fixed* y1p);
308 void GetEndPoints(PathElt* p, Fixed* px0, Fixed* py0, Fixed* px1, Fixed* py1);
309 Fixed VertQuo(Fixed xk, Fixed yk, Fixed xl, Fixed yl);
310 Fixed HorzQuo(Fixed xk, Fixed yk, Fixed xl, Fixed yl);
311 bool IsTiny(PathElt* e);
312 bool IsShort(PathElt* e);
313 PathElt* NxtForBend(PathElt* p, Fixed* px2, Fixed* py2, Fixed* px3, Fixed* py3);
314 PathElt* PrvForBend(PathElt* p, Fixed* px2, Fixed* py2);
315 bool IsLower(PathElt* p);
316 bool IsUpper(PathElt* p);
317 bool CloseSegs(HintSeg* s1, HintSeg* s2, bool vert);
318 
319 void DoPrune(void);
320 void PruneVVals(void);
321 void PruneHVals(void);
322 void MergeVals(bool vert);
323 void MergeFromMainHints(char ch);
324 void RoundPathCoords(void);
325 void MoveSubpathToEnd(PathElt* e);
326 void InitData(int32_t reason);
327 void InitFix(int32_t reason);
328 void InitGen(int32_t reason);
329 void InitPick(int32_t reason);
330 void AutoAddFlex(void);
331 bool SameHints(int32_t cn1, int32_t cn2);
332 bool PreCheckForHinting(void);
333 int32_t CountSubPaths(void);
334 void PickVVals(HintVal* gValList);
335 void PickHVals(HintVal* gValList);
336 void FindBestHVals(void);
337 void FindBestVVals(void);
338 void ReportAddFlex(void);
339 void ReportLinearCurve(PathElt* e, Fixed x0, Fixed y0, Fixed x1, Fixed y1);
340 void ReportNonHError(Fixed x0, Fixed y0, Fixed x1, Fixed y1);
341 void ReportNonVError(Fixed x0, Fixed y0, Fixed x1, Fixed y1);
342 void ExpectedMoveTo(PathElt* e);
343 void ReportMissingClosePath(void);
344 void ReportTryFlexNearMiss(Fixed x0, Fixed y0, Fixed x2, Fixed y2);
345 void ReportTryFlexError(bool CPflg, Fixed x, Fixed y);
346 void ReportSplit(PathElt* e);
347 void ReportRemFlare(PathElt* e, PathElt* e2, bool hFlg, int32_t i);
348 void ReportRemConflict(PathElt* e);
349 void ReportRemShortHints(Fixed ex, Fixed ey);
350 bool ResolveConflictBySplit(PathElt* e, bool Hflg, SegLnkLst* lnk1,
351                             SegLnkLst* lnk2);
352 void ReportPossibleLoop(PathElt* e);
353 void ShowHVal(HintVal* val);
354 void ShowHVals(HintVal* lst);
355 void ReportAddHVal(HintVal* val);
356 void ShowVVal(HintVal* val);
357 void ShowVVals(HintVal* lst);
358 void ReportAddVVal(HintVal* val);
359 void ReportFndBstVal(HintSeg* seg, HintVal* val, bool hFlg);
360 void ReportCarry(Fixed l0, Fixed l1, Fixed loc, HintVal* hints, bool vert);
361 void LogHintInfo(HintPoint* pl);
362 void ReportStemNearMiss(bool vert, Fixed w, Fixed minW, Fixed b, Fixed t,
363                         bool curve);
364 void ReportHintConflict(Fixed x0, Fixed y0, Fixed x1, Fixed y1, char ch);
365 void ReportDuplicates(Fixed x, Fixed y);
366 void ReportBBoxBogus(Fixed llx, Fixed lly, Fixed urx, Fixed ury);
367 void ReportMergeHVal(Fixed b0, Fixed t0, Fixed b1, Fixed t1, Fixed v0, Fixed s0,
368                      Fixed v1, Fixed s1);
369 void ReportMergeVVal(Fixed l0, Fixed r0, Fixed l1, Fixed r1, Fixed v0, Fixed s0,
370                      Fixed v1, Fixed s1);
371 void ReportPruneHVal(HintVal* val, HintVal* v, int32_t i);
372 void ReportPruneVVal(HintVal* val, HintVal* v, int32_t i);
373 unsigned char* InitShuffleSubpaths(void);
374 void MarkLinks(HintVal* vL, bool hFlg, unsigned char* links);
375 void DoShuffleSubpaths(unsigned char* links);
376 void CopyMainH(void);
377 void CopyMainV(void);
378 void RMovePoint(Fixed dx, Fixed dy, int32_t whichcp, PathElt* e);
379 void AddVSegment(Fixed from, Fixed to, Fixed loc, PathElt* p1, PathElt* p2,
380                  int32_t typ, int32_t i);
381 void AddHSegment(Fixed from, Fixed to, Fixed loc, PathElt* p1, PathElt* p2,
382                  int32_t typ, int32_t i);
383 void Delete(PathElt* e);
384 bool ReadGlyph(const char* srcglyph, bool forBlendData, bool readHints);
385 double FixToDbl(Fixed f);
386 bool CompareValues(HintVal* val1, HintVal* val2, int32_t factor,
387                    int32_t ghstshift);
388 void SaveFile(void);
389 void CheckForMultiMoveTo(void);
390 #define STARTUP (0)
391 #define RESTART (1)
392 
393 void ListHintInfo(void);
394 
395 void InitAll(int32_t reason);
396 
397 void AddVStem(Fixed right, Fixed left, bool curved);
398 void AddHStem(Fixed top, Fixed bottom, bool curved);
399 
400 void AddGlyphExtremes(Fixed bot, Fixed top);
401 
402 bool AutoHint(const ACFontInfo* fontinfo, const char* srcbezdata,
403               bool extrahint, bool changeGlyph, bool roundCoords);
404 
405 bool MergeGlyphPaths(const char** srcglyphs, int nmasters,
406                      const char** masters, ACBuffer** outbuffers);
407 
408 #endif /* AC_AC_H_ */
409