/* * see COPYRIGHT */ fchkneg(file, line, rc, cmd) char *file; int line; int rc; char *cmd; { if(rc<0) { fprintf(stderr,"%s: fatal error on line %d of %s: %d\n", PROGNAME, line, file, rc); fprintf(stderr,"%s\n", cmd); exit(1); } } fchknull(file, line, rc, cmd) char *file; int line; void *rc; char *cmd; { if(rc==NULL) { fprintf(stderr,"%s: fatal error on line %d of %s: NULL\n", PROGNAME, line, file); fprintf(stderr,"%s\n", cmd); exit(1); } } #define chkneg(f) fchkneg(__FILE__,__LINE__,(f),#f) #define chknull(f) fchknull(__FILE__,__LINE__,(f),#f) #define MYPAD 8 #define CHRNONE ' ' #define CHRBOTH '.' #define CHRONE '1' #define CHRTWO '2' #define MINSIZE 8 #define MAXSIZE 20 #define LINEWIDTH 80 /* screen line width in chars */ #define MAXLINES (MAXSIZE*(MAXSIZE-MINSIZE+1)) static char map[MAXLINES][LINEWIDTH+1]; static char mbase, mx, mend; /* returns 0 if the same, -1 if different */ int cmpglyphs(g1, g2) GLYPH *g1, *g2; { int wd1, wd2; int ht1, ht2; int i, j; char *p1, *p2; wd1=g1->metrics.rightSideBearing - g1->metrics.leftSideBearing; ht1=g1->metrics.ascent - g1->metrics.descent; wd2=g2->metrics.rightSideBearing - g2->metrics.leftSideBearing; ht2=g2->metrics.ascent - g2->metrics.descent; if(g1->bits==NULL && g2->bits!=NULL || g1->bits!=NULL && g2->bits==NULL) return -1; if(g1->metrics.ascent != g2->metrics.ascent) return -1; if(g1->metrics.descent != g2->metrics.descent) return -1; if( wd1 != wd2 ) return -1; if( (p1=g1->bits) !=NULL && (p2=g2->bits) !=NULL ) for(i=0; i mend) mend=row; } } void drawdotg1(row, col, val) unsigned row, col, val; { if(row < MAXLINES && col < LINEWIDTH-1) { if(val) map[row][col]=CHRONE; else map[row][col]=CHRNONE; if(row > mend) mend=row; } } void drawdotg2(row, col, val) unsigned row, col, val; { if(row < MAXLINES && col < LINEWIDTH-1) { if(val) if(map[row][col]==CHRONE) map[row][col]=CHRBOTH; else map[row][col]=CHRTWO; else if(map[row][col]!=CHRONE) map[row][col]=CHRNONE; if(row > mend) mend=row; } } void drawglyf(size, g1) int size; GLYPH *g1; { int wd1, wd2, wdm; int ht1, ht2, ascm, desm; int i, j, k, val; char *p; int off1, off2; wd1=g1->metrics.rightSideBearing - g1->metrics.leftSideBearing; ht1=g1->metrics.ascent - g1->metrics.descent; wdm=wd1; ascm=g1->metrics.ascent; desm= -g1->metrics.descent; if(mbase==0) mbase=ascm+1; else if(LINEWIDTH-mx <= wdm+1) { mx=0; mbase=mend+ascm+2; } drawdot(mbase-ascm-1, mx, (size/10)%10+'0'); drawdot(mbase-ascm-1, mx+1, size%10+'0'); if( (p=g1->bits) !=NULL) for(i=0; i>=1) drawdot(i+mbase-g1->metrics.ascent, mx+j+k, (val&1)?CHRBOTH:CHRNONE); } } wdm++; if(wdm<3) wdm=3; mx+=wdm; drawdot(mbase, mx-1, '-'); } void drawdiff(size, g1, g2) int size; GLYPH *g1, *g2; { int wd1, wd2, wdm; int ht1, ht2, ascm, desm; int i, j, k, val; char *p; int off1, off2; wd1=g1->metrics.rightSideBearing - g1->metrics.leftSideBearing; ht1=g1->metrics.ascent - g1->metrics.descent; wd2=g2->metrics.rightSideBearing - g2->metrics.leftSideBearing; ht2=g2->metrics.ascent - g2->metrics.descent; if(wd1>wd2) { wdm=wd1; off1=0; off2=wd1-wd2; } else { wdm=wd2; off2=0; off1=wd2-wd1; } if(g1->metrics.ascent > g2->metrics.ascent) ascm=g1->metrics.ascent; else ascm=g2->metrics.ascent; if(g1->metrics.descent < g2->metrics.descent) desm= -g1->metrics.descent; else desm= -g2->metrics.descent; if(mbase==0) mbase=ascm+1; else if(LINEWIDTH-mx <= wdm+1) { mx=0; mbase=mend+ascm+2; } drawdot(mbase-ascm-1, mx, (size/10)%10+'0'); drawdot(mbase-ascm-1, mx+1, size%10+'0'); /* check which alignment is better */ if(off1!=0 || off2!=0) { int cntl,cntr; int a1, a2, d1, d2; int val1, val2; int rstep1, rstep2; cntl=cntr=0; rstep1=(wd1+7)/8; rstep2=(wd2+7)/8; a1=g1->metrics.ascent; d1=g1->metrics.descent; a2=g2->metrics.ascent; d2=g2->metrics.descent; #ifdef dbgoff printf("size: %d\n", size); #endif for(i=ascm; i>= -desm; i--) { for(j=0; ja1 || i=wd1) val1=0; else val1=( g1->bits[ (a1-i)*rstep1+j/8 ] >> (j%8) ) & 1; if(i>a2 || i=wd2) val2=0; else val2=( g2->bits[ (a2-i)*rstep2+j/8 ] >> (j%8) ) & 1; cntl += (val1 ^ val2); #ifdef dbgoff putchar(val1?'1':' '); putchar(val2?'2':' '); putchar('.'); #endif /* now the right alignment */ if(i>a1 || i=wd1 || jbits[ (a1-i)*rstep1+(j-off1)/8 ] >> ((j-off1)%8) ) & 1; if(i>a2 || i=wd2) val2=0; else val2=( g2->bits[ (a2-i)*rstep2+(j-off2)/8 ] >> ((j-off2)%8) ) & 1; cntr += (val1 ^ val2); #ifdef dbgoff putchar(val1?'1':' '); putchar(val2?'2':' '); putchar('|'); #endif } #ifdef dbgoff putchar('\n'); #endif } #ifdef dbgoff printf("size %d: left %d right %d\n",size, cntl, cntr); #endif if(cntl <= cntr) /* left is better or the same */ off1=off2=0; } if( (p=g1->bits) !=NULL) for(i=0; i>=1) drawdotg1(i+mbase-g1->metrics.ascent, mx+j+k+off1, val&1); } } if( (p=g2->bits) !=NULL) for(i=0; i>=1) drawdotg2(i+mbase-g2->metrics.ascent, mx+j+k+off2, val&1); } } wdm++; if(wdm<3) wdm=3; mx+=wdm; drawdot(mbase, mx-1, '-'); } void printmap(f) FILE *f; { int i, j; for(i=0; i<=mend; i++) { for(j=LINEWIDTH-1; j>=0 && map[i][j]==' '; j--) {} map[i][j+1]='\n'; map[i][j+2]=0; fputs(map[i], f); } }