/* * webfont - * Make a PostScript Type1 font into a B/W image * and a fontinfo file. * * Paul Haeberli - 1995 * */ #include "math.h" #include "image.h" #include "stdio.h" #include "objfnt.h" #include "bitmap.h" #include "vect.h" #include "canvas.h" unsigned long *makebitmaps(); typedef struct glyph { unsigned long *data; int xsize, ysize; int pixoffset; int xdorg, ydorg; } glyph; int fbxsize, fbysize; objfnt *fnt; int pixhigh; int supersample; glyph **glyphs; char fullname[1024]; unsigned long *yflip(lbuf,xsize,ysize) unsigned long *lbuf; int xsize, ysize; { unsigned long *rbuf; int sy, dy; rbuf = (unsigned long *)malloc(xsize*ysize*sizeof(long)); for(dy=0; dy>8)&0xff,outf); fputc((val>>0)&0xff,outf); } writefontinfo(outname,imgname,fnt) char *outname; char *imgname; objfnt *fnt; { FILE *outf; int c, i, len, xadvance; int first, last; char advcode, sizecode; int xsize, ysize, pixoffset, xdorg, ydorg, pb; chardesc *cd; glyph *g; outf = fopen(outname,"w"); if(!outf) { fprintf(stderr,"webfont: can't open output file %s\n",outname); exit(1); } fputc(23,outf); fputc(45,outf); putshort(1,outf); /* advancedivisor */ putshort(0,outf); /* lineadvance x */ putshort(pixhigh,outf); /* lineadvance y */ advcode = 4; /* L-R, T-B, only X advances given */ fputc(advcode,outf); putshort(fnt->nchars,outf); /* glyphset */ putshort(fnt->charmin,outf); /* glyphset */ fputc(0,outf); /* glyphsetlist terminator */ fputc(0,outf); /* glyphsetlist terminator */ first = fnt->charmin; last = fnt->charmax; for(c=first; c<=last; c++) { i = c-first; cd = getchardesc(fnt,c); if(cd) xadvance = (pixhigh*cd->movex)/fnt->scale; else xadvance = 0; if(glyphs[i]) { g = glyphs[i]; xsize = g->xsize; ysize = g->ysize; xdorg = g->xdorg; ydorg = g->ydorg; pixoffset = g->pixoffset; } else { xsize = ysize = 0; pixoffset = 0; xdorg = ydorg = 0; } sizecode = 0; if(xadvance>255) sizecode |= 1; if(xsize>255 || ysize>255) sizecode |= 2; if(pixoffset<256) { pb = 1; } else if(pixoffset<(256*256)) { pb = 2; sizecode |= 4; } else if(pixoffset<(256*256*256)) { pb = 3; sizecode |= 8; } else { pb = 4; sizecode |= 4; sizecode |= 8; } if(xdorg>127 || xdorg<-128 || ydorg>127 || ydorg<-128) sizecode |= 16; printf("char %d sizecode %d adv %d size %d %d pixoffset %d dorg %d %d\n",c,sizecode,xadvance,xsize,ysize,pixoffset,xdorg,ydorg); fputc(sizecode,outf); if(xadvance>255) putshort(xadvance,outf); else fputc(xadvance,outf); if(xsize>255 || ysize>255) { putshort(xsize,outf); putshort(ysize,outf); } else { fputc(xsize,outf); fputc(ysize,outf); } for(i=0; i>(8*(pb-1-i)))&0xff,outf); if(xdorg>127 || xdorg<-128 || ydorg>127 || ydorg<-128) { putshort(xdorg,outf); putshort(ydorg,outf); } else { fputc(xdorg,outf); fputc(ydorg,outf); } } fclose(outf); } unsigned long *makepixdata(lbuf,xpix,ypix,xmin,xmax,ymin,ymax) unsigned long *lbuf; int xpix, ypix; int xmin, xmax, ymin, ymax; { unsigned long *gbuf, *lptr; int x, y, dxsize, dysize; dxsize = xmax-xmin+1; dysize = ymax-ymin+1; gbuf = lptr = (unsigned long *)malloc(dxsize*dysize*sizeof(long)); for(y=ymin; y<=ymax; y++) { for(x=xmin; x<=xmax; x++) *lptr++ = lbuf[y*xpix+x]; } return gbuf; } glyph *charglyph(fullname,psname,c) char *fullname; char *psname; int c; { glyph *g; FILE *outf; float inches; int margin, ixpix, iypix; unsigned long *lbuf; char cmd[1024]; int xmin, xmax, ymin, ymax; printf("car is '%c'\n",c); outf = fopen("PIXFONT.ps","w"); if(!outf) { fprintf(stderr,"pixfont: can't open output .ps file\n"); exit(1); } margin = pixhigh; inches = (supersample*3*pixhigh)/72.0; fprintf(outf,"%%!\n"); fprintf(outf,"/%s findfont\n",psname); fprintf(outf,"%d scalefont setfont\n",supersample*pixhigh); fprintf(outf,"%d %d moveto\n",supersample*margin,supersample*margin); if(c == '(' || c == ')') fprintf(outf,"(\\%c) show\n",c); else fprintf(outf,"(%c) show\n",c); fprintf(outf,"showpage\n"); fclose(outf); sprintf(cmd,"fromps PIXFONT.ps PIXFONT -p 72 -s %f %f",inches,inches); system(cmd); if(supersample>1) { sprintf(cmd,"izoom PIXFONT001.rgb PIXFONT.rgb %f %f -l",1.0/supersample,1.0/supersample); system(cmd); sprintf(cmd,"imgexp PIXFONT.rgb PIXFONT001.rgb 0 250"); system(cmd); } sizeofimage("PIXFONT001.rgb",&ixpix,&iypix); lbuf = (unsigned long *)longimagedata("PIXFONT001.rgb"); if(findbbox(lbuf,ixpix,iypix,&xmin,&xmax,&ymin,&ymax)) { g = (glyph *)malloc(sizeof(glyph)); g->xsize = xmax-xmin+1; g->ysize = ymax-ymin+1; g->data = makepixdata(lbuf,ixpix,iypix,xmin,xmax,ymin,ymax); g->xdorg = xmin-margin; g->ydorg = ymin-margin; printf("size %d %d org %d %d\n",g->xsize,g->ysize,g->xdorg,g->ydorg); return g; } else return 0; } findbbox(cbuf, xpix, ypix, xmin, xmax, ymin, ymax) unsigned char *cbuf; int xpix, ypix; int *xmin, *xmax, *ymin, *ymax; { int Xmin, Xmax, Ymin, Ymax; int x, y; Xmin = Ymin = 10000; Xmax = Ymax = -10000; for(y=0; yx) Xmin = x; if(Xmaxy) Ymin = y; if(Ymaxcharmin; last = fnt->charmax; nchars = last-first+1; /* malloc temp buffers */ glyphs = (glyph **)mymalloc(nchars*sizeof(glyph*)); for(c=first; c<=last; c++) { i = c-first; if(hasvertdata(fnt,c)) { cd = getchardesc(fnt,c); glyphs[i] = charglyph(fullname,psname,c); } else glyphs[i] = 0; } pixoffset = 0; for(c=first; c<=last; c++) { i = c-first; if(glyphs[i]) { pixoffset += (glyphs[i]->xsize*glyphs[i]->ysize); } } oxsize = 256; oysize = 1+((pixoffset-1)/oxsize); printf("width height %d %d\n",oxsize,oysize); lbuf = (unsigned long *)malloc(oxsize*oysize*sizeof(long)); setlongs(lbuf,0xffffff,oxsize*oysize); pixoffset = 0; for(c=first; c<=last; c++) { i = c-first; if(glyphs[i]) { placeglyph(lbuf,pixoffset,glyphs[i]); pixoffset += (glyphs[i]->xsize*glyphs[i]->ysize); } } *fxsize = oxsize; *fysize = oysize; return lbuf; } placeglyph(lbuf,pixoffset,g) unsigned long *lbuf; int pixoffset; glyph *g; { int x, y; unsigned long *sptr; sptr = g->data; lbuf += pixoffset; for(y=0; yysize; y++) { for(x=0; xxsize; x++) *lbuf++ = *sptr++; } g->pixoffset = pixoffset; } setlongs(lbuf,val,n) unsigned long *lbuf; long val; int n; { while(n--) *lbuf++ = val; }