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