/* t1.c */ /************************************************************************ Part of the dvipng distribution This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . Copyright (C) 2002-2008 Jan-Åke Larsson ************************************************************************/ #include "dvipng.h" #ifdef HAVE_ALLOCA_H # include #endif void LoadT1(int32_t c, struct char_entry * ptr) { GLYPH *glyph; int original_width,original_height; int i,j,k,width,height; unsigned short shrunk_width,shrunk_height; short xoffset,yoffset; unsigned short i_offset,j_offset; DEBUG_PRINT(DEBUG_T1,("\n LOAD T1 CHAR\t%d",c)); if ((glyph= T1_SetChar(currentfont->T1id, c, (float)currentfont->dpi*currentfont->d/65536/72.27, currentfont->psfontmap==NULL ? NULL : currentfont->psfontmap->t1_transformp)) ==NULL) Fatal("cannot load T1 char %d",c); DEBUG_PRINT(DEBUG_T1,(" (%d)",ptr->tfmw)); original_width = glyph->metrics.rightSideBearing - glyph->metrics.leftSideBearing; original_height = glyph->metrics.ascent - glyph->metrics.descent; DEBUG_PRINT(DEBUG_T1,(" %dx%d",original_width,original_height)); if (original_width > 0x7fff || original_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 = -glyph->metrics.leftSideBearing; /* printf("xoffset: %d\n",xoffset); */ i_offset = ( shrinkfactor - xoffset % shrinkfactor ) % shrinkfactor; width = original_width+i_offset; ptr->xOffset = xoffset+i_offset; yoffset = glyph->metrics.ascent-1; /* printf("yoffset: %d\n",yoffset); */ j_offset = ( shrinkfactor - (yoffset-(shrinkfactor-1)) % shrinkfactor ) % shrinkfactor; height = original_height+j_offset; ptr->yOffset = yoffset+j_offset; DEBUG_PRINT(DEBUG_T1,(" (%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; /* printf("(%d,%d) ",ptr->w,ptr->h); */ DEBUG_PRINT(DEBUG_GLYPH,("\nDRAW GLYPH %d\n", (int)c)); /* Shrink raster while doing antialiasing. */ if ((ptr->data = calloc(shrunk_width*shrunk_height,sizeof(char))) == NULL) Fatal("unable to allocate image space for char %c", (char)c); for (j = 0; j < original_height; j++) { for (i = 0; i < (original_width+7)/8 ; i++) { for (k = 0; k < 8 ; k++) { DEBUG_PRINT(DEBUG_GLYPH, ("%c", (glyph->bits[i+j*((original_width+7)/8)] & (1<data[(i*8+k+i_offset)/shrinkfactor +(j+j_offset)/shrinkfactor*shrunk_width] += (glyph->bits[i+j*((original_width+7)/8)] & (1<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")); } } bool InitT1(struct font_entry * tfontp) { if (libt1==NULL) { if ((libt1=T1_InitLib( NO_LOGFILE | IGNORE_CONFIGFILE | IGNORE_FONTDATABASE | T1_NO_AFM)) == NULL) { Warning("an error occured during t1lib initialisation, disabling it"); option_flags &= ~USE_LIBT1; return(false); } # ifdef DEBUG else DEBUG_PRINT(DEBUG_T1,("\n T1LIB VERSION: %s", T1_GetLibIdent())); # endif } DEBUG_PRINT((DEBUG_DVI|DEBUG_T1),("\n OPEN T1 FONT:\t'%s'", tfontp->name)); tfontp->T1id = T1_AddFont( tfontp->name ); if (tfontp->T1id < 0) { Warning("t1lib could not open font file %s", tfontp->name); return(false); } if (T1_LoadFont(tfontp->T1id)) { Warning("t1lib could not load font file %s", tfontp->name); return(false); } Message(BE_VERBOSE,"<%s>", tfontp->name); if (tfontp->psfontmap!=NULL && tfontp->psfontmap->encoding != NULL) { DEBUG_PRINT(DEBUG_T1,("\n USE ENCODING:\t'%s'", tfontp->psfontmap->encoding->name)); if (T1_ReencodeFont(tfontp->T1id,tfontp->psfontmap->encoding->charname)) { Warning("unable to use font encoding '%s' for %s", tfontp->psfontmap->encoding->name,tfontp->name); return(false); } } tfontp->type = FONT_TYPE_T1; return(true); } void UnLoadT1(struct char_entry *ptr) { if (ptr->data!=NULL) free(ptr->data); ptr->data=NULL; } void DoneT1(struct font_entry *tfontp) { int c=0; int error = T1_DeleteFont( tfontp->T1id ); if (error) Warning("font file %s could not be closed", tfontp->name); while(cchr[c]!=NULL) { UnLoadT1((struct char_entry*)tfontp->chr[c]); free(tfontp->chr[c]); tfontp->chr[c]=NULL; } c++; } tfontp->name[0]='\0'; }