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); }
static unsigned char* skip_specials(unsigned char* pos) { uint32_t i; while (*pos >= 240 && *pos != PK_POST) { i=0; switch (*pos++) { case 243: i = *pos++; case 242: i = 256 * i + *pos++; case 241: i = 256 * i + *pos++; case 240: i = 256 * i + *pos++; DEBUG_PRINT(DEBUG_PK,("\n PK SPECIAL\t'%.*s' ",(int)i,pos)); pos += i; break; case 244: #ifdef DEBUG { uint32_t c; c=UNumRead(pos,4); DEBUG_PRINT(DEBUG_PK,("\n PK SPECIAL\t%d",c)); } #endif pos += 4; break; case 245: break; case 246: DEBUG_PRINT(DEBUG_PK,("\n PK\tNOP ")); break; case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: case 255: Fatal("unexpected PK flagbyte %d", (int)*pos); } } return(pos); }
void FontDef(unsigned char* command, void* parent) { int32_t k; uint32_t c, s, d; uint8_t a, l; unsigned char* current; struct font_entry *tfontptr; /* temporary font_entry pointer */ struct font_num *tfontnump = NULL; /* temporary font_num pointer */ unsigned short i; current = command + 1; k = UNumRead(current, (int)*command - FNT_DEF1 + 1); current += (int)*command - FNT_DEF1 + 1; c = UNumRead(current, 4); /* checksum */ s = UNumRead(current+4, 4); /* space size */ d = UNumRead(current+8, 4); /* design size */ a = UNumRead(current+12, 1); /* length for font name */ l = UNumRead(current+13, 1); /* device length */ if (((struct font_entry*)parent)->type==FONT_TYPE_VF) { DEBUG_PRINT(DEBUG_VF,(" %d %d %d",k,c,s)); /* Rescale. s is relative to the actual scale /(1<<20) */ s = (uint32_t)((uint64_t) s * (((struct font_entry*) parent)->s) / (1<<20)); DEBUG_PRINT(DEBUG_VF,(" (%d) %d",s,d)); /* Oddly, d differs in the DVI and the VF that my system produces */ d = (uint32_t)((uint64_t) d * ((struct font_entry*)parent)->d / ((struct font_entry*)parent)->designsize); DEBUG_PRINT(DEBUG_VF,(" (%d)",d)); DEBUG_PRINT(DEBUG_VF,(" %d %d '%.*s'",a,l,a+l,current+14)); #ifdef DEBUG } else { DEBUG_PRINT(DEBUG_DVI,(" %d %d %d %d %d %d '%.*s'",k,c,s,d,a,l, a+l,current+14)); #endif } if (a+l > STRSIZE-1) Fatal("too long font name for font %ld",k); /* Find entry with this font number in use */ switch (((struct font_entry*)parent)->type) { case FONT_TYPE_VF: tfontnump = ((struct font_entry*)parent)->vffontnump; break; case DVI_TYPE: tfontnump = ((struct dvi_data*)parent)->fontnump; } while (tfontnump != NULL && tfontnump->k != k) { tfontnump = tfontnump->next; } /* If found, return if it is correct */ if (tfontnump!=NULL && tfontnump->fontp->s == s && tfontnump->fontp->d == d && strlen(tfontnump->fontp->n) == a+l && strncmp(tfontnump->fontp->n,(char*)current+14,a+l) == 0) { DEBUG_PRINT((DEBUG_DVI|DEBUG_VF),("\n FONT %d:\tMatch found",k)); return; } /* If not found, create new */ if (tfontnump==NULL) { if ((tfontnump=malloc(sizeof(struct font_num)))==NULL) Fatal("cannot malloc memory for new font number"); tfontnump->k=k; switch (((struct font_entry*)parent)->type) { case FONT_TYPE_VF: tfontnump->next=((struct font_entry*)parent)->vffontnump; ((struct font_entry*)parent)->vffontnump=tfontnump; break; case DVI_TYPE: tfontnump->next=((struct dvi_data*)parent)->fontnump; ((struct dvi_data*)parent)->fontnump=tfontnump; } } /* Search font list for possible match */ tfontptr = hfontptr; while (tfontptr != NULL && (tfontptr->s != s || tfontptr->d != d || strlen(tfontptr->n) != a+l || strncmp(tfontptr->n,(char*)current+14,a+l) != 0 ) ) { tfontptr = tfontptr->next; } /* If found, set its number and return */ if (tfontptr!=NULL) { DEBUG_PRINT((DEBUG_DVI|DEBUG_VF),("\n FONT %d:\tMatch found, number set",k)); tfontnump->fontp = tfontptr; return; } DEBUG_PRINT((DEBUG_DVI|DEBUG_VF),("\n FONT %d:\tNew entry created",k)); /* No fitting font found, create new entry. */ if ((tfontptr = calloc(1,sizeof(struct font_entry))) == NULL) Fatal("cannot malloc space for font_entry"); tfontptr->next = hfontptr; hfontptr = tfontptr; tfontnump->fontp = tfontptr; #ifndef WIN32 tfontptr->fmmap.fd = 0; #else /* WIN32 */ tfontptr->fmmap.hFile = INVALID_HANDLE_VALUE; #endif tfontptr->c = c; /* checksum */ tfontptr->s = s; /* space size */ tfontptr->d = d; /* design size */ tfontptr->a = a; /* length for font name */ tfontptr->l = l; /* device length */ strncpy(tfontptr->n,(char*)current+14,a+l); /* full font name */ tfontptr->n[a+l] = '\0'; tfontptr->name = NULL; for (i = FIRSTFNTCHAR; i <= LASTFNTCHAR; i++) { tfontptr->chr[i] = NULL; } tfontptr->dpi = (uint32_t)((ActualFactor((uint32_t)(1000.0*tfontptr->s /(double)tfontptr->d+0.5)) * ActualFactor(dvi->mag) * dpi*shrinkfactor) + 0.5); #ifdef HAVE_FT2 tfontptr->psfontmap=NULL; #endif }
void InitVF(struct font_entry * tfontp) { struct stat stat; unsigned char* position; int length; struct vf_char *tcharptr; uint32_t c=0; struct font_num *tfontnump; /* temporary font_num pointer */ DEBUG_PRINTF((DEBUG_DVI|DEBUG_VF),"\n OPEN FONT:\t'%s'", tfontp->name); Message(BE_VERBOSE,"<%s>", tfontp->name); if ((tfontp->filedes = open(tfontp->name,O_RDONLY)) == -1) Warning("font file %s could not be opened", tfontp->name); fstat(tfontp->filedes,&stat); tfontp->mmap = mmap(NULL,stat.st_size, PROT_READ, MAP_SHARED,tfontp->filedes,0); if (tfontp->mmap == (unsigned char *)-1) Fatal("cannot mmap VF file <%s> !\n",currentfont->name); if (*(tfontp->mmap) != PRE) Fatal("unknown font format in file <%s> !\n",currentfont->name); if (*(tfontp->mmap+1) != VF_ID) Fatal( "wrong version of vf file! (%d should be 202)\n", (int)*(tfontp->mmap+1)); DEBUG_PRINTF2(DEBUG_VF,"\n VF_PRE:\t'%.*s'", (int)*(tfontp->mmap+2), tfontp->mmap+3); position = tfontp->mmap+3 + *(tfontp->mmap+2); c=UNumRead(position, 4); DEBUG_PRINTF(DEBUG_VF," %d", c); CheckChecksum (tfontp->c, c, tfontp->name); tfontp->designsize = UNumRead(position+4,4); DEBUG_PRINTF(DEBUG_VF," %d", tfontp->designsize); tfontp->type = FONT_TYPE_VF; tfontp->vffontnump=NULL; /* Read font definitions */ position += 8; while(*position >= FNT_DEF1 && *position <= FNT_DEF4) { DEBUG_PRINTF2(DEBUG_VF,"\n @%ld VF:\t%s", (long)(position - tfontp->mmap), dvi_commands[*position]); FontDef(position,tfontp); length = dvi_commandlength[*position]; position += length + *(position + length-1) + *(position+length-2); } /* Default font is the first defined */ tfontnump = tfontp->vffontnump; while (tfontnump->next != NULL) { tfontnump = tfontnump->next; } tfontp->defaultfont=tfontnump->k; /* Read char definitions */ while(*position < FNT_DEF1) { DEBUG_PRINTF(DEBUG_VF,"\n@%ld VF CHAR:\t", (long)(position - tfontp->mmap)); tcharptr=xmalloc(sizeof(struct vf_char)); switch (*position) { case LONG_CHAR: tcharptr->length = UNumRead(position+1,4); c = UNumRead(position+5,4); tcharptr->tfmw = UNumRead(position+9,4); position += 13; break; default: tcharptr->length = UNumRead(position,1); c = UNumRead(position+1,1); tcharptr->tfmw = UNumRead(position+2,3); position += 5; } DEBUG_PRINTF2(DEBUG_VF,"%d %d",tcharptr->length,c); DEBUG_PRINTF(DEBUG_VF," %d",tcharptr->tfmw); tcharptr->tfmw = (int32_t) ((int64_t) tcharptr->tfmw * tfontp->s / (1 << 20)); DEBUG_PRINTF(DEBUG_VF," (%d)",tcharptr->tfmw); if (c > NFNTCHARS) /* Only positive for now */ Fatal("vf character exceeds numbering limit"); tfontp->chr[c] = tcharptr; tcharptr->mmap=position; position += tcharptr->length; } }
void InitPK(struct font_entry * tfontp) { unsigned char* position; struct char_entry *tcharptr; /* temporary char_entry pointer */ uint32_t hppp, vppp, packet_length; uint32_t c; DEBUG_PRINT((DEBUG_DVI|DEBUG_PK),("\n OPEN FONT:\t'%s'", tfontp->name)); Message(BE_VERBOSE,"<%s>", tfontp->name); if (MmapFile(tfontp->name,&(tfontp->fmmap))) Fatal("font file %s unusable", tfontp->name); position=(unsigned char*)tfontp->fmmap.data; if (tfontp->fmmap.size < 2 || tfontp->fmmap.size < 3+*(position+2)+16) Fatal("PK file %s ends prematurely",tfontp->name); if (*position++ != PK_PRE) Fatal("unknown font format in file %s",tfontp->name); if (*position++ != PK_ID) Fatal( "wrong version %d of PK file %s (should be 89)", (int)*(position-1),tfontp->name); DEBUG_PRINT(DEBUG_PK,("\n PK_PRE:\t'%.*s'",(int)*position, position+1)); position += *position + 1; tfontp->designsize = UNumRead(position, 4); DEBUG_PRINT(DEBUG_PK,(" %d", tfontp->designsize)); tfontp->type = FONT_TYPE_PK; c = UNumRead(position+4, 4); DEBUG_PRINT(DEBUG_PK,(" %d", c)); CheckChecksum (tfontp->c, c, tfontp->name); hppp = UNumRead(position+8, 4); vppp = UNumRead(position+12, 4); DEBUG_PRINT(DEBUG_PK,(" %d %d", hppp,vppp)); if (hppp != vppp) Warning("aspect ratio is %d:%d (should be 1:1)", hppp, vppp); tfontp->magnification = (uint32_t)((uint64_t)hppp * 7227 * 5 / 65536l + 50)/100; position+=16; /* Read char definitions */ position = skip_specials(position); while (*position != PK_POST) { DEBUG_PRINT(DEBUG_PK,("\n @%ld PK CHAR:\t%d", (long)((char *)position - tfontp->fmmap.data), *position)); if ((tcharptr = malloc(sizeof(struct char_entry))) == NULL) Fatal("cannot allocate space for char_entry"); tcharptr->flag_byte = *position; tcharptr->data = NULL; tcharptr->tfmw = 0; if ((*position & 7) == 7) { packet_length = UNumRead(position+1,4); c = UNumRead(position+5, 4); position += 9; } else if (*position & 4) { packet_length = (*position & 3) * 65536l + UNumRead(position+1, 2); c = UNumRead(position+3, 1); position += 4; } else { packet_length = (*position & 3) * 256 + UNumRead(position+1, 1); c = UNumRead(position+2, 1); position += 3; } DEBUG_PRINT(DEBUG_PK,(" %d %d",packet_length,c)); if (c > (LASTFNTCHAR)) Fatal("PK font %s exceeds char numbering limit",tfontp->name); tcharptr->length = packet_length; tcharptr->pkdata = position; tfontp->chr[c]=tcharptr; position += packet_length; position = skip_specials(position); } }
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); }