[6779] | 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 | |
---|