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 #include <stdarg.h>
11 
12 #include "ac.h"
13 
14 double
FixToDbl(Fixed f)15 FixToDbl(Fixed f)
16 {
17     float r;
18     acfixtopflt(f, &r);
19     return (double)r;
20 }
21 
22 void
ReportAddFlex(void)23 ReportAddFlex(void)
24 {
25     if (gHasFlex)
26         return;
27     gHasFlex = true;
28     LogMsg(INFO, OK, "added flex operators to this glyph.");
29 }
30 
31 void
ReportLinearCurve(PathElt * e,Fixed x0,Fixed y0,Fixed x1,Fixed y1)32 ReportLinearCurve(PathElt* e, Fixed x0, Fixed y0, Fixed x1, Fixed y1)
33 {
34     if (gAutoLinearCurveFix) {
35         e->type = LINETO;
36         e->x = e->x3;
37         e->y = e->y3;
38         LogMsg(INFO, OK, "Curve from %g %g to %g %g was changed to a line.",
39                FixToDbl(x0), FixToDbl(-y0), FixToDbl(x1), FixToDbl(-y1));
40     } else {
41         LogMsg(INFO, OK,
42                "Curve from %g %g to %g %g should be changed to a line.",
43                FixToDbl(x0), FixToDbl(-y0), FixToDbl(x1), FixToDbl(-y1));
44     }
45 }
46 
47 static void
ReportNonHVError(Fixed x0,Fixed y0,Fixed x1,Fixed y1,char * s)48 ReportNonHVError(Fixed x0, Fixed y0, Fixed x1, Fixed y1, char* s)
49 {
50     Fixed dx, dy;
51     y0 = -y0;
52     y1 = -y1;
53     dx = x0 - x1;
54     dy = y0 - y1;
55     if (abs(dx) > FixInt(10) || abs(dy) > FixInt(10) ||
56         FTrunc(dx * dx) + FTrunc(dy * dy) > FixInt(100)) {
57         LogMsg(INFO, OK, "The line from %g %g to %g %g is not exactly %s.",
58                FixToDbl(x0), FixToDbl(y0), FixToDbl(x1), FixToDbl(y1), s);
59     }
60 }
61 
62 void
ReportNonHError(Fixed x0,Fixed y0,Fixed x1,Fixed y1)63 ReportNonHError(Fixed x0, Fixed y0, Fixed x1, Fixed y1)
64 {
65     ReportNonHVError(x0, y0, x1, y1, "horizontal");
66 }
67 
68 void
ReportNonVError(Fixed x0,Fixed y0,Fixed x1,Fixed y1)69 ReportNonVError(Fixed x0, Fixed y0, Fixed x1, Fixed y1)
70 {
71     ReportNonHVError(x0, y0, x1, y1, "vertical");
72 }
73 
74 void
ExpectedMoveTo(PathElt * e)75 ExpectedMoveTo(PathElt* e)
76 {
77     char* s;
78     switch (e->type) {
79         case LINETO:
80             s = (char*)"lineto";
81             break;
82         case CURVETO:
83             s = (char*)"curveto";
84             break;
85         case CLOSEPATH:
86             s = (char*)"closepath";
87             break;
88         default:
89             LogMsg(LOGERROR, NONFATALERROR, "Malformed path list.");
90             return;
91     }
92     LogMsg(LOGERROR, NONFATALERROR,
93            "Glyph path has a %s where a moveto was expected. "
94            "The data is probably truncated.",
95            s);
96 }
97 
98 void
ReportMissingClosePath(void)99 ReportMissingClosePath(void)
100 {
101     LogMsg(LOGERROR, NONFATALERROR,
102            "Missing closepath. The data is probably truncated.");
103 }
104 
105 void
ReportTryFlexNearMiss(Fixed x0,Fixed y0,Fixed x2,Fixed y2)106 ReportTryFlexNearMiss(Fixed x0, Fixed y0, Fixed x2, Fixed y2)
107 {
108     LogMsg(WARNING, OK, "Curves from %g %g to %g %g near miss for adding flex.",
109            FixToDbl(x0), FixToDbl(-y0), FixToDbl(x2), FixToDbl(-y2));
110 }
111 
112 void
ReportTryFlexError(bool CPflg,Fixed x,Fixed y)113 ReportTryFlexError(bool CPflg, Fixed x, Fixed y)
114 {
115     LogMsg(LOGERROR, OK,
116            CPflg
117              ? "Please move closepath from %g %g so can add flex."
118              : "Please remove zero length element at %g %g so can add flex.",
119            FixToDbl(x), FixToDbl(-y));
120 }
121 
122 void
ReportSplit(PathElt * e)123 ReportSplit(PathElt* e)
124 {
125     Fixed x0, y0, x1, y1;
126     GetEndPoints(e, &x0, &y0, &x1, &y1);
127     LogMsg(INFO, OK,
128            "the element that goes from %g %g to %g %g has been split.",
129            FixToDbl(x0), FixToDbl(-y0), FixToDbl(x1), FixToDbl(-y1));
130 }
131 
132 void
ReportPossibleLoop(PathElt * e)133 ReportPossibleLoop(PathElt* e)
134 {
135     Fixed x0, y0, x1, y1;
136     if (e->type == MOVETO)
137         e = GetClosedBy(e);
138     GetEndPoints(e, &x0, &y0, &x1, &y1);
139     LogMsg(LOGERROR, OK,
140            "Possible loop in element that goes from %g %g to %g %g."
141            " Please check.",
142            FixToDbl(x0), FixToDbl(-y0), FixToDbl(x1), FixToDbl(-y1));
143 }
144 
145 void
ReportRemFlare(PathElt * e,PathElt * e2,bool hFlg,int32_t i)146 ReportRemFlare(PathElt* e, PathElt* e2, bool hFlg, int32_t i)
147 {
148     Fixed ex1, ey1, ex2, ey2;
149     GetEndPoint(e, &ex1, &ey1);
150     GetEndPoint(e2, &ex2, &ey2);
151     LogMsg(INFO, OK, "Removed %s flare at %g %g by %g %g : %d.",
152            hFlg ? "horizontal" : "vertical", FixToDbl(ex1), FixToDbl(-ey1),
153            FixToDbl(ex2), FixToDbl(-ey2), i);
154 }
155 
156 void
ReportRemConflict(PathElt * e)157 ReportRemConflict(PathElt* e)
158 {
159     Fixed ex, ey;
160     GetEndPoint(e, &ex, &ey);
161     LogMsg(INFO, OK, "Removed conflicting hints at %g %g.", FixToDbl(ex),
162            FixToDbl(-ey));
163 }
164 
165 void
ReportRemShortHints(Fixed ex,Fixed ey)166 ReportRemShortHints(Fixed ex, Fixed ey)
167 {
168     LogMsg(INFO, OK, "Removed hints from short element at %g %g.", FixToDbl(ex),
169            FixToDbl(-ey));
170 }
171 
172 #define VAL(v) ((v) >= FixInt(100000) ? FTrunc(v) : FixToDbl(v))
173 
174 static void
ShwHV(HintVal * val)175 ShwHV(HintVal* val)
176 {
177     Fixed bot, top;
178     bot = -val->vLoc1;
179     top = -val->vLoc2;
180     LogMsg(LOGDEBUG, OK, "b %g t %g v %g s %g%s", FixToDbl(bot), FixToDbl(top),
181            VAL(val->vVal), FixToDbl(val->vSpc), val->vGhst ? " G" : "");
182 }
183 
184 void
ShowHVal(HintVal * val)185 ShowHVal(HintVal* val)
186 {
187     Fixed l1, l2, r1, r2;
188     Fixed bot, top;
189     HintSeg* seg = val->vSeg1;
190     if (seg == NULL) {
191         ShwHV(val);
192         return;
193     }
194     bot = -val->vLoc1;
195     top = -val->vLoc2;
196     l1 = seg->sMin;
197     r1 = seg->sMax;
198     seg = val->vSeg2;
199     l2 = seg->sMin;
200     r2 = seg->sMax;
201     LogMsg(LOGDEBUG, OK, "b %g t %g v %g s %g%s l1 %g r1 %g  l2 %g r2 %g",
202            FixToDbl(bot), FixToDbl(top), VAL(val->vVal), FixToDbl(val->vSpc),
203            val->vGhst ? " G" : "", FixToDbl(l1), FixToDbl(r1), FixToDbl(l2),
204            FixToDbl(r2));
205 }
206 
207 void
ShowHVals(HintVal * lst)208 ShowHVals(HintVal* lst)
209 {
210     while (lst != NULL) {
211         ShowHVal(lst);
212         lst = lst->vNxt;
213     }
214 }
215 
216 void
ReportAddHVal(HintVal * val)217 ReportAddHVal(HintVal* val)
218 {
219     ShowHVal(val);
220 }
221 
222 static void
ShwVV(HintVal * val)223 ShwVV(HintVal* val)
224 {
225     Fixed lft, rht;
226     lft = val->vLoc1;
227     rht = val->vLoc2;
228     LogMsg(LOGDEBUG, OK, "l %g r %g v %g s %g", FixToDbl(lft), FixToDbl(rht),
229            VAL(val->vVal), FixToDbl(val->vSpc));
230 }
231 
232 void
ShowVVal(HintVal * val)233 ShowVVal(HintVal* val)
234 {
235     Fixed b1, b2, t1, t2;
236     Fixed lft, rht;
237     HintSeg* seg = val->vSeg1;
238     if (seg == NULL) {
239         ShwVV(val);
240         return;
241     }
242     lft = val->vLoc1;
243     rht = val->vLoc2;
244     b1 = -seg->sMin;
245     t1 = -seg->sMax;
246     seg = val->vSeg2;
247     b2 = -seg->sMin;
248     t2 = -seg->sMax;
249     LogMsg(LOGDEBUG, OK, "l %g r %g v %g s %g b1 %g t1 %g  b2 %g t2 %g",
250            FixToDbl(lft), FixToDbl(rht), VAL(val->vVal), FixToDbl(val->vSpc),
251            FixToDbl(b1), FixToDbl(t1), FixToDbl(b2), FixToDbl(t2));
252 }
253 
254 void
ShowVVals(HintVal * lst)255 ShowVVals(HintVal* lst)
256 {
257     while (lst != NULL) {
258         ShowVVal(lst);
259         lst = lst->vNxt;
260     }
261 }
262 
263 void
ReportAddVVal(HintVal * val)264 ReportAddVVal(HintVal* val)
265 {
266     ShowVVal(val);
267 }
268 
269 void
ReportFndBstVal(HintSeg * seg,HintVal * val,bool hFlg)270 ReportFndBstVal(HintSeg* seg, HintVal* val, bool hFlg)
271 {
272     if (hFlg) {
273         LogMsg(LOGDEBUG, OK, "FndBstVal: sLoc %g sLft %g sRght %g ",
274                FixToDbl(-seg->sLoc), FixToDbl(seg->sMin), FixToDbl(seg->sMax));
275         if (val)
276             ShwHV(val);
277         else
278             LogMsg(LOGDEBUG, OK, "NULL");
279     } else {
280         LogMsg(LOGDEBUG, OK, "FndBstVal: sLoc %g sBot %g sTop %g ",
281                FixToDbl(seg->sLoc), FixToDbl(-seg->sMin), FixToDbl(-seg->sMax));
282         if (val)
283             ShwVV(val);
284         else
285             LogMsg(LOGDEBUG, OK, "NULL");
286     }
287 }
288 
289 void
ReportCarry(Fixed l0,Fixed l1,Fixed loc,HintVal * hints,bool vert)290 ReportCarry(Fixed l0, Fixed l1, Fixed loc, HintVal* hints, bool vert)
291 {
292     if (vert) {
293         ShowVVal(hints);
294     } else {
295         ShowHVal(hints);
296         loc = -loc;
297         l0 = -l0;
298         l1 = -l1;
299     }
300     LogMsg(LOGDEBUG, OK, " carry to %g in [%g..%g]", FixToDbl(loc),
301            FixToDbl(l0), FixToDbl(l1));
302 }
303 
304 void
LogHintInfo(HintPoint * pl)305 LogHintInfo(HintPoint* pl)
306 {
307     char c = pl->c;
308     if (c == 'y' || c == 'm') { /* vertical lines */
309         Fixed lft = pl->x0;
310         Fixed rht = pl->x1;
311         LogMsg(LOGDEBUG, OK, "%4g  %-30s%5g%5g", FixToDbl(rht - lft),
312                gGlyphName, FixToDbl(lft), FixToDbl(rht));
313     } else {
314         Fixed bot = pl->y0;
315         Fixed top = pl->y1;
316         Fixed wdth = top - bot;
317         if (wdth == -FixInt(21) || wdth == -FixInt(20))
318             return; /* ghost pair */
319         LogMsg(LOGDEBUG, OK, "%4g  %-30s%5g%5g", FixToDbl(wdth), gGlyphName,
320                FixToDbl(bot), FixToDbl(top));
321     }
322 }
323 
324 static void
LstHVal(HintVal * val)325 LstHVal(HintVal* val)
326 {
327     ShowHVal(val);
328 }
329 
330 static void
LstVVal(HintVal * val)331 LstVVal(HintVal* val)
332 {
333     ShowVVal(val);
334 }
335 
336 void
ListHintInfo(void)337 ListHintInfo(void)
338 { /* debugging routine */
339     PathElt* e;
340     SegLnkLst *hLst, *vLst;
341     HintSeg* seg;
342     Fixed x, y;
343     e = gPathStart;
344     while (e != NULL) {
345         hLst = e->Hs;
346         vLst = e->Vs;
347         if ((hLst != NULL) || (vLst != NULL)) {
348             GetEndPoint(e, &x, &y);
349             y = -y;
350             LogMsg(LOGDEBUG, OK, "x %g y %g ", FixToDbl(x), FixToDbl(y));
351             while (hLst != NULL) {
352                 seg = hLst->lnk->seg;
353                 LstHVal(seg->sLnk);
354                 hLst = hLst->next;
355             }
356             while (vLst != NULL) {
357                 seg = vLst->lnk->seg;
358                 LstVVal(seg->sLnk);
359                 vLst = vLst->next;
360             }
361         }
362         e = e->next;
363     }
364 }
365 
366 void
ReportStemNearMiss(bool vert,Fixed w,Fixed minW,Fixed b,Fixed t,bool curve)367 ReportStemNearMiss(bool vert, Fixed w, Fixed minW, Fixed b, Fixed t, bool curve)
368 {
369     LogMsg(INFO, OK, "%s %s stem near miss: %g instead of %g at %g to %g.",
370            vert ? "Vertical" : "Horizontal", curve ? "curve" : "linear",
371            FixToDbl(w), FixToDbl(minW), FixToDbl(NUMMIN(b, t)),
372            FixToDbl(NUMMAX(b, t)));
373 }
374 
375 void
ReportHintConflict(Fixed x0,Fixed y0,Fixed x1,Fixed y1,char ch)376 ReportHintConflict(Fixed x0, Fixed y0, Fixed x1, Fixed y1, char ch)
377 {
378     char s[2];
379     s[0] = ch;
380     s[1] = 0;
381     LogMsg(LOGERROR, OK, "  Conflicts with current hints: %g %g %g %g %s.",
382            FixToDbl(x0), FixToDbl(y0), FixToDbl(x1), FixToDbl(y1), s);
383 }
384 
385 void
ReportDuplicates(Fixed x,Fixed y)386 ReportDuplicates(Fixed x, Fixed y)
387 {
388     LogMsg(LOGERROR, OK, "Check for duplicate subpath at %g %g.", FixToDbl(x),
389            FixToDbl(y));
390 }
391 
392 void
ReportBBoxBogus(Fixed llx,Fixed lly,Fixed urx,Fixed ury)393 ReportBBoxBogus(Fixed llx, Fixed lly, Fixed urx, Fixed ury)
394 {
395     LogMsg(WARNING, OK, "Glyph bounding box looks bogus: %g %g %g %g.",
396            FixToDbl(llx), FixToDbl(lly), FixToDbl(urx), FixToDbl(ury));
397 }
398 
399 void
ReportMergeHVal(Fixed b0,Fixed t0,Fixed b1,Fixed t1,Fixed v0,Fixed s0,Fixed v1,Fixed s1)400 ReportMergeHVal(Fixed b0, Fixed t0, Fixed b1, Fixed t1, Fixed v0, Fixed s0,
401                 Fixed v1, Fixed s1)
402 {
403     LogMsg(LOGDEBUG, OK, "Replace H hints pair at %g %g by %g %g",
404            FixToDbl(-b0), FixToDbl(-t0), FixToDbl(-b1), FixToDbl(-t1));
405     LogMsg(LOGDEBUG, OK, "\told value %g %g new value %g %g", VAL(v0),
406            FixToDbl(s0), VAL(v1), FixToDbl(s1));
407 }
408 
409 void
ReportMergeVVal(Fixed l0,Fixed r0,Fixed l1,Fixed r1,Fixed v0,Fixed s0,Fixed v1,Fixed s1)410 ReportMergeVVal(Fixed l0, Fixed r0, Fixed l1, Fixed r1, Fixed v0, Fixed s0,
411                 Fixed v1, Fixed s1)
412 {
413     LogMsg(LOGDEBUG, OK, "Replace V hints pair at %g %g by %g %g", FixToDbl(l0),
414            FixToDbl(r0), FixToDbl(l1), FixToDbl(r1));
415     LogMsg(LOGDEBUG, OK, "\told value %g %g new value %g %g", VAL(v0),
416            FixToDbl(s0), VAL(v1), FixToDbl(s1));
417 }
418 
419 void
ReportPruneHVal(HintVal * val,HintVal * v,int32_t i)420 ReportPruneHVal(HintVal* val, HintVal* v, int32_t i)
421 {
422     LogMsg(LOGDEBUG, OK, "PruneHVal: %d", i);
423     ShowHVal(val);
424     ShowHVal(v);
425 }
426 
427 void
ReportPruneVVal(HintVal * val,HintVal * v,int32_t i)428 ReportPruneVVal(HintVal* val, HintVal* v, int32_t i)
429 {
430     LogMsg(LOGDEBUG, OK, "PruneVVal: %d", i);
431     ShowVVal(val);
432     ShowVVal(v);
433 }
434