339 lines
6.1 KiB
C
339 lines
6.1 KiB
C
/*
|
|
* 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<ht1; i++) {
|
|
for(j=0; j<wd1; j+=8) {
|
|
if( *p1++ != *p2++)
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
resetmap()
|
|
{
|
|
int i, j;
|
|
|
|
for(i=0; i<MAXLINES; i++)
|
|
for(j=0; j<LINEWIDTH; j++)
|
|
map[i][j]=' ';
|
|
mbase=mx=mend=0;
|
|
}
|
|
|
|
void
|
|
drawdot(row, col, val)
|
|
unsigned row, col, val;
|
|
{
|
|
if(row < MAXLINES && col < LINEWIDTH-1) {
|
|
map[row][col]=val;
|
|
if(row > 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<ht1; i++) {
|
|
for(j=0; j<wd1; j+=8) {
|
|
val = *p++;
|
|
for(k=0; k<8 && j+k<wd1; k++, val>>=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; j<wdm; j++) {
|
|
/* first the left alignment */
|
|
if(i>a1 || i<d1 || j>=wd1)
|
|
val1=0;
|
|
else
|
|
val1=( g1->bits[ (a1-i)*rstep1+j/8 ] >> (j%8) ) & 1;
|
|
if(i>a2 || i<d2 || j>=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<d1 || j-off1>=wd1 || j<off1)
|
|
val1=0;
|
|
else
|
|
val1=( g1->bits[ (a1-i)*rstep1+(j-off1)/8 ] >> ((j-off1)%8) ) & 1;
|
|
if(i>a2 || i<d2 || j-off2>=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<ht1; i++) {
|
|
for(j=0; j<wd1; j+=8) {
|
|
val = *p++;
|
|
for(k=0; k<8 && j+k<wd1; k++, val>>=1)
|
|
drawdotg1(i+mbase-g1->metrics.ascent, mx+j+k+off1, val&1);
|
|
}
|
|
}
|
|
if( (p=g2->bits) !=NULL)
|
|
for(i=0; i<ht2; i++) {
|
|
for(j=0; j<wd2; j+=8) {
|
|
val = *p++;
|
|
for(k=0; k<8 && j+k<wd2; k++, val>>=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);
|
|
}
|
|
}
|
|
|