1 | /* |
---|
2 | * see COPYRIGHT |
---|
3 | */ |
---|
4 | |
---|
5 | |
---|
6 | fchkneg(file, line, rc, cmd) |
---|
7 | char *file; |
---|
8 | int line; |
---|
9 | int rc; |
---|
10 | char *cmd; |
---|
11 | { |
---|
12 | if(rc<0) { |
---|
13 | fprintf(stderr,"%s: fatal error on line %d of %s: %d\n", |
---|
14 | PROGNAME, line, file, rc); |
---|
15 | fprintf(stderr,"%s\n", cmd); |
---|
16 | exit(1); |
---|
17 | } |
---|
18 | } |
---|
19 | |
---|
20 | fchknull(file, line, rc, cmd) |
---|
21 | char *file; |
---|
22 | int line; |
---|
23 | void *rc; |
---|
24 | char *cmd; |
---|
25 | { |
---|
26 | if(rc==NULL) { |
---|
27 | fprintf(stderr,"%s: fatal error on line %d of %s: NULL\n", |
---|
28 | PROGNAME, line, file); |
---|
29 | fprintf(stderr,"%s\n", cmd); |
---|
30 | exit(1); |
---|
31 | } |
---|
32 | } |
---|
33 | |
---|
34 | #define chkneg(f) fchkneg(__FILE__,__LINE__,(f),#f) |
---|
35 | #define chknull(f) fchknull(__FILE__,__LINE__,(f),#f) |
---|
36 | |
---|
37 | #define MYPAD 8 |
---|
38 | |
---|
39 | #define CHRNONE ' ' |
---|
40 | #define CHRBOTH '.' |
---|
41 | #define CHRONE '1' |
---|
42 | #define CHRTWO '2' |
---|
43 | |
---|
44 | #define MINSIZE 8 |
---|
45 | #define MAXSIZE 20 |
---|
46 | |
---|
47 | #define LINEWIDTH 80 /* screen line width in chars */ |
---|
48 | #define MAXLINES (MAXSIZE*(MAXSIZE-MINSIZE+1)) |
---|
49 | |
---|
50 | static char map[MAXLINES][LINEWIDTH+1]; |
---|
51 | static char mbase, mx, mend; |
---|
52 | |
---|
53 | /* returns 0 if the same, -1 if different */ |
---|
54 | |
---|
55 | int |
---|
56 | cmpglyphs(g1, g2) |
---|
57 | GLYPH *g1, *g2; |
---|
58 | { |
---|
59 | int wd1, wd2; |
---|
60 | int ht1, ht2; |
---|
61 | int i, j; |
---|
62 | char *p1, *p2; |
---|
63 | |
---|
64 | wd1=g1->metrics.rightSideBearing - g1->metrics.leftSideBearing; |
---|
65 | ht1=g1->metrics.ascent - g1->metrics.descent; |
---|
66 | wd2=g2->metrics.rightSideBearing - g2->metrics.leftSideBearing; |
---|
67 | ht2=g2->metrics.ascent - g2->metrics.descent; |
---|
68 | |
---|
69 | if(g1->bits==NULL && g2->bits!=NULL |
---|
70 | || g1->bits!=NULL && g2->bits==NULL) |
---|
71 | return -1; |
---|
72 | |
---|
73 | if(g1->metrics.ascent != g2->metrics.ascent) |
---|
74 | return -1; |
---|
75 | |
---|
76 | if(g1->metrics.descent != g2->metrics.descent) |
---|
77 | return -1; |
---|
78 | |
---|
79 | if( wd1 != wd2 ) |
---|
80 | return -1; |
---|
81 | |
---|
82 | if( (p1=g1->bits) !=NULL && (p2=g2->bits) !=NULL ) |
---|
83 | for(i=0; i<ht1; i++) { |
---|
84 | for(j=0; j<wd1; j+=8) { |
---|
85 | if( *p1++ != *p2++) |
---|
86 | return -1; |
---|
87 | } |
---|
88 | } |
---|
89 | return 0; |
---|
90 | } |
---|
91 | |
---|
92 | void |
---|
93 | resetmap() |
---|
94 | { |
---|
95 | int i, j; |
---|
96 | |
---|
97 | for(i=0; i<MAXLINES; i++) |
---|
98 | for(j=0; j<LINEWIDTH; j++) |
---|
99 | map[i][j]=' '; |
---|
100 | mbase=mx=mend=0; |
---|
101 | } |
---|
102 | |
---|
103 | void |
---|
104 | drawdot(row, col, val) |
---|
105 | unsigned row, col, val; |
---|
106 | { |
---|
107 | if(row < MAXLINES && col < LINEWIDTH-1) { |
---|
108 | map[row][col]=val; |
---|
109 | if(row > mend) |
---|
110 | mend=row; |
---|
111 | } |
---|
112 | } |
---|
113 | |
---|
114 | void |
---|
115 | drawdotg1(row, col, val) |
---|
116 | unsigned row, col, val; |
---|
117 | { |
---|
118 | if(row < MAXLINES && col < LINEWIDTH-1) { |
---|
119 | if(val) |
---|
120 | map[row][col]=CHRONE; |
---|
121 | else |
---|
122 | map[row][col]=CHRNONE; |
---|
123 | if(row > mend) |
---|
124 | mend=row; |
---|
125 | } |
---|
126 | } |
---|
127 | |
---|
128 | void |
---|
129 | drawdotg2(row, col, val) |
---|
130 | unsigned row, col, val; |
---|
131 | { |
---|
132 | if(row < MAXLINES && col < LINEWIDTH-1) { |
---|
133 | if(val) |
---|
134 | if(map[row][col]==CHRONE) |
---|
135 | map[row][col]=CHRBOTH; |
---|
136 | else |
---|
137 | map[row][col]=CHRTWO; |
---|
138 | else if(map[row][col]!=CHRONE) |
---|
139 | map[row][col]=CHRNONE; |
---|
140 | if(row > mend) |
---|
141 | mend=row; |
---|
142 | } |
---|
143 | } |
---|
144 | |
---|
145 | void |
---|
146 | drawglyf(size, g1) |
---|
147 | int size; |
---|
148 | GLYPH *g1; |
---|
149 | { |
---|
150 | int wd1, wd2, wdm; |
---|
151 | int ht1, ht2, ascm, desm; |
---|
152 | int i, j, k, val; |
---|
153 | char *p; |
---|
154 | int off1, off2; |
---|
155 | |
---|
156 | wd1=g1->metrics.rightSideBearing - g1->metrics.leftSideBearing; |
---|
157 | ht1=g1->metrics.ascent - g1->metrics.descent; |
---|
158 | |
---|
159 | wdm=wd1; |
---|
160 | |
---|
161 | ascm=g1->metrics.ascent; |
---|
162 | desm= -g1->metrics.descent; |
---|
163 | |
---|
164 | if(mbase==0) |
---|
165 | mbase=ascm+1; |
---|
166 | else if(LINEWIDTH-mx <= wdm+1) { |
---|
167 | mx=0; mbase=mend+ascm+2; |
---|
168 | } |
---|
169 | |
---|
170 | drawdot(mbase-ascm-1, mx, (size/10)%10+'0'); |
---|
171 | drawdot(mbase-ascm-1, mx+1, size%10+'0'); |
---|
172 | |
---|
173 | if( (p=g1->bits) !=NULL) |
---|
174 | for(i=0; i<ht1; i++) { |
---|
175 | for(j=0; j<wd1; j+=8) { |
---|
176 | val = *p++; |
---|
177 | for(k=0; k<8 && j+k<wd1; k++, val>>=1) |
---|
178 | drawdot(i+mbase-g1->metrics.ascent, mx+j+k, (val&1)?CHRBOTH:CHRNONE); |
---|
179 | } |
---|
180 | } |
---|
181 | |
---|
182 | wdm++; |
---|
183 | if(wdm<3) |
---|
184 | wdm=3; |
---|
185 | mx+=wdm; |
---|
186 | drawdot(mbase, mx-1, '-'); |
---|
187 | } |
---|
188 | |
---|
189 | void |
---|
190 | drawdiff(size, g1, g2) |
---|
191 | int size; |
---|
192 | GLYPH *g1, *g2; |
---|
193 | { |
---|
194 | int wd1, wd2, wdm; |
---|
195 | int ht1, ht2, ascm, desm; |
---|
196 | int i, j, k, val; |
---|
197 | char *p; |
---|
198 | int off1, off2; |
---|
199 | |
---|
200 | wd1=g1->metrics.rightSideBearing - g1->metrics.leftSideBearing; |
---|
201 | ht1=g1->metrics.ascent - g1->metrics.descent; |
---|
202 | wd2=g2->metrics.rightSideBearing - g2->metrics.leftSideBearing; |
---|
203 | ht2=g2->metrics.ascent - g2->metrics.descent; |
---|
204 | |
---|
205 | if(wd1>wd2) { |
---|
206 | wdm=wd1; |
---|
207 | off1=0; off2=wd1-wd2; |
---|
208 | } else { |
---|
209 | wdm=wd2; |
---|
210 | off2=0; off1=wd2-wd1; |
---|
211 | } |
---|
212 | |
---|
213 | if(g1->metrics.ascent > g2->metrics.ascent) |
---|
214 | ascm=g1->metrics.ascent; |
---|
215 | else |
---|
216 | ascm=g2->metrics.ascent; |
---|
217 | |
---|
218 | if(g1->metrics.descent < g2->metrics.descent) |
---|
219 | desm= -g1->metrics.descent; |
---|
220 | else |
---|
221 | desm= -g2->metrics.descent; |
---|
222 | |
---|
223 | if(mbase==0) |
---|
224 | mbase=ascm+1; |
---|
225 | else if(LINEWIDTH-mx <= wdm+1) { |
---|
226 | mx=0; mbase=mend+ascm+2; |
---|
227 | } |
---|
228 | |
---|
229 | drawdot(mbase-ascm-1, mx, (size/10)%10+'0'); |
---|
230 | drawdot(mbase-ascm-1, mx+1, size%10+'0'); |
---|
231 | |
---|
232 | /* check which alignment is better */ |
---|
233 | if(off1!=0 || off2!=0) { |
---|
234 | int cntl,cntr; |
---|
235 | int a1, a2, d1, d2; |
---|
236 | int val1, val2; |
---|
237 | int rstep1, rstep2; |
---|
238 | |
---|
239 | cntl=cntr=0; |
---|
240 | rstep1=(wd1+7)/8; |
---|
241 | rstep2=(wd2+7)/8; |
---|
242 | a1=g1->metrics.ascent; |
---|
243 | d1=g1->metrics.descent; |
---|
244 | a2=g2->metrics.ascent; |
---|
245 | d2=g2->metrics.descent; |
---|
246 | |
---|
247 | #ifdef dbgoff |
---|
248 | printf("size: %d\n", size); |
---|
249 | #endif |
---|
250 | for(i=ascm; i>= -desm; i--) { |
---|
251 | for(j=0; j<wdm; j++) { |
---|
252 | /* first the left alignment */ |
---|
253 | if(i>a1 || i<d1 || j>=wd1) |
---|
254 | val1=0; |
---|
255 | else |
---|
256 | val1=( g1->bits[ (a1-i)*rstep1+j/8 ] >> (j%8) ) & 1; |
---|
257 | if(i>a2 || i<d2 || j>=wd2) |
---|
258 | val2=0; |
---|
259 | else |
---|
260 | val2=( g2->bits[ (a2-i)*rstep2+j/8 ] >> (j%8) ) & 1; |
---|
261 | |
---|
262 | cntl += (val1 ^ val2); |
---|
263 | |
---|
264 | #ifdef dbgoff |
---|
265 | putchar(val1?'1':' '); |
---|
266 | putchar(val2?'2':' '); |
---|
267 | putchar('.'); |
---|
268 | #endif |
---|
269 | |
---|
270 | /* now the right alignment */ |
---|
271 | if(i>a1 || i<d1 || j-off1>=wd1 || j<off1) |
---|
272 | val1=0; |
---|
273 | else |
---|
274 | val1=( g1->bits[ (a1-i)*rstep1+(j-off1)/8 ] >> ((j-off1)%8) ) & 1; |
---|
275 | if(i>a2 || i<d2 || j-off2>=wd2) |
---|
276 | val2=0; |
---|
277 | else |
---|
278 | val2=( g2->bits[ (a2-i)*rstep2+(j-off2)/8 ] >> ((j-off2)%8) ) & 1; |
---|
279 | |
---|
280 | cntr += (val1 ^ val2); |
---|
281 | |
---|
282 | #ifdef dbgoff |
---|
283 | putchar(val1?'1':' '); |
---|
284 | putchar(val2?'2':' '); |
---|
285 | putchar('|'); |
---|
286 | #endif |
---|
287 | } |
---|
288 | #ifdef dbgoff |
---|
289 | putchar('\n'); |
---|
290 | #endif |
---|
291 | } |
---|
292 | |
---|
293 | #ifdef dbgoff |
---|
294 | printf("size %d: left %d right %d\n",size, cntl, cntr); |
---|
295 | #endif |
---|
296 | if(cntl <= cntr) /* left is better or the same */ |
---|
297 | off1=off2=0; |
---|
298 | } |
---|
299 | |
---|
300 | if( (p=g1->bits) !=NULL) |
---|
301 | for(i=0; i<ht1; i++) { |
---|
302 | for(j=0; j<wd1; j+=8) { |
---|
303 | val = *p++; |
---|
304 | for(k=0; k<8 && j+k<wd1; k++, val>>=1) |
---|
305 | drawdotg1(i+mbase-g1->metrics.ascent, mx+j+k+off1, val&1); |
---|
306 | } |
---|
307 | } |
---|
308 | if( (p=g2->bits) !=NULL) |
---|
309 | for(i=0; i<ht2; i++) { |
---|
310 | for(j=0; j<wd2; j+=8) { |
---|
311 | val = *p++; |
---|
312 | for(k=0; k<8 && j+k<wd2; k++, val>>=1) |
---|
313 | drawdotg2(i+mbase-g2->metrics.ascent, mx+j+k+off2, val&1); |
---|
314 | } |
---|
315 | } |
---|
316 | |
---|
317 | wdm++; |
---|
318 | if(wdm<3) |
---|
319 | wdm=3; |
---|
320 | mx+=wdm; |
---|
321 | drawdot(mbase, mx-1, '-'); |
---|
322 | } |
---|
323 | |
---|
324 | void |
---|
325 | printmap(f) |
---|
326 | FILE *f; |
---|
327 | { |
---|
328 | int i, j; |
---|
329 | |
---|
330 | for(i=0; i<=mend; i++) { |
---|
331 | for(j=LINEWIDTH-1; j>=0 && map[i][j]==' '; j--) |
---|
332 | {} |
---|
333 | map[i][j+1]='\n'; |
---|
334 | map[i][j+2]=0; |
---|
335 | fputs(map[i], f); |
---|
336 | } |
---|
337 | } |
---|
338 | |
---|