bool ReadTFM(struct font_entry * tfontp, char* tfmname) { struct filemmap fmmap; struct char_entry *tcharptr; unsigned char *position; int lh,bc,ec,nw, c; dviunits* width; DEBUG_PRINT((DEBUG_DVI|DEBUG_FT|DEBUG_TFM), ("\n OPEN METRICS:\t'%s'", tfmname)); if (MmapFile(tfmname,&fmmap)) return(false); position=(unsigned char*)fmmap.data; if (fmmap.size<10) Fatal("TFM file %s ends prematurely",tfmname); lh = UNumRead(position+2,2); bc = UNumRead(position+4,2); ec = UNumRead(position+6,2); nw = UNumRead(position+8,2); DEBUG_PRINT(DEBUG_TFM,(" %d %d %d %d",lh,bc,ec,nw)); if (nw>0) { unsigned char *end=(unsigned char *) fmmap.data+fmmap.size; if ((width=malloc(nw*sizeof(dviunits)))==NULL) Fatal("cannot allocate memory for TFM widths"); c=0; position=position+24+(lh+ec-bc+1)*4; while( c < nw ) { if (position >= end - 4) Fatal("TFM file %s ends prematurely",tfmname); width[c] = SNumRead(position,4); c++; position += 4; } /* Read char widths */ c=bc; position=(unsigned char*)fmmap.data+24+lh*4; while(c <= ec) { if (position >= end) Fatal("TFM file %s ends prematurely",tfmname); DEBUG_PRINT(DEBUG_TFM,("\n@%ld TFM METRICS:\t", (long)((char *)position - fmmap.data))); if ((tcharptr=malloc(sizeof(struct char_entry)))==NULL) Fatal("cannot allocate memory for TFM char entry"); tcharptr->data=NULL; if (*position < nw) { tcharptr->tfmw=width[*position]; } else { Fatal("TFM file %s lacks width for char %u", tfmname, *position); } DEBUG_PRINT(DEBUG_TFM,("%d [%d] %d",c,*position,tcharptr->tfmw)); tcharptr->tfmw = (dviunits) ((int64_t) tcharptr->tfmw * tfontp->s / (1 << 20)); DEBUG_PRINT(DEBUG_TFM,(" (%d)",tcharptr->tfmw)); if (c >= NFNTCHARS) /* Only positive for now */ Fatal("tfm file %s exceeds char numbering limit %u",tfmname,NFNTCHARS); tfontp->chr[c] = tcharptr; c++; position += 4; } free(width); } UnMmapFile(&fmmap); return(true); }
void LoadPK(int32_t c, register struct char_entry * ptr) { unsigned short shrunk_width,shrunk_height; unsigned short width,height; short xoffset,yoffset; unsigned short i_offset,j_offset; int i,j,k,n; int count=0; bool paint_switch; unsigned char *pos,*buffer; DEBUG_PRINT(DEBUG_PK,("\n LOAD PK CHAR\t%d",c)); pos=ptr->pkdata; if ((ptr->flag_byte & 7) == 7) n=4; else if ((ptr->flag_byte & 4) == 4) n=2; else n=1; dyn_f = ptr->flag_byte / 16; paint_switch = ((ptr->flag_byte & 8) != 0); /* * Read character preamble */ if (n != 4) { ptr->tfmw = UNumRead(pos, 3); /* +n: vertical escapement not used */ pos+=3+n; } else { ptr->tfmw = UNumRead(pos, 4); /* +4: horizontal escapement not used */ /* +n: vertical escapement not used */ pos+=8+n; } DEBUG_PRINT(DEBUG_PK,(" %d",ptr->tfmw)); ptr->tfmw = (dviunits) ((int64_t) ptr->tfmw * currentfont->s / 0x100000 ); DEBUG_PRINT(DEBUG_PK,(" (%d)",ptr->tfmw)); width = UNumRead(pos, n); height = UNumRead(pos+=n, n); DEBUG_PRINT(DEBUG_PK,(" %dx%d",width,height)); if (width > 0x7fff || height > 0x7fff) Fatal("character %d too large in file %s", c, currentfont->name); /* * Hotspot issues: Shrinking to the topleft corner rather than the hotspot will displace glyphs a fraction of a pixel. We deal with this in as follows: The glyph is shrunk to its hotspot by offsetting the bitmap somewhat to put the hotspot in the lower left corner of a "shrink square". Shrinking to the topleft corner will then act as shrinking to the hotspot. This may enlarge the bitmap somewhat, of course. (Also remember that the below calculation of i/j_offset is in integer arithmetics.) There will still be a displacement from rounding the dvi position, but vertically it will be equal for all glyphs on a line, so we displace a whole line vertically by fractions of a pixel. This is acceptible, IMHO. Sometime there will be support for subpixel positioning, horizontally. Will do for now, I suppose. */ xoffset = SNumRead(pos+=n, n); i_offset = ( shrinkfactor - xoffset % shrinkfactor ) % shrinkfactor; width += i_offset; ptr->xOffset = xoffset+i_offset; yoffset = SNumRead(pos+=n, n); j_offset = ( shrinkfactor - (yoffset-(shrinkfactor-1)) % shrinkfactor ) % shrinkfactor; height += j_offset; ptr->yOffset = yoffset+j_offset; DEBUG_PRINT(DEBUG_PK,(" (%dx%d)",width,height)); /* Extra marginal so that we do not crop the image when shrinking. */ shrunk_width = (width + shrinkfactor - 1) / shrinkfactor; shrunk_height = (height + shrinkfactor - 1) / shrinkfactor; ptr->w = shrunk_width; ptr->h = shrunk_height; pos+=n; if ((buffer = calloc(shrunk_width*shrunk_height* shrinkfactor*shrinkfactor,sizeof(char)))==NULL) Fatal("cannot allocate space for pk buffer"); DEBUG_PRINT(DEBUG_GLYPH,("\nDRAW GLYPH %d\n", (int)c)); /* Raster char */ if (dyn_f == 14) { /* get raster by bits */ int bitweight = 0; for (j = j_offset; j < (int) height; j++) { /* get all rows */ for (i = i_offset; i < (int) width; i++) { /* get one row */ bitweight /= 2; if (bitweight == 0) { count = *pos++; bitweight = 128; } if (count & bitweight) { buffer[i+j*width]=1; #ifdef DEBUG DEBUG_PRINT(DEBUG_GLYPH,("+")); } else { DEBUG_PRINT(DEBUG_GLYPH,(" ")); #endif } } DEBUG_PRINT(DEBUG_GLYPH,("|\n")); } } else { /* get packed raster */ poshalf=0; repeatcount = 0; for(i=i_offset, j=j_offset; j<height; ) { count = pk_packed_num(&pos); while (count > 0) { if (i+count < width) { if (paint_switch) for(k=0;k<count;k++) { buffer[k+i+j*width]=1; DEBUG_PRINT(DEBUG_GLYPH,("*")); } #ifdef DEBUG else for(k=0;k<count;k++) DEBUG_PRINT(DEBUG_GLYPH,(" ")); #endif i += count; count = 0; } else { if (paint_switch) for(k=i;k<width;k++) { buffer[k+j*width]=1; DEBUG_PRINT(DEBUG_GLYPH,("#")); } #ifdef DEBUG else for(k=i;k<width;k++) DEBUG_PRINT(DEBUG_GLYPH,(" ")); #endif DEBUG_PRINT(DEBUG_GLYPH,("|\n")); j++; count -= width-i; /* Repeat row(s) */ for (;repeatcount>0; repeatcount--,j++) { for (i = i_offset; i<width; i++) { buffer[i+j*width]=buffer[i+(j-1)*width]; #ifdef DEBUG if (buffer[i+j*width]>0) { DEBUG_PRINT(DEBUG_GLYPH,("=")); } else { DEBUG_PRINT(DEBUG_GLYPH,(" ")); } #endif } DEBUG_PRINT(DEBUG_GLYPH,("|\n")); } i=i_offset; } } paint_switch = 1 - paint_switch; } if (i>i_offset) Fatal("wrong number of bits stored: char. %c, font %s", (char)c, currentfont->name); if (j>height) Fatal("bad PK file %s, too many bits", currentfont->name); } /* Shrink raster while doing antialiasing. (See above. The single-glyph output seems better than what xdvi at 300 dpi, shrinkfactor 3 produces.) */ if ((ptr->data = calloc(shrunk_width*shrunk_height,sizeof(char))) == NULL) Fatal("unable to malloc image space for char %c", (char)c); for (j = 0; j < (int) height; j++) { for (i = 0; i < (int) width; i++) { /* if (((i % shrinkfactor) == 0) && ((j % shrinkfactor) == 0)) ptr->data[i/shrinkfactor+j/shrinkfactor*shrunk_width] = buffer[i+j*width]; else */ ptr->data[i/shrinkfactor+j/shrinkfactor*shrunk_width] += buffer[i+j*width]; } } for (j = 0; j < shrunk_height; j++) { for (i = 0; i < shrunk_width; i++) { ptr->data[i+j*shrunk_width] = ptr->data[i+j*shrunk_width] *255/shrinkfactor/shrinkfactor; DEBUG_PRINT(DEBUG_GLYPH,("%3u ",ptr->data[i+j*shrunk_width])); } DEBUG_PRINT(DEBUG_GLYPH,("|\n")); } free(buffer); }