Back to index

tetex-bin  3.0
Functions
t1set.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

GLYPHT1_SetChar (int FontID, char charcode, float size, T1_TMATRIX *transform)
GLYPHT1_SetString (int FontID, char *string, volatile int len, long spaceoff, int modflag, float size, T1_TMATRIX *transform)
GLYPHT1_SetRect (int FontID, float size, float width, float height, T1_TMATRIX *transform)
void fill (char *dest, int h, int w, struct region *area, int byte, int bit, int wordsize)
void fillrun (char *p, pel x0, pel x1, int bit)
GLYPHT1_CopyGlyph (GLYPH *glyph)
void T1_DumpGlyph (GLYPH *glyph)
GLYPHT1_ConcatGlyphs (GLYPH *glyph1, GLYPH *glyph2, int x_off, int y_off, int modflag)
GLYPHT1_FillOutline (T1_OUTLINE *path, int modflag)
struct regionfontfcnB (int FontID, int modflag, struct XYspace *S, char **ev, unsigned char index, int *mode, psfont *Font_Ptr, int do_raster, float strokewidth)
struct regionfontfcnB_string (int FontID, int modflag, struct XYspace *S, char **ev, unsigned char *string, int no_chars, int *mode, psfont *Font_Ptr, int *kern_pairs, long spacewidth, int do_raster, float strokewidth)
struct regionfontfcnB_ByName (int FontID, int modflag, struct XYspace *S, char *charname, int *mode, psfont *Font_Ptr, int do_raster)
struct regionfontfcnRect (float width, float height, struct XYspace *S, int *mode, int do_raster, float strokewidth)

Function Documentation

void fill ( char *  dest,
int  h,
int  w,
struct region area,
int  byte,
int  bit,
int  wordsize 
)

Definition at line 1307 of file t1set.c.

{
  register struct edgelist *edge;  /* for looping through edges         */
  register char *p;     /* current scan line in 'dest'                  */
  register int y;       /* for looping through scans                    */
  register int wbytes = w / 8;  /* number of bytes in width             */
  register pel *leftP,*rightP;  /* pointers to X values, left and right */
  int xmin = area->xmin;  /* upper left X                               */
  int ymin = area->ymin;  /* upper left Y                               */
  
  for (edge = area->anchor; VALIDEDGE(edge); edge = edge->link->link) {
    
    p = dest + (edge->ymin - ymin) * wbytes;
    leftP = edge->xvalues;
    rightP = edge->link->xvalues;
    
    for (y = edge->ymin; y < edge->ymax; y++) {
      fillrun(p, *leftP++ - xmin , *rightP++ - xmin, bit);
      p += wbytes;
    }
  }
  /* 
    Now, as an afterthought, we'll go reorganize if odd byte order requires
    it:
    */
  /* We do not reorganize since t1lib internally always uses LSBFirst */
  /*
  if ( 0 && wordsize != 8) {
    register int i; 
    printf("Reorganizing data ..\n");
    
    switch (wordsize) { 
    case 16: 
      { 
       register unsigned short data,*p; 
       p = (unsigned short *) dest; 
       for (i = h * w /16; --i >= 0;) { 
         data = *p; 
         *p++ = (data << 8) + (data >> 8); 
       } 
       break; 
      } 
    case 64: 
    case 32: 
      { 
       register ULONG data,*p; 
       p = (ULONG *) dest; 
       for (i = h * w / 32; --i >= 0;) { 
         data = *p; 
         *p++ = (data << 24) + (data >> 24) 
           + (0xFF00 & (data >> 8)) 
           + (0xFF0000 & (data << 8)); 
       } 
       if (wordsize == 64) { 
         p = (ULONG *) dest; 
         for (i = h * w / 64; --i >= 0;) { 
           data = *p++; 
           p[-1] = p[0]; 
           *p++ = data; 
         } 
       }
       break; 
      } 
    default: 
      abort("xiFill: unknown format"); 
    } 
  }
  */
}
void fillrun ( char *  p,
pel  x0,
pel  x1,
int  bit 
)
struct region* fontfcnB ( int  FontID,
int  modflag,
struct XYspace S,
char **  ev,
unsigned char  index,
int mode,
psfont Font_Ptr,
int  do_raster,
float  strokewidth 
) [read]

Definition at line 277 of file fontfcn.c.

{
 
  psobj *charnameP; /* points to psobj that is name of character*/
  FontInfo *pAFMData=NULL;
  int i=-1;
  int j=0;
  int numPieces=1;
  int N;
  T1_PATHPOINT currdisp;
  int basechar;
  
  psdict *CharStringsDictP; /* dictionary with char strings     */
  psobj   CodeName;   /* used to store the translation of the name*/
  psobj  *SubrsArrayP;
  psobj  *theStringP;
  int localmode=0;
  
  struct segment *charpath=NULL;   /* the path for this character   */           
  struct segment *tmppath1=NULL;
  struct segment *tmppath2=NULL;
  struct segment *tmppath3=NULL;
  struct segment *tmppath4=NULL;
  
   
  /* set the global font pointer to the address of already allocated
     structure and setup pointers*/
  FontP=Font_Ptr;
  CharStringsDictP =  FontP->CharStringsP;
  SubrsArrayP = &(FontP->Subrs);
  charnameP = &CodeName;

  if (ev==NULL){  /* font-internal encoding should be used */
    charnameP->len = FontP->fontInfoP[ENCODING].value.data.arrayP[index].len;
    charnameP->data.stringP = (unsigned char *) FontP->fontInfoP[ENCODING].value.data.arrayP[index].data.arrayP;
  }
  else{           /* some user-supplied encoding is to be used */
    charnameP->len = strlen(ev[index]);
    charnameP->data.stringP = (unsigned char *) ev[index];
  }
  strncpy( (char *)CurCharName, (char *)charnameP->data.stringP, charnameP->len);
  CurCharName[charnameP->len]='\0';
  
 
  /* search the chars string for this charname as key */
  basechar = SearchDictName(CharStringsDictP,charnameP);
  if (basechar<=0) {
    /* Check first, whether a char in question is a composite char */
    if ((i=isCompositeChar( FontID, CurCharName))>-1) {
      /* i is now the index of the composite char definitions
        (starting at 0). At this point it is clear that AFM-info
        must be present -> fetch first component of composite char. */
      pAFMData=pFontBase->pFontArray[FontID].pAFMData;
      charnameP->len=strlen( pAFMData->ccd[i].pieces[0].pccName);
      charnameP->data.stringP=(unsigned char*)pAFMData->ccd[i].pieces[0].pccName;
      numPieces=pAFMData->ccd[i].numOfPieces;
      
      if ((basechar=SearchDictName(CharStringsDictP,charnameP))<=0) {
       /* this is bad, AFM-file and font file do not match. This 
          will most probably lead to errors or inconsistencies later.
          However, we substitute .notdef and inform the user via
          logfile and T1_errno. */
       sprintf( err_warn_msg_buf,
               "Charstring \"%s\" needed to construct composite char \"%s\" not defined (FontID=%d)",
               pAFMData->ccd[i].pieces[0].pccName,
               pAFMData->ccd[i].ccName, FontID);
       T1_PrintLog( "fontfcnB():", err_warn_msg_buf, T1LOG_WARNING);
       T1_errno=T1ERR_COMPOSITE_CHAR;
      }
    }
  }
  
  if (basechar<=0) { /* This  means the requested char is unknown or the
                     base char of a composite is not found ->
                     we substitute .notdef */
    charnameP = &CodeName;
    charnameP->len = 7;
    charnameP->data.stringP = (unsigned char *) notdef;
    basechar = SearchDictName(CharStringsDictP,charnameP);
    localmode=FF_NOTDEF_SUBST;
    /* Font must be completely damaged if it doesn't define a .notdef */
    if (basechar<=0) {
      *mode=FF_PARSE_ERROR;
      return(NULL);
    }
  } /* if (basechar<=0) */
  /* basechar is now the index of the base character in the CharStrings
     dictionary */

  /* we provide the Type1Char() procedure with the name of the character
     to rasterize for debugging purposes */
  strncpy( (char *)CurCharName, (char *)charnameP->data.stringP, charnameP->len);
  CurCharName[charnameP->len]='\0';
  /* get CharString and character path */
  theStringP = &(CharStringsDictP[basechar].value);
  tmppath2 = (struct segment *) Type1Char(FontP,S,theStringP,SubrsArrayP,NULL,
                                     FontP->BluesP,mode,CurCharName,strokewidth);
  /* if Type1Char reported an error, then return */
  if ( *mode == FF_PARSE_ERROR || *mode==FF_PATH_ERROR)
    return(NULL);
  
  /* Defer rastering to later, we first have to handle the composite
     symbols */
  for (j=1; j<numPieces; j++) {
    /* get composite symbol name */
    charnameP->len=strlen( pAFMData->ccd[i].pieces[j].pccName);
    charnameP->data.stringP=(unsigned char*)pAFMData->ccd[i].pieces[j].pccName;
    /* get CharString definition */
    if ((N=SearchDictName(CharStringsDictP,charnameP))<=0) {
      /* handling of errors, see comments above ... */
      sprintf( err_warn_msg_buf,
              "Charstring \"%s\" needed to construct composite char \"%s\" not defined (FontID=%d)",
              pAFMData->ccd[i].pieces[j].pccName,
              pAFMData->ccd[i].ccName, FontID);
      T1_PrintLog( "fontfcnB():", err_warn_msg_buf, T1LOG_WARNING);
      charnameP = &CodeName;
      charnameP->len = 7;
      charnameP->data.stringP = (unsigned char *) notdef;
      N = SearchDictName(CharStringsDictP,charnameP);
      localmode=FF_NOTDEF_SUBST;
      /* damaged Font */
      if (N<=0) {
       *mode=FF_PARSE_ERROR;
       if (charpath!=NULL) {
         KillPath( charpath);
       }
       return(NULL);
      }
    }
    theStringP = &(CharStringsDictP[N].value);
    tmppath1=(struct segment *)ILoc(S,
                                pAFMData->ccd[i].pieces[j].deltax,
                                pAFMData->ccd[i].pieces[j].deltay);
    
    strncpy( (char *)CurCharName, (char *)charnameP->data.stringP, charnameP->len);
    CurCharName[charnameP->len]='\0';
    charpath=(struct segment *)Type1Char(FontP,S,theStringP,SubrsArrayP,NULL,
                                    FontP->BluesP,mode,CurCharName,strokewidth);
    /* return if Type1Char reports an error */
    if ( *mode == FF_PARSE_ERROR || *mode==FF_PATH_ERROR)
      return(NULL);
    /* get escapement of current symbol */
    currdisp=getDisplacement( charpath);
    /* concat displacement and symbol path */
    charpath=(struct segment *)Join(tmppath1,charpath);
    /* for composite symbols we have to step back the char escapement.
       this is, in order to be able to use accents that cause a
       non zero displacement of the current point! We further have to
       step back the displacement from composite char data. */
    tmppath1=(struct segment *)t1_PathSegment( MOVETYPE, -currdisp.x, -currdisp.y);
    tmppath3=(struct segment *)ILoc(S,
                                -pAFMData->ccd[i].pieces[j].deltax,
                                -pAFMData->ccd[i].pieces[j].deltay);
    tmppath3=(struct segment *)Join(tmppath1,tmppath3);
    /* create path, or, respectively, append to existing path */
    if (tmppath4==NULL) {
      tmppath4=(struct segment *)Join(charpath,tmppath3);
    }
    else {
      charpath=(struct segment *)Join(charpath,tmppath3);
      tmppath4=(struct segment *)Join(tmppath4,charpath);
    }
  }

  /* concat composite symbols and base char */
  if (tmppath4==NULL) { /* no previous composite symbols */
    charpath=tmppath2; /* a simple char */
  }
  else { 
    charpath=(struct segment *)Join(tmppath4,tmppath2);
  }
  
  
  if (do_raster) { 
    /* fill with winding rule unless path was requested */
    if (*mode != FF_PATH) {
      charpath =  (struct segment *)Interior(charpath,WINDINGRULE+CONTINUITY);
    }
  }

  if (*mode==0)
    *mode=localmode;
  
  return((xobject) charpath);
}

Here is the call graph for this function:

struct region* fontfcnB_ByName ( int  FontID,
int  modflag,
struct XYspace S,
char *  charname,
int mode,
psfont Font_Ptr,
int  do_raster 
) [read]
struct region* fontfcnB_string ( int  FontID,
int  modflag,
struct XYspace S,
char **  ev,
unsigned char *  string,
int  no_chars,
int mode,
psfont Font_Ptr,
int kern_pairs,
long  spacewidth,
int  do_raster,
float  strokewidth 
) [read]

Definition at line 629 of file fontfcn.c.

{
 
  psobj *charnameP; /* points to psobj that is name of character*/
  FontInfo *pAFMData=NULL;
  int i=-1;
  int j=0;
  int k=0;
  long acc_width=0;
  int numPieces=1;
  int N;
  T1_PATHPOINT currdisp;
  int basechar;
  
  psdict *CharStringsDictP; /* dictionary with char strings     */
  psobj   CodeName;   /* used to store the translation of the name*/
  psobj  *SubrsArrayP;
  psobj  *theStringP;
  int localmode=0;
  
  struct segment *charpath=NULL;   /* the path for this character   */           
  struct segment *tmppath1=NULL;
  struct segment *tmppath2=NULL;
  struct segment *tmppath3=NULL;
  struct segment *tmppath4=NULL;
  struct segment *tmppath5=NULL;
  
   
  /* set the global font pointer to the address of already allocated
     structure and setup pointers*/
  FontP=Font_Ptr;
  CharStringsDictP =  FontP->CharStringsP;
  SubrsArrayP = &(FontP->Subrs);
  charnameP = &CodeName;

  
  /* In the following for-loop, all characters are processed, one after
     the other. Between them, the amount of kerning is inserted.
     The number of path variables used is somewhat numerous. We use the
     follwing conventions:

     charpath:  the overall path of the string.
     tmppath5:  the overall path of one component (possibly a composite symbol)
     tmppath2:  the path of a simple char or base char of a composite
     tmppath4:  the path of all "accents" of a composite symbol
  */
  for (k=0; k<no_chars;k++) {
    if (ev==NULL){  /* font-internal encoding should be used */
      charnameP = &CodeName;
      charnameP->len = FontP->fontInfoP[ENCODING].value.data.arrayP[string[k]].len;
      charnameP->data.stringP = (unsigned char *) FontP->fontInfoP[ENCODING].value.data.arrayP[string[k]].data.arrayP;
    }
    else {           /* some user-supplied encoding is to be used */
      charnameP = &CodeName;
      charnameP->len = strlen(ev[string[k]]);
      charnameP->data.stringP = (unsigned char*) ev[string[k]];
    }
    
    /* Spacing is to be under users control: => if space is the charname, don't
       raster it. Rather, generate a horizontal movement of spacewidth: */
    if (strcmp((char *)charnameP->data.stringP, "space")==0){
      tmppath5=(struct segment *)ILoc(S, spacewidth,0);
      acc_width += spacewidth;
    }
    else {
      /* here a character or composite character is to be constructed */
      strncpy( (char *)CurCharName, (char *)charnameP->data.stringP, charnameP->len);
      CurCharName[charnameP->len]='\0';
      
      /* search the CharString for this charname as key */
      basechar = SearchDictName(CharStringsDictP,charnameP);
      if (basechar<=0) {
       /* Check first, whether a char in question is a composite char */
       if ((i=isCompositeChar( FontID, CurCharName))>-1) {
         /* i is now the index of the composite char definitions
            (starting at 0). At this point it is clear that AFM-info
            must be present -> fetch first component of composite char. */
         pAFMData=pFontBase->pFontArray[FontID].pAFMData;
         charnameP->len=strlen( pAFMData->ccd[i].pieces[0].pccName);
         charnameP->data.stringP=(unsigned char*)pAFMData->ccd[i].pieces[0].pccName;
         numPieces=pAFMData->ccd[i].numOfPieces;
         
         if ((basechar=SearchDictName(CharStringsDictP,charnameP))<=0) {
           /* this is bad, AFM-file and font file do not match. This 
              will most probably lead to errors or inconsistencies later.
              However, we substitute .notdef and inform the user via
              logfile and T1_errno. */
           sprintf( err_warn_msg_buf,
                   "Charstring \"%s\" needed to construct composite char \"%s\" not defined (FontID=%d)",
                   pAFMData->ccd[i].pieces[0].pccName,
                   pAFMData->ccd[i].ccName, FontID);
           T1_PrintLog( "fontfcnB():", err_warn_msg_buf, T1LOG_WARNING);
           T1_errno=T1ERR_COMPOSITE_CHAR;
         }
       }
      }
      
      if (basechar<=0) { /* This  means the requested char is unknown or the
                         base char of a composite is not found ->
                         we substitute .notdef */
       charnameP = &CodeName;
       charnameP->len = 7;
       charnameP->data.stringP = (unsigned char *) notdef;
       basechar = SearchDictName(CharStringsDictP,charnameP);
       localmode=FF_NOTDEF_SUBST;
       /* Font must be completely damaged if it doesn't define a .notdef */
       if (basechar<=0) {
         *mode=FF_PARSE_ERROR;
         return(NULL);
       }
      } /* if (basechar<=0) */
      /* basechar is now the index of the base character in the CharStrings
        dictionary */
      
      /* we provide the Type1Char() procedure with the name of the character
        to rasterize for debugging purposes */
      strncpy( (char *)CurCharName, (char *)charnameP->data.stringP, charnameP->len);
      CurCharName[charnameP->len]='\0';
      /* get CharString and character path */
      theStringP = &(CharStringsDictP[basechar].value);
      tmppath2 = (struct segment *) Type1Char(FontP,S,theStringP,SubrsArrayP,NULL,
                                         FontP->BluesP,mode,CurCharName,strokewidth);
      strcpy( BaseCharName, CurCharName);
      /* if Type1Char reports an error, clean up and return */
      if ( *mode == FF_PARSE_ERROR || *mode==FF_PATH_ERROR) {
       if (charpath!=NULL) {
         KillPath( charpath);
       }
       if (tmppath1!=NULL) {
         KillPath( tmppath1);
       }
       if (tmppath2!=NULL) {
         KillPath( tmppath2);
       }
       if (tmppath3!=NULL) {
         KillPath( tmppath3);
       }
       if (tmppath4!=NULL) {
         KillPath( tmppath4);
       }
       if (tmppath5!=NULL) {
         KillPath( tmppath5);
       }
       return(NULL);
      }
       
      /* Defer rastering to later, we first have to handle the composite
        symbols */
      for (j=1; j<numPieces; j++) {
       /* get composite symbol name */
       charnameP->len=strlen( pAFMData->ccd[i].pieces[j].pccName);
       charnameP->data.stringP=(unsigned char*)pAFMData->ccd[i].pieces[j].pccName;
       /* get CharString definition */
       if ((N=SearchDictName(CharStringsDictP,charnameP))<=0) {
         /* handling of errors, see comments above ... */
         sprintf( err_warn_msg_buf,
                 "Charstring \"%s\" needed to construct composite char \"%s\" not defined (FontID=%d)",
                 pAFMData->ccd[i].pieces[j].pccName,
                 pAFMData->ccd[i].ccName, FontID);
         T1_PrintLog( "fontfcnB():", err_warn_msg_buf, T1LOG_WARNING);
         charnameP = &CodeName;
         charnameP->len = 7;
         charnameP->data.stringP = (unsigned char *) notdef;
         N = SearchDictName(CharStringsDictP,charnameP);
         localmode=FF_NOTDEF_SUBST;
         /* an undefined .notdef is fatal -> clean up and return */
         if (N<=0) {
           *mode=FF_PARSE_ERROR;
           if (charpath!=NULL) {
             KillPath( charpath);
           }
           if (tmppath1!=NULL) {
             KillPath( tmppath1);
           }
           if (tmppath2!=NULL) {
             KillPath( tmppath2);
           }
           if (tmppath3!=NULL) {
             KillPath( tmppath3);
           }
           if (tmppath4!=NULL) {
             KillPath( tmppath4);
           }
           if (tmppath5!=NULL) {
             KillPath( tmppath5);
           }
           return(NULL);
         }
       }
       theStringP = &(CharStringsDictP[N].value);
       tmppath1=(struct segment *)ILoc(S,
                                   pAFMData->ccd[i].pieces[j].deltax,
                                   pAFMData->ccd[i].pieces[j].deltay);
    
       strncpy( (char *)CurCharName, (char *)charnameP->data.stringP, charnameP->len);
       CurCharName[charnameP->len]='\0';
       tmppath5=(struct segment *)Type1Char(FontP,S,theStringP,SubrsArrayP,NULL,
                                        FontP->BluesP,mode,CurCharName,strokewidth);
       /* return if Type1Char reports an error */
       if ( *mode == FF_PARSE_ERROR || *mode==FF_PATH_ERROR)
         return(NULL);
       /* get escapement of current symbol */
       currdisp=getDisplacement( tmppath5);
       /* concat displacement and symbol path */
       tmppath5=(struct segment *)Join(tmppath1,tmppath5);
       /* for composite symbols we have to step back the char escapement.
          this is, in order to be able to use accents that cause a
          non zero displacement of the current point! We further have to
          step back the displacement from composite char data. */
       tmppath1=(struct segment *)t1_PathSegment( MOVETYPE, -currdisp.x, -currdisp.y);
       tmppath3=(struct segment *)ILoc(S,
                                   -pAFMData->ccd[i].pieces[j].deltax,
                                   -pAFMData->ccd[i].pieces[j].deltay);
       tmppath3=(struct segment *)Join(tmppath1,tmppath3);
       /* create path, or, respectively, append to existing path */
       if (tmppath4==NULL) {
         tmppath4=(struct segment *)Join(tmppath5,tmppath3);
       }
       else {
         tmppath5=(struct segment *)Join(tmppath5,tmppath3);
         tmppath4=(struct segment *)Join(tmppath4,tmppath5);
       }
      }
      
      /* concat composite symbols and base char. We use tmppath5 to store
        the path of the resulting (possibly composite) character. */
      if (tmppath4==NULL) { /* no previous composite symbols */
       tmppath5=tmppath2; /* a simple char */
      }
      else { 
       tmppath5=(struct segment *)Join(tmppath4,tmppath2);
      }
      

      /* Accumulate displacement, but be careful: In case of composite
        characters, we have to take the escapement of the base char only
        into account, because accents do not cause spacing. The path is
        constructed in a way that this automatically matches.
      */
      if (numPieces>1) { /* composite character */
       acc_width +=pFontBase->pFontArray[FontID].pAFMData->ccd[-(pFontBase->pFontArray[FontID].pEncMap[string[k]]+1)].wx;
      }
      else { /* ordinary character */
       acc_width +=pFontBase->pFontArray[FontID].pAFMData->cmi[pFontBase->pFontArray[FontID].pEncMap[string[k]]-1].wx;
      }
      
    } /* else (if (char==space) */

    /* character path is now stored in tmppath5. It may be a composite character.
       Insert kerning amount, if it is not the last character of the string. */
    if (k<no_chars-1){
      tmppath2=(struct segment *)ILoc(S,kern_pairs[k],0); 
      tmppath5=(struct segment *)Join(tmppath5,tmppath2);
      acc_width += kern_pairs[k];
    }
    if (charpath!=NULL){
      charpath=(struct segment *)Join(charpath,tmppath5);
    }
    else{
      charpath=(struct segment *)tmppath5;
    }
    /* reset the temporary paths so that constructing composite
       characters wiil continue to work properly in the next interation. */
    tmppath1=NULL;
    tmppath2=NULL;
    tmppath3=NULL;
    tmppath4=NULL;
    tmppath5=NULL;
    /* reset composition parameters */
    i=-1;
    numPieces=1;
    
  } /* for (k<no_chars) */
  
  
  /* Take care for underlining and such */
  if (modflag & T1_UNDERLINE){
    tmppath2=(struct segment *)Type1Line(FontP,S,
                                    pFontBase->pFontArray[FontID].UndrLnPos,
                                    pFontBase->pFontArray[FontID].UndrLnThick,
                                    (float) acc_width,strokewidth);
    charpath=(struct segment *)Join(charpath,tmppath2);
  }
  if (modflag & T1_OVERLINE){
    tmppath2=(struct segment *)Type1Line(FontP,S,
                                    pFontBase->pFontArray[FontID].OvrLnPos,
                                    pFontBase->pFontArray[FontID].OvrLnThick,
                                    (float) acc_width,strokewidth);
    charpath=(struct segment *)Join(charpath,tmppath2);
  }
  if (modflag & T1_OVERSTRIKE){
    tmppath2=(struct segment *)Type1Line(FontP,S,
                                    pFontBase->pFontArray[FontID].OvrStrkPos,
                                    pFontBase->pFontArray[FontID].OvrStrkThick,
                                    (float) acc_width,strokewidth);
    charpath=(struct segment *)Join(charpath,tmppath2);
  }
  
  /*
  printf("charpath->type: %x\n",charpath->type);
  printf("path1->type: %x\n",path1->type);
  printf("path2->type: %x\n",path2->type);
  */

  /* if Type1Char reported an error, then return */

  if ( *mode == FF_PARSE_ERROR)  return(NULL);
  if ( *mode == FF_PATH_ERROR)  return(NULL);
  if (do_raster) { 
    /* fill with winding rule unless path was requested */
    if (*mode != FF_PATH) {
      charpath = (struct segment *) Interior((path) charpath,WINDINGRULE+CONTINUITY);
    }
  }
  
  if (*mode==0)
    *mode=localmode;

  return((path)charpath);
}

Here is the call graph for this function:

struct region* fontfcnRect ( float  width,
float  height,
struct XYspace S,
int mode,
int  do_raster,
float  strokewidth 
) [read]

Definition at line 1146 of file fontfcn.c.

{
  struct segment *charpath = NULL;   /* the path for this character (rectangle)  */           
  
  charpath = (struct segment *) Type1Line( NULL, S,
                                      0.5f * height,    /* position */
                                      height,           /* thickness */
                                      -width,            /* width */
                                      strokewidth       /* strokewidth */
                                      );
  
  if (do_raster) { 
    /* fill with winding rule unless path was requested */
    if (*mode != FF_PATH) {
      charpath =  (struct segment *)Interior(charpath,WINDINGRULE+CONTINUITY);
    }
  }

  return((xobject) charpath);
  
}

Here is the call graph for this function:

Here is the caller graph for this function:

GLYPH* T1_ConcatGlyphs ( GLYPH glyph1,
GLYPH glyph2,
int  x_off,
int  y_off,
int  modflag 
)

Definition at line 1587 of file t1set.c.

{

  int lsb1, lsb2, rsb1, rsb2;
  int advanceX1, advanceX2, advanceY1, advanceY2;
  int ascent1, ascent2, descent1, descent2;
  int rsb, lsb, ascent, descent, advanceX, advanceY;
  int vanchor, w, h, wscanline, wscanline1, wscanline2, bpp;
  int memsize, BitShift;
  GLYPH *glyph1, *glyph2;
  unsigned T1_AA_TYPE16 BitBuf_c;
  unsigned T1_AA_TYPE32 BitBuf_s;
  unsigned long BitBuf_l;   /* This is only actually used if sizeof long = 8 */
  int i, j, k;
  int ByteOffset;
  
  unsigned char *Target_c, *p_c;
  unsigned T1_AA_TYPE16 *Target_s, *p_s;
  unsigned T1_AA_TYPE32 *Target_l, *p_l;
  
  static GLYPH glyph={NULL,{0,0,0,0,0,0},NULL,1};
  

  /* We handle the Right-To-Left concatenation the simple way:
     1) Change the order of the two glyphs
     2) Invert the sign of the y-part of the offset
     3) Recalculate the dimensions of the resulating glyph.
  */
  /* Check for writing direction and reorganize appropriately: */
  if (modflag & T1_RIGHT_TO_LEFT){
    glyph1=glyph_2;
    glyph2=glyph_1;
    y_off=-y_off;
  }
  else {
    glyph1=glyph_1;
    glyph2=glyph_2;
  }
  
  if (glyph1==NULL){
    T1_errno=T1ERR_INVALID_PARAMETER;
    return( NULL);
  }
  if (glyph2==NULL){
    T1_errno=T1ERR_INVALID_PARAMETER;
    return( NULL);
  }
  if (glyph1->bpp != glyph2->bpp){
    T1_errno=T1ERR_INVALID_PARAMETER;
    return( NULL);
  }
  
  /* We have two glyph different from NULL */
  /* Reset glyph, if necessary */
  if (glyph.bits!=NULL){
    free(glyph.bits);
    glyph.bits=NULL;
  }
  glyph.metrics.leftSideBearing=0;
  glyph.metrics.rightSideBearing=0;
  glyph.metrics.advanceX=0;
  glyph.metrics.advanceY=0;
  glyph.metrics.ascent=0;
  glyph.metrics.descent=0;
  glyph.pFontCacheInfo=NULL;
  glyph.bpp=1;

  /* Assign dimens */
  lsb1=glyph1->metrics.leftSideBearing;
  rsb1=glyph1->metrics.rightSideBearing;
  ascent1=glyph1->metrics.ascent;
  descent1=glyph1->metrics.descent;
  advanceX1=glyph1->metrics.advanceX + x_off;
  advanceY1=glyph1->metrics.advanceY + y_off;
  
  lsb2=glyph2->metrics.leftSideBearing;
  rsb2=glyph2->metrics.rightSideBearing;
  ascent2=glyph2->metrics.ascent;
  descent2=glyph2->metrics.descent;
  advanceX2=glyph2->metrics.advanceX;
  advanceY2=glyph2->metrics.advanceY;
  
  lsb=lsb1 < lsb2+advanceX1 ? lsb1 : lsb2+advanceX1;
  rsb=rsb1 > rsb2+advanceX1 ? rsb1 : rsb2+advanceX1;
  ascent=ascent1 > ascent2+advanceY1 ? ascent1 : ascent2+advanceY1;
  descent=descent1 < descent2+advanceY1 ? descent1 : descent2+advanceY1;
  advanceX=advanceX1+advanceX2;
  advanceY=advanceY1+advanceY2;

  bpp=glyph1->bpp;
  w=rsb-lsb;
  h=ascent-descent;
  wscanline=PAD( w*bpp, T1_pad) / 8;
  wscanline1=PAD( (rsb1-lsb1)*bpp, T1_pad) / 8;
  wscanline2=PAD( (rsb2-lsb2)*bpp, T1_pad) / 8;
  memsize=wscanline*h;
  if ((glyph.bits=(char *)calloc( memsize + 1, sizeof(unsigned char)))==NULL){
    T1_errno=T1ERR_ALLOC_MEM;
    return(NULL);
  }
  
  if (bpp==1){
    if (T1_pad==32 && T1_byte==0 && sizeof(long)==8){
      /* The following loop steps through the lines of the first glyph: */
      vanchor=ascent-ascent1;
      BitShift=(lsb1-lsb) % 32;
      ByteOffset=(lsb1-lsb)/32*4;
      for ( i=0; i<ascent1-descent1; i++){
       Target_l= (unsigned T1_AA_TYPE32 *)(glyph.bits +((vanchor+i)*wscanline)
                                       +ByteOffset);
       p_l = (unsigned T1_AA_TYPE32 *)(glyph1->bits+(wscanline1*i));
       if (BitShift == 0){
         for (k=wscanline1/4; k; k--)
           *Target_l++ |= *p_l++;
       }
       else{
         for (k=wscanline1/4; k; k--){
           BitBuf_l = ((long)*p_l++) << BitShift;
           *Target_l++ |= BitBuf_l;
           *Target_l |= BitBuf_l>>l_shift;
         }
       }
      }
      /* The following loop steps through the lines of the second glyph: */
      vanchor=ascent-(ascent2+advanceY1);
      BitShift=(lsb2+advanceX1-lsb) % 32;
      ByteOffset=(lsb2+advanceX1-lsb)/32*4;
      for ( i=0; i<ascent2-descent2; i++){
       Target_l= (unsigned T1_AA_TYPE32 *)(glyph.bits +((vanchor+i)*wscanline)
                                       +ByteOffset);
       p_l = (unsigned T1_AA_TYPE32 *)(glyph2->bits+(wscanline2*i));
       if (BitShift == 0){
         for (k=wscanline2/4; k; k--)
           *Target_l++ |= *p_l++;
       }
       else{
         for (k=wscanline2/4; k; k--){
           BitBuf_l = ((long)*p_l++) << BitShift;
           *Target_l++ |= BitBuf_l;
           *Target_l |= BitBuf_l>>l_shift;
         } 
       } 
      }
    }
    else if(T1_pad==16 && T1_byte==0){
      /* The following loop steps through the lines of the first glyph: */
      vanchor=ascent-ascent1;
      BitShift=(lsb1-lsb) % 16;
      ByteOffset=(lsb1-lsb)/16*2;
      for ( i=0; i<ascent1-descent1; i++){
       Target_s= (unsigned T1_AA_TYPE16 *)(glyph.bits +((vanchor+i)*wscanline)
                                       +ByteOffset);
       p_s = (unsigned T1_AA_TYPE16 *)(glyph1->bits+(wscanline1*i));
       if (BitShift == 0){
         for (k=wscanline1/2; k; k--)
           *Target_s++ |= *p_s++;
       }
       else{
         for (k=wscanline1/2; k; k--){
           BitBuf_s = ((T1_AA_TYPE32)*p_s++) << BitShift;
           *Target_s++ |= BitBuf_s;
           *Target_s |= BitBuf_s>>s_shift;
         }
       }
      }
      /* The following loop steps through the lines of the second glyph: */
      vanchor=ascent-(ascent2+advanceY1);
      BitShift=(lsb2+advanceX1-lsb) % 16;
      ByteOffset=(lsb2+advanceX1-lsb)/16*2;
      for ( i=0; i<ascent2-descent2; i++){
       Target_s= (unsigned T1_AA_TYPE16 *)(glyph.bits +((vanchor+i)*wscanline)
                                       +ByteOffset);
       p_s = (unsigned T1_AA_TYPE16 *)(glyph2->bits+(wscanline2*i));
       if (BitShift == 0){
         for (k=wscanline2/2; k; k--)
           *Target_s++ |= *p_s++;
       }
       else{
         for (k=wscanline2/2; k; k--){
           BitBuf_s = ((T1_AA_TYPE32)*p_s++) << BitShift;
           *Target_s++ |= BitBuf_s;
           *Target_s |= BitBuf_s>>s_shift;
         } 
       } 
      }
    }
    else{ /* T1_pad==8 or Big Endian machine */
      /* The following loop steps through the lines of the first glyph: */
      vanchor=ascent-ascent1;
      BitShift=(lsb1-lsb) % 8;
      ByteOffset=(lsb1-lsb) / 8;
      for ( i=0; i<ascent1-descent1; i++){
       Target_c= (unsigned char *)(glyph.bits +((vanchor+i)*wscanline)
                                +ByteOffset);
       p_c = (unsigned char *)(glyph1->bits+(wscanline1*i));
       if (BitShift == 0){
         for (k=wscanline1; k; k--)
           *Target_c++ |= *p_c++;
       }
       else{
         for (k=wscanline1; k; k--){
           BitBuf_c = ((T1_AA_TYPE16)*p_c++) << BitShift;
           *Target_c++ |= BitBuf_c;
           *Target_c |= BitBuf_c>>c_shift;
         }
       }
      }
      /* The following loop steps through the lines of the second glyph: */
      vanchor=ascent-(ascent2+advanceY1);
      BitShift=(lsb2+advanceX1-lsb) % 8;
      ByteOffset=(lsb2+advanceX1-lsb) / 8;
      for ( i=0; i<ascent2-descent2; i++){
       Target_c= (unsigned char *)(glyph.bits +((vanchor+i)*wscanline)
                                +ByteOffset);
       p_c = (unsigned char *)(glyph2->bits+(wscanline2*i));
       if (BitShift == 0){
         for (k=wscanline2; k; k--)
           *Target_c++ |= *p_c++;
       }
       else{
         for (k=wscanline2; k; k--){
           BitBuf_c = ((T1_AA_TYPE16)*p_c++) << BitShift;
           *Target_c++ |= BitBuf_c;
           *Target_c |= BitBuf_c>>c_shift;
         } 
       } 
      }
    }
  } /* end of if (bpp==1) ... */
  else if (bpp==8){
    /* Set background */
    for ( i=0; i<memsize; i++)
      ((char *)glyph.bits)[i]=(char) T1aa_bg;
    /* The following loop steps through the lines of the first glyph: */
    vanchor=ascent-ascent1;
    for ( i=0; i<ascent1-descent1; i++){
      Target_c= (unsigned char *)(glyph.bits +((vanchor+i)*wscanline)
                              +(lsb1-lsb));
      p_c = (unsigned char *)(glyph1->bits+(wscanline1*i));
      memcpy( Target_c, p_c, (rsb1-lsb1));
    }
    /* The following loop steps through the lines of the second glyph.
       Note that we only set the pixel if it is not background! */
    vanchor=ascent-(ascent2+advanceY1);
    for ( i=0; i<ascent2-descent2; i++){
      Target_c= (unsigned char *)(glyph.bits +((vanchor+i)*wscanline)
                              +(lsb2+advanceX1-lsb));
      p_c = (unsigned char *)(glyph2->bits+(wscanline2*i));
      for (j=0; j<(rsb2-lsb2); j++)
       if (p_c[j] != (unsigned char) T1aa_bg)
         Target_c[j]=p_c[j];
    }
  } /* end of if (bpp==8) ... */
  else if (bpp==16){
    /* Set background */
    for ( i=0; i<memsize/2; i++)
      ((T1_AA_TYPE16 *)glyph.bits)[i]=(T1_AA_TYPE16) T1aa_bg;
    /* The following loop steps through the lines of the first glyph: */
    vanchor=ascent-ascent1;
    for ( i=0; i<ascent1-descent1; i++){
      Target_s= (unsigned T1_AA_TYPE16 *)(glyph.bits +((vanchor+i)*wscanline)
                              +(lsb1-lsb)*2);
      p_s = (unsigned T1_AA_TYPE16 *)(glyph1->bits+(wscanline1*i));
      memcpy( Target_s, p_s, (rsb1-lsb1)*2);
    }
    /* The following loop steps through the lines of the second glyph.
       Note that we only set the pixel if it is not background! */
    vanchor=ascent-(ascent2+advanceY1);
    for ( i=0; i<ascent2-descent2; i++){
      Target_s= (unsigned T1_AA_TYPE16 *)(glyph.bits +((vanchor+i)*wscanline)
                              +(lsb2+advanceX1-lsb)*2);
      p_s = (unsigned T1_AA_TYPE16 *)(glyph2->bits+(wscanline2*i));
      for (j=0; j<(rsb2-lsb2); j++)
       if (p_s[j] != (unsigned T1_AA_TYPE16) T1aa_bg)
         Target_s[j]=p_s[j];
    }
  } /* end of if (bpp==16) ... */
  else if (bpp==32){
    /* Set background */
    for ( i=0; i<memsize/4; i++)
      ((T1_AA_TYPE32 *)glyph.bits)[i]=(T1_AA_TYPE32) T1aa_bg;
    /* The following loop steps through the lines of the first glyph: */
    vanchor=ascent-ascent1;
    for ( i=0; i<ascent1-descent1; i++){
      Target_l= (unsigned T1_AA_TYPE32 *)(glyph.bits +((vanchor+i)*wscanline)
                              +(lsb1-lsb)*4);
      p_l = (unsigned T1_AA_TYPE32 *)(glyph1->bits+(wscanline1*i));
      memcpy( Target_l, p_l, (rsb1-lsb1)*4);
    }
    /* The following loop steps through the lines of the second glyph.
       Note that we only set the pixel if it is not background! */
    vanchor=ascent-(ascent2+advanceY1);
    for ( i=0; i<ascent2-descent2; i++){
      Target_l= (unsigned T1_AA_TYPE32 *)(glyph.bits +((vanchor+i)*wscanline)
                              +(lsb2+advanceX1-lsb)*4);
      p_l = (unsigned T1_AA_TYPE32 *)(glyph2->bits+(wscanline2*i));
      for (j=0; j<(rsb2-lsb2); j++)
       if (p_l[j] != (unsigned T1_AA_TYPE32) T1aa_bg)
         Target_l[j]=p_l[j];
    }
  } /* end of if (bpp==32) ... */
  
  
  /* Check for writing direction and re-compute dimens appropriately: */
  if (modflag & T1_RIGHT_TO_LEFT){
    advanceX=-advanceX1-advanceX2;
    advanceY=-advanceY1-advanceY2;
    lsb=lsb1 < lsb2+advanceX1 ? advanceX+lsb1 : advanceX+lsb2+advanceX1;
    rsb=rsb1 > rsb2+advanceX1 ? advanceX+rsb1 : advanceX+rsb2+advanceX1;
    ascent=ascent1 > ascent2+advanceY1 ? ascent1 : ascent2+advanceY1;
    descent=descent1 < descent2+advanceY1 ? descent1 : descent2+advanceY1;
    ascent += advanceY;
    descent += advanceY;
  } 
  
  glyph.metrics.leftSideBearing=lsb;
  glyph.metrics.rightSideBearing=rsb;
  glyph.metrics.advanceX=advanceX;
  glyph.metrics.advanceY=advanceY;
  glyph.metrics.ascent=ascent;
  glyph.metrics.descent=descent;
  glyph.bpp=bpp;
  
  /*
  printf("lsb=%d, rsb=%d, adX=%d, adY=%d asc=%d, desc=%d\n",
        glyph.metrics.leftSideBearing,
        glyph.metrics.rightSideBearing,
        glyph.metrics.advanceX,
        glyph.metrics.advanceY,
        glyph.metrics.ascent,
        glyph.metrics.descent );
        */
  
  return( &glyph);
  
}

Here is the call graph for this function:

GLYPH* T1_CopyGlyph ( GLYPH glyph)

Definition at line 1455 of file t1set.c.

{
  GLYPH *dest;
  long size;
  

  if (glyph==NULL){
    T1_errno=T1ERR_INVALID_PARAMETER;
    return(NULL);
  }
  
  /* Assign padding value */
  T1_pad=pFontBase->bitmap_pad;
  /* Allocate memory for struct: */
  if ((dest=(GLYPH *)malloc(sizeof(GLYPH)))==NULL){
    T1_errno=T1ERR_ALLOC_MEM;
    return(NULL);
  }
  
  /* Copy the structure members: */
  *dest=*glyph;
  /* Allocate memory for bitmap, initialize pointer to it and copy bitmap: */
  size=PAD((dest->metrics.rightSideBearing-dest->metrics.leftSideBearing)*
          glyph->bpp, T1_pad) / 8;
  size=size*(dest->metrics.ascent-dest->metrics.descent);
   /* We must check whether there's actually a bits-pointer different from
      NULL. If not omit the following step: */
  if (glyph->bits!=NULL){
    if ((dest->bits=(char *)malloc(size*sizeof(char)))==NULL){
      free(dest);
      T1_errno=T1ERR_ALLOC_MEM;
      return(NULL);
    }
    memcpy(dest->bits,glyph->bits,size);
  }
  return(dest);
}

Here is the call graph for this function:

void T1_DumpGlyph ( GLYPH glyph)

Definition at line 1494 of file t1set.c.

{
  int i,j,h,w;   /* i=line-index, j=column-index */ 
  long paddedW;
  
  
  printf("Dataformat: T1_bit=%d, T1_byte=%d, T1_wordsize=%d, T1_pad=%d\n",
        T1_bit, T1_byte, T1_pad, T1_pad);

  if (glyph==NULL){
    return;
  }
  
  h=glyph->metrics.ascent-glyph->metrics.descent;
  w=glyph->metrics.rightSideBearing-glyph->metrics.leftSideBearing;
  
  paddedW=PAD(w,T1_pad);
  
  printf("GlyphInfo: h=%d, w=%d, paddedW=%ld\n", h, w, paddedW);
  
  for ( i=0; i<h; i++){
    if (T1_pad==8)
      for (j=0; j<paddedW/T1_pad; j++)
       bin_dump_c(glyph->bits[i*paddedW/T1_pad+j], 1);
    else if (T1_pad==16)
      for (j=0; j<paddedW/T1_pad; j++){
       bin_dump_s(((unsigned short *)glyph->bits)[i*paddedW/T1_pad+j], 1);
      }
    else
      for (j=0; j<paddedW/T1_pad; j++){
       bin_dump_l(((unsigned long *)glyph->bits)[i*paddedW/T1_pad+j], 1);
      }
    printf("\n");
  } 
} 

Here is the call graph for this function:

GLYPH* T1_FillOutline ( T1_OUTLINE path,
int  modflag 
)

Definition at line 1928 of file t1set.c.

{
  struct region *area=NULL;

  static GLYPH glyph={NULL,{0,0,0,0,0,0},NULL,1};
  volatile int memsize=0;
  int i;
  LONG h,w;
  LONG paddedW;

  
  /* We return to this if something goes wrong deep in the rasterizer */
  if ((i=setjmp( stck_state))!=0) {
    T1_errno=T1ERR_TYPE1_ABORT;
    sprintf( err_warn_msg_buf, "t1_abort: Reason: %s",
            t1_get_abort_message( i));
    T1_PrintLog( "T1_FillOutline()", err_warn_msg_buf,
              T1LOG_ERROR);
    return( NULL);
  }

  /* Reset character glyph, if necessary */
  if (glyph.bits!=NULL){
    free(glyph.bits);
    glyph.bits=NULL;
  }
  glyph.metrics.leftSideBearing=0;
  glyph.metrics.rightSideBearing=0;
  glyph.metrics.advanceX=0;
  glyph.metrics.advanceY=0;
  glyph.metrics.ascent=0;
  glyph.metrics.descent=0;
  glyph.pFontCacheInfo=NULL;
  glyph.bpp=1;  
  
  
  /* Assign padding value */
  T1_pad=pFontBase->bitmap_pad;
  if (pFontBase->endian)
    T1_byte=1;
  else
    T1_byte=0;
  T1_wordsize=T1_pad;

  /* Create a region from outline */
  area=(struct region *)Interior( (struct segment *)path,
                              WINDINGRULE+CONTINUITY);

  /* fill the glyph-structure */
  if (area == NULL){
    T1_PrintLog( "T1_FillOutline()", "area=NULL returned by Interior()", T1LOG_WARNING);
    T1_errno=1000;
    return(NULL);
  }
  h = area->ymax - area->ymin;
  w = area->xmax - area->xmin;

  
  paddedW = PAD(w, T1_pad);
  if ( (area->xmin > area->xmax) || (area->ymin > area->ymax) ){
    /* There was a character like .notdef or space, that didn't
       produce any black pixels on the bitmap! -> we return a glyph with
       correct metrics and bitmap pointer set to NULL */
    sprintf( err_warn_msg_buf,
            "No black pixels in outline %p", path);
    T1_PrintLog( "T1_FillOutline()", err_warn_msg_buf, T1LOG_WARNING);
    
    glyph.metrics.leftSideBearing  = 0;
    glyph.metrics.advanceX   = NEARESTPEL(area->ending.x - area->origin.x);
    glyph.metrics.advanceY   = - NEARESTPEL(area->ending.y - area->origin.y);
    glyph.metrics.rightSideBearing = 0;
    glyph.metrics.descent          = 0;
    glyph.metrics.ascent           = 0;
    /* make sure to get rid of 'area' before leaving! */
    KillRegion (area);
    return( &glyph);
  }
  if (h > 0 && w > 0) {
    memsize = h * paddedW / 8 + 1;
    /* This is for the users copy of the character, for security-reasons
       the original pointer to the cache area is not used. The entry glyph.bits
       is free'ed every time this function is called: */
    glyph.bits = (char *)malloc(memsize*sizeof( char));
    if (glyph.bits == NULL){
      T1_errno=T1ERR_ALLOC_MEM;
      /* make sure to get rid of area if it's there */
      if (area){
       KillRegion (area);
      }
      return(NULL);
    }
    
  }
  else {
    h = w = 0;
    area->xmin = area->xmax = 0;
    area->ymin = area->ymax = 0;
  }
  
  glyph.metrics.leftSideBearing  = area->xmin;
  glyph.metrics.advanceX   = NEARESTPEL(area->ending.x - area->origin.x);
  glyph.metrics.advanceY   = - NEARESTPEL(area->ending.y - area->origin.y);
  glyph.metrics.rightSideBearing = area->xmax;
  glyph.metrics.descent          = - area->ymax;
  glyph.metrics.ascent           = - area->ymin;
  
  
  if (h > 0 && w > 0) {
    (void) memset(glyph.bits, 0, memsize);
    fill(glyph.bits, h, paddedW, area, T1_byte, T1_bit, T1_wordsize );
  }

  /* Check for writing direction and re-compute dimensions appropriately: */
  if (modflag & T1_RIGHT_TO_LEFT){
    glyph.metrics.advanceX *= -1;
    glyph.metrics.advanceY *= -1;
    glyph.metrics.leftSideBearing += glyph.metrics.advanceX;
    glyph.metrics.rightSideBearing += glyph.metrics.advanceX;
    glyph.metrics.descent += glyph.metrics.advanceY;
    glyph.metrics.ascent += glyph.metrics.advanceY;
  } 
  
  /* make sure to get rid of area if it's there */
  if (area){
    KillRegion (area);
  }
  return( &glyph);
  
  
}

Here is the call graph for this function:

GLYPH* T1_SetChar ( int  FontID,
char  charcode,
float  size,
T1_TMATRIX transform 
)

Definition at line 193 of file t1set.c.

{
  int i;
  int mode;
  struct region *area;
  struct XYspace *Current_S;
  int cache_flag    = 1;
  int rot_flag      = 0;
  unsigned char ucharcode;
  float strokewidth = 0.0f;
  volatile int strokeextraflag = 0;
  
  
  FONTSIZEDEPS *font_ptr;
  FONTPRIVATE  *fontarrayP;
  
  volatile int memsize=0;
  LONG h,w;
  LONG paddedW;

  /* We don't implement underlining for characters, but the rasterer
     implements it. Thus, we use a modflag of constant 0 */
  int modflag=0;

  static GLYPH glyph={NULL,{0,0,0,0,0,0},NULL,1};


  /* We return to this if something goes wrong deep in the rasterizer */
  if ((i=setjmp( stck_state))!=0) {
    T1_errno=T1ERR_TYPE1_ABORT;
    sprintf( err_warn_msg_buf, "t1_abort: Reason: %s",
            t1_get_abort_message( i));
    T1_PrintLog( "T1_SetChar()", err_warn_msg_buf,
              T1LOG_ERROR);
    return( NULL);
  }

  ucharcode=(unsigned char)charcode;

  
  /* Reset character glyph, if necessary */
  if (glyph.bits!=NULL){
    free(glyph.bits);
    glyph.bits=NULL;
  }
  glyph.metrics.leftSideBearing=0;
  glyph.metrics.rightSideBearing=0;
  glyph.metrics.advanceX=0;
  glyph.metrics.advanceY=0;
  glyph.metrics.ascent=0;
  glyph.metrics.descent=0;
  glyph.pFontCacheInfo=NULL;
  glyph.bpp=1;  
  
  /* First, check for a correct ID */
  i=T1_CheckForFontID(FontID);
  if (i==-1){
    T1_errno=T1ERR_INVALID_FONTID;
    return(NULL);
  }
  /* if necessary load font into memory */
  if (i==0)
    if (T1_LoadFont(FontID))
      return(NULL);

  /* Check for valid size */
  if (size<=0.0){
    T1_errno=T1ERR_INVALID_PARAMETER;
    return(NULL);
  }

  /* Assign padding value */
  T1_pad=pFontBase->bitmap_pad;
  if (pFontBase->endian)
    T1_byte=1;
  else
    T1_byte=0;
  T1_wordsize=T1_pad;

  fontarrayP=&(pFontBase->pFontArray[FontID]);
  
  /* Check if rotation is requested */
  if (transform!=NULL){
    /* there's rotation requested => do not cache the resulting bitmap */
    rot_flag=1;
    cache_flag=0;
  }
  else {
    rot_flag=0;
    cache_flag=1;
  }
  
  /* handle stroking stuff */
  if ( pFontBase->pFontArray[FontID].info_flags & RASTER_STROKED) {
    /* Stroking requested. If caching is not desired, clear cache_flag.
       Otherwise, leave it unaffected. */
    if ( (pFontBase->pFontArray[FontID].info_flags & CACHE_STROKED) == 0 ) {
      /* filled glyphs are cached, indicate that character is to be rendered
        on the fly and not to be cached */
      strokeextraflag = 1;
      cache_flag = 0;
    }
    strokewidth = pFontBase->pFontArray[FontID].StrokeWidth;
  }
  else {
    /* filling requested. */
    if ( (pFontBase->pFontArray[FontID].info_flags & CACHE_STROKED) != 0 ) {
      /* stroked glyphs are cached, indicate that character is to be rendered
        on the fly and not to be cached */
      strokeextraflag = 1;
      cache_flag = 0;
    }
    strokewidth = 0.0f;
  }
  
  /* font is now loaded into memory =>
     Check for size: */
  if ((font_ptr=T1int_QueryFontSize( FontID, size, NO_ANTIALIAS))==NULL){
    font_ptr=T1int_CreateNewFontSize( FontID, size, NO_ANTIALIAS);
    if (font_ptr==NULL){
      T1_errno=T1ERR_ALLOC_MEM;
      return(NULL);
    }
  }
  else {/* size is already existent in cache */
    /* If no rotation and no noncached stroking , try to get character from cache */
    if ( (rot_flag==0) && (strokeextraflag==0) ) {
      /* we don't use the .bits entry to check because in newer releases
        also white glyphs (bits=NULL) are allowed. Rather, we check
        whether bpp > 0! */
      if (font_ptr->pFontCache[ucharcode].bpp > 0){
       /* Character is already in Chache -> create a copy of cache
          and return a pointer to the result: */
       memcpy( &glyph, &(font_ptr->pFontCache[ucharcode]), sizeof(GLYPH));
       paddedW = PAD((glyph.metrics.rightSideBearing-glyph.metrics.leftSideBearing),
                    T1_pad);
       if (font_ptr->pFontCache[ucharcode].bits!=NULL) {
         memsize = (glyph.metrics.ascent-glyph.metrics.descent)*paddedW / 8;
         glyph.bits = (char *)malloc(memsize*sizeof( char));
         if (glyph.bits == NULL){
           T1_errno=T1ERR_ALLOC_MEM;
           return(NULL);
         }
         memcpy( glyph.bits, font_ptr->pFontCache[ucharcode].bits, memsize);
       }
       return(&(glyph));
      }
    }
  }
  /* Setup an appropriate charspace matrix. Note that the rasterizer
     assumes vertical values with inverted sign! Transformation should
     create a copy of the local charspace matrix which then still has
     to be made permanent. */
  if (rot_flag){
    Current_S=(struct XYspace *) 
      Permanent(Scale(Transform (font_ptr->pCharSpaceLocal,
                             transform->cxx, - transform->cxy,
                             transform->cyx, - transform->cyy),
                    DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
  }
  else{
    Current_S=(struct XYspace *)
      Permanent(Scale(Transform(font_ptr->pCharSpaceLocal,
                            1.0, 0.0, 0.0, -1.0),
                    DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
  }
  
  /* fnt_ptr now points to the correct FontSizeDeps-struct =>
     lets now raster the character */
  mode=0;
  area=fontfcnB( FontID, modflag, Current_S,
               fontarrayP->pFontEnc,
               ucharcode, &mode,
               fontarrayP->pType1Data,
               DO_RASTER,
               strokewidth);
  KillSpace (Current_S);

  /* fill the glyph-structure */
  if (mode > 0) {
    sprintf( err_warn_msg_buf, "fontfcnB() set mode=%d", mode);
    T1_PrintLog( "T1_SetChar()", err_warn_msg_buf, T1LOG_WARNING);
    T1_errno=mode;
    return(NULL);
  }
  if (area == NULL){
    T1_PrintLog( "T1_SetChar()", "area=NULL returned by fontfcnB()", T1LOG_WARNING);
    T1_errno=mode;
    return(NULL);
  }
  h = area->ymax - area->ymin;
  w = area->xmax - area->xmin;

  if (mode == FF_NOTDEF_SUBST) {
    sprintf( err_warn_msg_buf,
            "\".notdef\" substituted for character %d from font %d",
            ucharcode, FontID);
    T1_PrintLog( "T1_SetChar()", err_warn_msg_buf, T1LOG_WARNING);
    mode=0;
  }
  
  paddedW = PAD(w, T1_pad);
  
  if (h > 0 && w > 0) {
    memsize = h * paddedW / 8 + 1;
    /* This is for the users copy of the character, for security-reasons
       the original pointer to the cache area is not used. The entry glyph.bits
       is free'ed every time this function is called: */
    glyph.bits = (char *)malloc(memsize*sizeof( char));
    if (glyph.bits == NULL){
      T1_errno=T1ERR_ALLOC_MEM;
      /* make sure to get rid of 'area' before leaving! */
      KillRegion (area);
      return(NULL);
    }
  }
  else {
    h = w = 0;
    area->xmin = area->xmax = 0;
    area->ymin = area->ymax = 0;
  }

  /* Assign metrics */
  glyph.metrics.leftSideBearing  = area->xmin;
  glyph.metrics.advanceX   = NEARESTPEL(area->ending.x - area->origin.x);
  glyph.metrics.advanceY   = - NEARESTPEL(area->ending.y - area->origin.y);
  glyph.metrics.rightSideBearing = area->xmax;
  glyph.metrics.descent          = - area->ymax;
  glyph.metrics.ascent           = - area->ymin;

  
  if (h > 0 && w > 0) {
    (void) memset(glyph.bits, 0, memsize);
    fill(glyph.bits, h, paddedW, area, T1_byte, T1_bit, T1_wordsize );
  }
  
  /* make sure to get rid of 'area' before leaving! */
  KillRegion (area);
  
  /* Cache glyph if requested, also if it contains only white space */
  if (cache_flag){
    /* Copy glyph to cache but be careful not to modify the pixmap
       entry */
    font_ptr->pFontCache[ucharcode].metrics.leftSideBearing=glyph.metrics.leftSideBearing;
    font_ptr->pFontCache[ucharcode].metrics.rightSideBearing=glyph.metrics.rightSideBearing;
    font_ptr->pFontCache[ucharcode].metrics.advanceX=glyph.metrics.advanceX;
    font_ptr->pFontCache[ucharcode].metrics.advanceY=glyph.metrics.advanceY;
    font_ptr->pFontCache[ucharcode].metrics.ascent=glyph.metrics.ascent;
    font_ptr->pFontCache[ucharcode].metrics.descent=glyph.metrics.descent;
    font_ptr->pFontCache[ucharcode].pFontCacheInfo=glyph.pFontCacheInfo;
    font_ptr->pFontCache[ucharcode].bpp=glyph.bpp;
    if (glyph.bits==NULL) {
      font_ptr->pFontCache[ucharcode].bits=NULL;
    }
    else {
      font_ptr->pFontCache[ucharcode].bits = (char *)malloc(memsize*sizeof( char));
      if (font_ptr->pFontCache[ucharcode].bits == NULL){
       T1_errno=T1ERR_ALLOC_MEM;
       return(NULL);
      }
      /* ... and copy bitmap to cache area: */
      memcpy( font_ptr->pFontCache[ucharcode].bits, glyph.bits, memsize);
    }
    
  }


  return(&glyph);
}

Here is the call graph for this function:

GLYPH* T1_SetRect ( int  FontID,
float  size,
float  width,
float  height,
T1_TMATRIX transform 
)

Definition at line 2062 of file t1set.c.

{
  int i;
  int mode;
  struct region *area;
  struct XYspace *Current_S;
  float strokewidth = 0.0f;
  
  FONTSIZEDEPS *font_ptr;
  FONTPRIVATE  *fontarrayP;
  
  volatile int memsize=0;
  LONG h,w;
  LONG paddedW;

  static GLYPH glyph={NULL,{0,0,0,0,0,0},NULL,1};


  /* We return to this if something goes wrong deep in the rasterizer */
  if ((i=setjmp( stck_state))!=0) {
    T1_errno=T1ERR_TYPE1_ABORT;
    sprintf( err_warn_msg_buf, "t1_abort: Reason: %s",
            t1_get_abort_message( i));
    T1_PrintLog( "T1_SetRect()", err_warn_msg_buf,
              T1LOG_ERROR);
    return( NULL);
  }

  font_ptr = NULL;
  
  /* Reset character glyph, if necessary */
  if (glyph.bits!=NULL){
    free(glyph.bits);
    glyph.bits=NULL;
  }
  glyph.metrics.leftSideBearing=0;
  glyph.metrics.rightSideBearing=0;
  glyph.metrics.advanceX=0;
  glyph.metrics.advanceY=0;
  glyph.metrics.ascent=0;
  glyph.metrics.descent=0;
  glyph.pFontCacheInfo=NULL;
  glyph.bpp=1;  
  
  /* First, check for a correct ID. */
  i=T1_CheckForFontID(FontID);
  if ( i == -1 ) {
    return NULL;
  }
  /* if necessary load font into memory */
  if ( i == 0 )
    if ( T1_LoadFont( FontID) )
      return NULL;

  /* Check for valid size */
  if (size<=0.0){
    T1_errno=T1ERR_INVALID_PARAMETER;
    return(NULL);
  }

  /* Assign padding value */
  T1_pad=pFontBase->bitmap_pad;
  if (pFontBase->endian)
    T1_byte=1;
  else
    T1_byte=0;
  T1_wordsize=T1_pad;

  if ( i > 0 ) {
    /* FontID identifies a valid font */
    fontarrayP = &(pFontBase->pFontArray[FontID]);
    
    /* Check for size and create it if necessary */
    if ((font_ptr=T1int_QueryFontSize( FontID, size, NO_ANTIALIAS))==NULL){
      font_ptr=T1int_CreateNewFontSize( FontID, size, NO_ANTIALIAS);
      if (font_ptr==NULL){
       T1_errno=T1ERR_ALLOC_MEM;
       return(NULL);
      }
    }
    
    /* handle stroking stuff */
    if ( fontarrayP->info_flags & RASTER_STROKED) {
      strokewidth = pFontBase->pFontArray[FontID].StrokeWidth;
    }
    else {
      strokewidth = 0.0f;
    }
  }
  else {
    fontarrayP = NULL;
    strokewidth = 0.0f;
  }
  
  
  /* Setup an appropriate charspace matrix. Note that the rasterizer
     assumes vertical values with inverted sign! Transformation should
     create a copy of the local charspace matrix which then still has
     to be made permanent. */
  if ( transform != NULL ) {
    Current_S = (struct XYspace *) 
      Permanent(Scale(Transform (font_ptr->pCharSpaceLocal,
                             transform->cxx, - transform->cxy,
                             transform->cyx, - transform->cyy),
                    DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
  }
  else{
    Current_S = (struct XYspace *)
      Permanent(Scale(Transform(font_ptr->pCharSpaceLocal,
                            1.0, 0.0, 0.0, -1.0),
                    DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
  }
  
  mode=0;
  area=fontfcnRect( width,
                  height,
                  Current_S,
                  &mode,
                  DO_RASTER,
                  strokewidth);
  KillSpace (Current_S);
  
  /* fill the glyph-structure */
  if ( mode > 0 ) {
    sprintf( err_warn_msg_buf, "fontfcnRect() set mode=%d", mode);
    T1_PrintLog( "T1_SetRect()", err_warn_msg_buf, T1LOG_WARNING);
    T1_errno=mode;
    return(NULL);
  }
  if ( area == NULL ) {
    T1_PrintLog( "T1_SetRect()", "area=NULL returned by fontfcnRect()", T1LOG_WARNING);
    T1_errno=mode;
    return(NULL);
  }
  h = area->ymax - area->ymin;
  w = area->xmax - area->xmin;

  paddedW = PAD(w, T1_pad);
  
  if (h > 0 && w > 0) {
    memsize = h * paddedW / 8 + 1;
    /* This is for the users copy of the character, for security-reasons
       the original pointer to the cache area is not used. The entry glyph.bits
       is free'ed every time this function is called: */
    glyph.bits = (char *)malloc(memsize*sizeof( char));
    if ( glyph.bits == NULL ) {
      T1_errno=T1ERR_ALLOC_MEM;
      /* make sure to get rid of 'area' before leaving! */
      KillRegion (area);
      return(NULL);
    }
  }
  else {
    h = w = 0;
    area->xmin = area->xmax = 0;
    area->ymin = area->ymax = 0;
  }

  /* Assign metrics */
  glyph.metrics.leftSideBearing  = area->xmin;
  glyph.metrics.advanceX   = NEARESTPEL(area->ending.x - area->origin.x);
  glyph.metrics.advanceY   = - NEARESTPEL(area->ending.y - area->origin.y);
  glyph.metrics.rightSideBearing = area->xmax;
  glyph.metrics.descent          = - area->ymax;
  glyph.metrics.ascent           = - area->ymin;

  
  if (h > 0 && w > 0) {
    (void) memset(glyph.bits, 0, memsize);
    fill(glyph.bits, h, paddedW, area, T1_byte, T1_bit, T1_wordsize );
  }
  
  /* make sure to get rid of 'area' before leaving! */
  KillRegion (area);
  
  return(&glyph);
}

Here is the call graph for this function:

GLYPH* T1_SetString ( int  FontID,
char *  string,
volatile int  len,
long  spaceoff,
int  modflag,
float  size,
T1_TMATRIX transform 
)

Definition at line 467 of file t1set.c.

{
  volatile int i, j=0, k;
  int mode;
  /* initialize this to NULL just to be on the safe side */
  struct region *area = NULL;
  struct XYspace *Current_S, *S;
  int cache_flag=1;
  volatile int rot_flag=0;
  int *kern_pairs;       /* use for accessing the kern pairs if kerning is
                         requested */
  int no_chars=0;        /* The number of characters in the string */
  static int lastno_chars=0;
  float factor;
  long spacewidth;       /* This is given to fontfcnb_string() */
  float strokewidth = 0.0f;
  volatile int strokeextraflag = 0;
  
  
  FONTSIZEDEPS *font_ptr;
  FONTPRIVATE  *fontarrayP;
  

  volatile int memsize=0;

  long h,w;
  long paddedW, char_paddedW;
  int h_anchor, v_anchor;
  static int *pixel_h_anchor_corr=NULL;
  static int *flags=NULL;
  int lsb_min, rsb_max;
  long overallwidth=0;
  long overallascent=0;
  long overalldescent=0;

  int underline_startx, underline_starty, underline_endx, underline_endy;
  int overline_startx, overline_starty, overline_endx, overline_endy;
  int overstrike_startx, overstrike_starty, overstrike_endx, overstrike_endy;
  int start, middle;
  int afm_ind;
  
  char startmask, endmask;
  static unsigned char *r2lstring;
  static int r2l_len=0;
  
  static GLYPH string_glyph={NULL,{0,0,0,0,0,0},NULL,1};
  GLYPH *currchar;

  
  
  /* The following are for bitmap blitting */
  long BitShift;
  long ByteOffset;
  /* pad=8 */
  unsigned T1_AA_TYPE16 BitBuf_c;
  unsigned char *p_c;
  unsigned char *Target_c;
  /* pad=16 */
  unsigned T1_AA_TYPE32 BitBuf_s;
  unsigned T1_AA_TYPE16 *p_s;
  unsigned T1_AA_TYPE16 *Target_s;
#ifdef T1_AA_TYPE64 
  /* pad=32 */
  unsigned T1_AA_TYPE64 BitBuf_l;
  unsigned T1_AA_TYPE32 *p_l;
  unsigned T1_AA_TYPE32 *Target_l;
#endif
  unsigned char *ustring;
  

  /* We return to this if something goes wrong deep in the rasterizer */
  if ((i=setjmp( stck_state))!=0) {
    T1_errno=T1ERR_TYPE1_ABORT;
    sprintf( err_warn_msg_buf, "t1_abort: Reason: %s",
            t1_get_abort_message( i));
    T1_PrintLog( "T1_SetString()", err_warn_msg_buf,
              T1LOG_ERROR);
    return( NULL);
  }

  /* force string elements into unsigned */
  ustring=(unsigned char*)string;


  /* Check for valid string */
  if (string==NULL){
    T1_errno=T1ERR_INVALID_PARAMETER;
    return(NULL);
  }

  /* Reorganize if required */
  if (modflag & T1_RIGHT_TO_LEFT){
    if (len)
      i=len;
    else
      i=j=strlen( string);
    if (i+1>r2l_len){
      if (r2lstring!=NULL)
       free( r2lstring);
      r2lstring=(unsigned char *)malloc( (i+1)*sizeof(char));
      r2l_len=i+1;
    }
    j--;
    while ( i--) {
      r2lstring[j-i]=ustring[i];
    }
    ustring=r2lstring;
    len=j+1;
  }
  
  
  /* Reset string glyph, if necessary */
  if (string_glyph.bits!=NULL){
    free(string_glyph.bits);
    string_glyph.bits=NULL;
  }
  string_glyph.metrics.leftSideBearing=0;
  string_glyph.metrics.rightSideBearing=0;
  string_glyph.metrics.advanceX=0;
  string_glyph.metrics.advanceY=0;
  string_glyph.metrics.ascent=0;
  string_glyph.metrics.descent=0;
  string_glyph.pFontCacheInfo=NULL;
  string_glyph.bpp=1;
  
  /* We don't want to cache the resulting bitmap: */
  cache_flag=0;
  
  /* First, check for a correct ID */
  i=T1_CheckForFontID(FontID);
  if (i==-1){
    T1_errno=T1ERR_INVALID_FONTID;
    return(NULL);
  }
  
  /* if necessary load font into memory */
  if (i==0)
    if (T1_LoadFont(FontID))
      return(NULL);

  /* If no AFM info is present, we return an error */
  if (pFontBase->pFontArray[FontID].pAFMData==NULL) {
    T1_errno=T1ERR_NO_AFM_DATA;
    return(NULL);
  }

  /* Check for valid size */
  if (size<=0.0){
    T1_errno=T1ERR_INVALID_PARAMETER;
    return(NULL);
  }

  /* Assign padding value */
  T1_pad=pFontBase->bitmap_pad;
  if (pFontBase->endian)
    T1_byte=1;
  else
    T1_byte=0;
  T1_wordsize=T1_pad;

  fontarrayP=&(pFontBase->pFontArray[FontID]);
  
  /* Check if rotation is requested */
  if (transform!=NULL){
    /* there's rotation requested => do not cache the resulting bitmap */
    rot_flag=1;
    cache_flag=0;
  }
  
  /* handle stroking stuff */
  if ( pFontBase->pFontArray[FontID].info_flags & RASTER_STROKED) {
    /* Stroking requested. If caching is not desired, clear cache_flag.
       Otherwise, leave it unaffected. */
    if ( (pFontBase->pFontArray[FontID].info_flags & CACHE_STROKED) == 0 ) {
      /* filled glyphs are cached, indicate that character is to be rendered
        on the fly and not to be cached */
      strokeextraflag = 1;
      cache_flag = 0;
    }
    strokewidth = pFontBase->pFontArray[FontID].StrokeWidth;
  }
  else {
    /* filling requested. */
    if ( (pFontBase->pFontArray[FontID].info_flags & CACHE_STROKED) != 0 ) {
      /* stroked glyphs are cached, indicate that character is to be rendered
        on the fly and not to be cached */
      strokeextraflag = 1;
      cache_flag = 0;
    }
    strokewidth = 0.0f;
  }
  
  /* font is now loaded into memory =>
     Check for size: */
  if ((font_ptr=T1int_QueryFontSize( FontID, size, NO_ANTIALIAS))==NULL){
    font_ptr=T1int_CreateNewFontSize( FontID, size, NO_ANTIALIAS);
    if (font_ptr==NULL){
      T1_errno=T1ERR_ALLOC_MEM;
      return(NULL);
    }
  }
  
  /* Now comes string specific stuff: Get length of string and create an
     array of integers where to store the bitmap positioning dimens: */
  if (len<0){  /* invalid length */
    T1_errno=T1ERR_INVALID_PARAMETER;
    return(NULL);
  }
  
  if (len==0) /* should be computed assuming "normal" 0-terminated string,
               or R2L-part has already been computed! */
    no_chars=strlen(string);
  else        /* use value given on command line */
    no_chars=len;

  /* If necessary, allocate memory */
  if (no_chars>lastno_chars){
    if (pixel_h_anchor_corr!=NULL){
      free(pixel_h_anchor_corr);
    }
    if (flags!=NULL){
      free(flags);
    }
    pixel_h_anchor_corr=(int *)calloc(no_chars, sizeof(int));
    flags=(int *)calloc(no_chars, sizeof(int));
    lastno_chars=no_chars;
  }
  else{
    /* Reset flags  and position array */
    for (i=0; i<no_chars; i++){
      flags[i]=0;
      pixel_h_anchor_corr[i]=0;
    }
  }
  
  /* Setup an appropriate charspace matrix. Note that the rasterizer
     assumes vertical values with inverted sign! Transformation should
     create a copy of the local charspace matrix which then still has
     to be made permanent. */
  if (rot_flag){
    Current_S=(struct XYspace *) 
      Permanent(Scale(Transform (font_ptr->pCharSpaceLocal,
                             transform->cxx, - transform->cxy,
                             transform->cyx, - transform->cyy),
                    DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
  }
  else{
    Current_S=(struct XYspace *)
      Permanent(Scale(Transform(font_ptr->pCharSpaceLocal,
                            1.0, 0.0, 0.0, -1.0),
                    DeviceSpecifics.scale_x, DeviceSpecifics.scale_y));
  }
  
  /* Compute the correct spacewidth value (in charspace units). The
     value supplied by the user is interpreted as an offset in
     char space units:
     */
  spacewidth=T1_GetCharWidth(FontID,fontarrayP->space_position)+spaceoff;
  
  
  /* The following if (rot_flag==0){ ... } contains the whole code
     to execute when the string is oriented horizontal. Then, there's
     the possibility of concatenating most probably existent bitmaps
     from the Cache, which should be much faster than every time raster
     all the characters.
     */
  /* First, ensure that all needed characters are in the Cache; if not,
     generate them */
  if ( (rot_flag==0) && (strokeextraflag==0) ){
    overallwidth=0;
    for (i=0; i<no_chars; i++) {
      currchar= &(font_ptr->pFontCache[ustring[i]]);
      if (currchar->bpp<1) {
       flags[i]=0;
       mode=0;
       /*  Don't try to generate space-character: */
       if (ustring[i]!=fontarrayP->space_position){
         /* Note: Never underline etc. cached chars --> modflag=0 */ 
         area=fontfcnB( FontID, 0, Current_S,
                      fontarrayP->pFontEnc,
                      ustring[i], &mode,
                      fontarrayP->pType1Data,
                      DO_RASTER,
                      strokewidth);

         /* fill the glyph-structure */
         if (mode > 0) {
           sprintf( err_warn_msg_buf, "fontfcnB() set mode=%d", mode);
           T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_WARNING);
           T1_errno=mode;
           /* Make sure to free the region if it's non-NULL */
           if (area){
             KillRegion (area);
           }
           return(NULL);
         }
         if (area == NULL){
           T1_PrintLog( "T1_SetString()", "area=NULL returned by fontfcnB()", T1LOG_WARNING);
           T1_errno=mode;
           return(NULL);
         }
         
         if (mode == FF_NOTDEF_SUBST) {
           sprintf( err_warn_msg_buf,
                   "\".notdef\" substituted in string[%d] (=character %d) from font %d",
                   i, ustring[i], FontID);
           T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_WARNING);
           mode=0;
           flags[i]=1; /* indicates that .notdef has been substituted */
         }
         
         h = area->ymax - area->ymin;
         w = area->xmax - area->xmin;
         
         if (h > 0 && w > 0) {  /* bitmap contains pixels */
           paddedW = PAD(w, T1_pad);
           memsize = h * paddedW / 8 + 1;
           currchar->bits = (char *)malloc(memsize*sizeof( char));
           if (currchar->bits == NULL) {
             T1_errno=T1ERR_ALLOC_MEM;
             /* Make sure to free up the region if it's non-NULL */
             if (area){
              KillRegion (area);
             }
             return(NULL);
           }
           (void) memset(currchar->bits, 0, memsize);
           fill(currchar->bits, h, paddedW, area,
               T1_byte, T1_bit, T1_wordsize );
         }
         /* area valid -> set metrics in cache for that character */ 
         currchar->metrics.leftSideBearing  = area->xmin;
         currchar->metrics.advanceX   = NEARESTPEL(area->ending.x - area->origin.x);
         currchar->metrics.advanceY   = - NEARESTPEL(area->ending.y - area->origin.y);
         currchar->metrics.rightSideBearing = area->xmax;
         currchar->metrics.descent          = - area->ymax;
         currchar->metrics.ascent           = - area->ymin;
         currchar->bpp=1;
         
         /* By this point, it's clear that the 'area' struct exists,
            and that we no longer need it, so free it up. */
         KillRegion (area);
       }
      } /* end of if ( ... ), needed characters are now in cache! */
    } /* end of for (i<no_chars) loop */
    /* we still have to delete the Space */
    KillSpace (Current_S);

    /* We've to compute the scale factor: */
    factor=size*DeviceSpecifics.scale_x/1000;

    /* h_anchor is the horizontal position in the resulting bitmap;
       it is incremented on the fly and of course initially 0! */
    h_anchor=0;
    /* These are the initial values for left and right sidebearing */
    rsb_max=-30000;
    lsb_min= 30000;
    overallascent=-30000;
    overalldescent=30000;
    for (i=0;i<no_chars;i++){
      /* first get index into AFM-tables */
      afm_ind=pFontBase->pFontArray[FontID].pEncMap[(int) ustring[i]];
      /* Advance to next character in high resolution */
      if (ustring[i]==fontarrayP->space_position)
       h_anchor +=(int)spacewidth;
      /* check for a substituted char or notdef and get missing escapement */
      else if (afm_ind==0) {
       /* Setup apropriate charspace matrix */
       S=(struct XYspace *)IDENTITY;
       /* Make this permanent so that scaling it in fontfcnB_ByName will
          make a duplicate of it, and this duplicate can thus be safely
          destroyed.  Fixes the somewhat smaller memory leak */
       S=(struct XYspace *)Permanent
         (Transform(S, pFontBase->pFontArray[FontID].FontTransform[0],
                   pFontBase->pFontArray[FontID].FontTransform[1],
                   pFontBase->pFontArray[FontID].FontTransform[2],
                   pFontBase->pFontArray[FontID].FontTransform[3]));
       /* Get metrics values */
       area=fontfcnB_ByName( FontID, 0, S, ".notdef", &mode,
                           pFontBase->pFontArray[FontID].pType1Data, DO_RASTER);
       if (area==NULL || mode!=0){
         sprintf( err_warn_msg_buf,
                 "Could not get charspace representation of \".notdef\", Font %d, mode=%d!",
                 FontID, mode);
         T1_PrintLog( "T1_SetString()", err_warn_msg_buf,
                     T1LOG_ERROR);
         T1_errno=mode;
         return( NULL);
       }
       /* value to add to hanchor */ 
       h_anchor +=NEARESTPEL(area->ending.x);
       /* make sure to free S */
       if (S) {
         KillSpace (S);
       }
       /* make sure to free area */
       if (area) {
         KillRegion (area);
       }
      }
      else{
       currchar=&(font_ptr->pFontCache[ustring[i]]);
       pixel_h_anchor_corr[i]=((int)floor(h_anchor*factor+0.5));
       /* Store maximum rsb ...*/
       if ( pixel_h_anchor_corr[i]+currchar->metrics.rightSideBearing > rsb_max){
         rsb_max=pixel_h_anchor_corr[i]+currchar->metrics.rightSideBearing;
       }
       /* ... and minimum lsb */
       if ( pixel_h_anchor_corr[i]+currchar->metrics.leftSideBearing < lsb_min){
         lsb_min=pixel_h_anchor_corr[i]+currchar->metrics.leftSideBearing;
       }
       /* Advance by current chars width */
       /*     h_anchor +=T1_GetCharWidth( FontID, ustring[i]); */
       if (afm_ind>0) { /* we have a standard character */
         h_anchor +=(fontarrayP->pAFMData->cmi[afm_ind-1].wx) * fontarrayP->extend;
       }
       else { /* afm_ind must be negative so that we have a composite char */
         h_anchor +=(fontarrayP->pAFMData->ccd[-(afm_ind+1)].wx) * fontarrayP->extend;
       }
       /* If kerning, insert kerning amount */
       if ((i<no_chars -1) && (modflag & T1_KERNING))
         h_anchor +=T1_GetKerning( FontID, ustring[i], ustring[i+1]);
       
       /* We still have to care for vertical metrics: */
       if (currchar->metrics.ascent>overallascent)
         overallascent=currchar->metrics.ascent;
       if (currchar->metrics.descent<overalldescent)
         overalldescent=currchar->metrics.descent;
      }
    }
    string_glyph.metrics.advanceX=(int)floor(h_anchor*factor+0.5);

    /* We have to check for underlining and such things. They may affect the
       bounding box of the glyph */
    if (modflag & T1_UNDERLINE){
      T1_ComputeLineParameters( FontID, T1_UNDERLINE,
                            string_glyph.metrics.advanceX,
                            size,
                             &underline_startx, &underline_endx,
                             &underline_starty, &underline_endy);
      /* Check whether rsb is affected ...*/
      if ( underline_endx > rsb_max){
       rsb_max=underline_endx;
      }
      /* ... and for lsb */
      if ( underline_startx < lsb_min){
       lsb_min=underline_startx;
      }

      /* Vertical metrics may also be affected. */
      if (underline_starty > overallascent)
       overallascent=underline_starty;
      if (underline_endy < overalldescent)
       overalldescent=underline_endy;
    }
    if (modflag & T1_OVERLINE){
      T1_ComputeLineParameters( FontID, T1_OVERLINE,
                            string_glyph.metrics.advanceX,
                            size,
                             &overline_startx, &overline_endx,
                             &overline_starty, &overline_endy);
      /* Check whether rsb is affected ...*/
      if ( overline_endx > rsb_max){
       rsb_max=overline_endx;
      }
      /* ... and for lsb */
      if ( overline_startx < lsb_min){
       lsb_min=overline_startx;
      }

      /* Vertical metrics may also be affected. */
      if (overline_starty > overallascent)
       overallascent=overline_starty;
      if (overline_endy < overalldescent)
       overalldescent=overline_endy;
    }
    if (modflag & T1_OVERSTRIKE){
      T1_ComputeLineParameters( FontID, T1_OVERSTRIKE,
                            string_glyph.metrics.advanceX,
                            size,
                             &overstrike_startx, &overstrike_endx,
                             &overstrike_starty, &overstrike_endy);
      /* Check whether rsb is affected ...*/
      if ( overstrike_endx > rsb_max){
       rsb_max=overstrike_endx;
      }
      /* ... and for lsb */
      if ( overstrike_startx < lsb_min){
       lsb_min=overstrike_startx;
      }

      /* Vertical metrics may also be affected. */
      if (overstrike_starty > overallascent)
       overallascent=overstrike_starty;
      if (overstrike_endy < overalldescent)
       overalldescent=overstrike_endy;
    }
    

    
    /* Set the string-glyphs' metrics: */
    /* Bearings: */
    string_glyph.metrics.rightSideBearing=rsb_max;      
    string_glyph.metrics.leftSideBearing=lsb_min;
    /* ascent and descent: */
    string_glyph.metrics.ascent=overallascent;
    string_glyph.metrics.descent=overalldescent;

    

    /* Now, allocate memory for the resulting bitmap and set it to 0: */
    h=overallascent - overalldescent;
    w=string_glyph.metrics.rightSideBearing-string_glyph.metrics.leftSideBearing;
    
    paddedW = PAD( w, T1_pad);
    if ( h > 0 && w > 0){
      memsize = h * paddedW / 8;
      /* We alloc some amount more in order to avoid alignment check in
        bit-blitting loop */
      memsize += T1_pad/8;
      string_glyph.bits = (char *)malloc( memsize);
      if (string_glyph.bits == NULL) {
       T1_errno=T1ERR_ALLOC_MEM;
       return(NULL);
      }
      
    }
    else {
    /* We have only characters without pixels in the string ->
       we allow this and only set the advance width in the glyph.
       The bits pointer will be NULL. We reset rsb and lsb */
      string_glyph.metrics.rightSideBearing=0;      
      string_glyph.metrics.leftSideBearing=0;
      string_glyph.metrics.ascent=0;      
      string_glyph.metrics.descent=0;
    }
    
    if (string_glyph.bits != NULL) {
      
      memset(string_glyph.bits, 0, memsize);
      
      /* Now comes the loop for bitmap blitting: */
      for (i=0;i<no_chars;i++){
       /* Get pointer to character number i of string: */
       currchar=&(font_ptr->pFontCache[ustring[i]]);
       
       /* First, we have to correct the positioning values to refer to
          the bitmap BBox */
       pixel_h_anchor_corr[i] -= lsb_min;
       pixel_h_anchor_corr[i] += currchar->metrics.leftSideBearing;   
       
       /* Compute vertical anchor for current char-bitmap: */
       v_anchor=overallascent - currchar->metrics.ascent;
       char_paddedW=PAD( currchar->metrics.rightSideBearing
                       - currchar->metrics.leftSideBearing , T1_pad);
       /* We have to check for Big Endian. In that case, we have to
          act on byte-level */
       if (T1_byte){
         BitShift =  pixel_h_anchor_corr[i] % 8;
         ByteOffset = pixel_h_anchor_corr[i] / 8;
       }
       else { 
         BitShift =  pixel_h_anchor_corr[i] % T1_pad;
         ByteOffset = pixel_h_anchor_corr[i] / T1_pad;
         if (T1_pad==32)
           ByteOffset *=4;
         else if (T1_pad==16)
           ByteOffset *=2;
       }  
#ifdef T1_AA_TYPE64
       /* We compile this part only if long is 64 bits to be conform to ANSI C */
       if (T1_pad==32 && T1_byte==0){
         /* The following loop steps through the lines of the character bitmap: */
         for (j=0;j<currchar->metrics.ascent-currchar->metrics.descent;j++){
           Target_l= (unsigned T1_AA_TYPE32 *)(string_glyph.bits +((v_anchor+j)*paddedW/8)
                                   +ByteOffset);
           /* The following loop copies the scanline of a character bitmap: */
           if (currchar->bits != NULL) {
             p_l = (unsigned T1_AA_TYPE32 *)(currchar->bits+(char_paddedW/8*j));
             if (BitShift == 0) {
              for (k=char_paddedW >> 5; k; k--)
                *Target_l++ |= *p_l++;
             } else {
              for (k=0; k < char_paddedW / 32 ; k++){
                BitBuf_l= ((T1_AA_TYPE64)(*p_l++)) << BitShift;
                *Target_l++ |= BitBuf_l;
                *Target_l |= BitBuf_l>>l_shift;
              } /* End of for ( .. ) stepping through columns */
             }
           } /* End of if(currchar->bits != NULL) */
         } /* End of for( .. ) steppin' through lines of char bitmap */
       }/* end if (T1_pad==32) */
       else
#endif 
         if (T1_pad==16 && T1_byte==0){
           /* The following loop steps through the lines of the character bitmap: */
           for (j=0;j<currchar->metrics.ascent-currchar->metrics.descent;j++){
             Target_s= (unsigned T1_AA_TYPE16 *)(string_glyph.bits +((v_anchor+j)*paddedW/8)
                                      +ByteOffset);
             /* The following loop copies the scanline of a character bitmap: */
             if (currchar->bits != NULL) {
              p_s = (unsigned  T1_AA_TYPE16 *)(currchar->bits+(char_paddedW/8*j));
              if (BitShift == 0) {
                for (k=char_paddedW >> 4; k; k--)
                  *Target_s++ |= *p_s++;
              }
              else{
                for (k=char_paddedW >> 4; k; k--){
                  BitBuf_s= ((T1_AA_TYPE32)(*p_s++))<<BitShift;
                  *Target_s++ |= BitBuf_s;
                  *Target_s |= BitBuf_s>>s_shift;
                } /* End of for ( .. ) stepping through columns */
              }
             } /* End of if(currchar->bits != NULL) */
           } /* End of for( .. ) steppin' through lines of char bitmap */
         }/* end if (T1_pad==16 */
         else{ /* T1_pad = 8 or Big Endian machine */
           /* The following loop steps through the lines of the character bitmap: */
           for (j=0;j<currchar->metrics.ascent-currchar->metrics.descent;j++){
             Target_c= (unsigned char *)(string_glyph.bits +((v_anchor+j)*paddedW/8)
                                     +ByteOffset);
             /* The following loop copies the scanline of a character bitmap: */
             if (currchar->bits != NULL) {
              p_c = (unsigned char *)(currchar->bits+(char_paddedW/8*j));
              if (BitShift == 0){
                for (k=char_paddedW >> 3; k; k--)
                  *Target_c++ |= *p_c++;
              }
              else{
                for (k=char_paddedW >> 3; k; k--){
                  BitBuf_c = ((T1_AA_TYPE16)(*p_c++)) << BitShift;
                  *Target_c++ |= BitBuf_c;
                  *Target_c |= BitBuf_c>>c_shift;
                } /* End of for ( .. ) stepping through columns */
              }
             } /* End of if(currchar->bits != NULL) */
           } /* End of for( .. ) steppin' through lines of char bitmap */
         } /* end if (T1_pad==8) and/or BigEndian  */
      }
    } /* if (string_glyph.bits != NULL) */
    
    
    /* We now put the underlining rule on the glyph */
    if (modflag & T1_UNDERLINE){
      start=-string_glyph.metrics.leftSideBearing;
      for (i=string_glyph.metrics.ascent-underline_starty;
          i<string_glyph.metrics.ascent-underline_endy; i++){
       start =-string_glyph.metrics.leftSideBearing +
         (int) floor((double)(string_glyph.metrics.ascent-i)
                    *fontarrayP->slant+0.5);
       middle = ((start+string_glyph.metrics.advanceX) / 8) - (start / 8);
       startmask = 0xFF << (start % 8);
       endmask = (char) ~(0xFF << ((start+string_glyph.metrics.advanceX) % 8));
       Target_c= (unsigned char *)(string_glyph.bits +(i*paddedW/8)
                                + (start / 8));
       j=middle;
       if (j == 0)
         *Target_c++ |= startmask & endmask;
       else {
         *Target_c++ |= startmask;
         while (--j > 0)
           *Target_c++ = (unsigned char) 0xFF;
         if ((endmask))
           *Target_c |= endmask;
       }
      }
    }
    /* Put an overstrike rule on the glyph */
    if (modflag & T1_OVERSTRIKE){
      start=-string_glyph.metrics.leftSideBearing;
      for (i=string_glyph.metrics.ascent-overstrike_starty;
          i<string_glyph.metrics.ascent-overstrike_endy; i++){
       start =-string_glyph.metrics.leftSideBearing +
         (int) floor((double)(string_glyph.metrics.ascent-i)
                    *fontarrayP->slant+0.5);
       middle = ((start+string_glyph.metrics.advanceX) / 8) - (start / 8);
       startmask = 0xFF << (start % 8);
       endmask = (char) ~(0xFF << ((start+string_glyph.metrics.advanceX) % 8));
       Target_c= (unsigned char *)(string_glyph.bits +(i*paddedW/8)
                                + (start / 8));
       j=middle;
       if (j == 0)
         *Target_c++ |= startmask & endmask;
       else {
         *Target_c++ |= startmask;
         while (--j > 0)
           *Target_c++ = (unsigned char) 0xFF;
         if ((endmask))
           *Target_c |= endmask;
       }
      }
    }
    /* Put an overline rule */
    if (modflag & T1_OVERLINE){
      start=-string_glyph.metrics.leftSideBearing;
      for (i=string_glyph.metrics.ascent-overline_starty;
          i<string_glyph.metrics.ascent-overline_endy; i++){
       start =-string_glyph.metrics.leftSideBearing +
         (int) floor((double)(string_glyph.metrics.ascent-i)
                    *fontarrayP->slant+0.5);
       middle = ((start+string_glyph.metrics.advanceX) / 8) - (start / 8);
       startmask = 0xFF << (start % 8);
       endmask = (char) ~(0xFF << ((start+string_glyph.metrics.advanceX) % 8));
       Target_c= (unsigned char *)(string_glyph.bits +(i*paddedW/8)
                                + (start / 8));
       j=middle;
       if (j == 0)
         *Target_c++ |= startmask & endmask;
       else {
         *Target_c++ |= startmask;
         while (--j > 0)
           *Target_c++ = (unsigned char) 0xFF;
         if ((endmask))
           *Target_c |= endmask;
       }
      }
    }

    /* Check for writing direction and re-compute dimensions appropriately: */
    if (modflag & T1_RIGHT_TO_LEFT){
      string_glyph.metrics.advanceX *= -1;
      string_glyph.metrics.leftSideBearing += string_glyph.metrics.advanceX;
      string_glyph.metrics.rightSideBearing += string_glyph.metrics.advanceX;
    } 
    
    return(&string_glyph);
  } /* end of "if (rot_flag==0.0)" */


  /* fnt_ptr now points to the correct FontSizeDeps-struct =>
     lets now raster the character */
  mode=0;
  kern_pairs=(int *)calloc(no_chars, sizeof(int));
  if ((modflag & T1_KERNING))
    for (i=0; i<no_chars -1; i++)
      kern_pairs[i]=T1_GetKerning( FontID, ustring[i], ustring[i+1]);
  area=fontfcnB_string( FontID, modflag, Current_S,
                     fontarrayP->pFontEnc,
                     ustring, no_chars, &mode,
                     fontarrayP->pType1Data,
                     kern_pairs, spacewidth,
                     DO_RASTER,
                     strokewidth);
  KillSpace (Current_S);
  
  /* In all cases, free memory for kerning pairs */
  free(kern_pairs);
  
  /* fill the string_glyph-structure */
  if (mode > 0) {
    sprintf( err_warn_msg_buf, "fontfcnB() set mode=%d", mode);
    T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_WARNING);
    T1_errno=mode;
    /* make sure to get rid of area if it's there */
    if (area){
      KillRegion (area);
    }
    return(NULL);
  }
  if (area == NULL){
    T1_PrintLog( "T1_SetString()", "area=NULL returned by fontfcnB()", T1LOG_WARNING);
    T1_errno=mode;
    return(NULL);
  }
  
  if (mode == FF_NOTDEF_SUBST) {
    sprintf( err_warn_msg_buf,
            "\".notdef\" substituted somewhere in string from font %d",
            FontID);
    T1_PrintLog( "T1_SetString()", err_warn_msg_buf, T1LOG_WARNING);
    mode=0;
  }
  
  h = area->ymax - area->ymin;
  w = area->xmax - area->xmin;
  paddedW = PAD(w, T1_pad);
  if (h > 0 && w > 0) {
    memsize = h * paddedW / 8 + 1;
    /* This is for the users copy of the character, for security-reasons
       the original pointer to the cache area is not used. The entry string_glyph.bits
       is free'ed every time this function is called: */
    string_glyph.bits = (char *)malloc(memsize*sizeof( char));
    if (string_glyph.bits == NULL) {
      T1_errno=T1ERR_ALLOC_MEM;
      /* make sure to get rid of area if it's there */
      if (area){
       KillRegion (area);
      }
      /* it's safe to free this, since this is a rotated glyph and
        therefore it's a copy of the original one */
      return(NULL);
    }
  }
  else {
    h = w = 0;
    area->xmin = area->xmax = 0;
    area->ymin = area->ymax = 0;
  }
  
  string_glyph.metrics.leftSideBearing=area->xmin;
  string_glyph.metrics.advanceX=NEARESTPEL(area->ending.x - area->origin.x);
  string_glyph.metrics.advanceY=-NEARESTPEL(area->ending.y - area->origin.y);
  string_glyph.metrics.rightSideBearing=area->xmax; 
  string_glyph.metrics.descent=-area->ymax;  
  string_glyph.metrics.ascent=-area->ymin; 

  if (h > 0 && w > 0) {
    (void) memset(string_glyph.bits, 0, memsize);
    fill(string_glyph.bits, h, paddedW, area, T1_byte, T1_bit, T1_wordsize );
  }
  else { /* We have no black pixels */
    string_glyph.metrics.leftSideBearing=0;
    string_glyph.metrics.advanceX=NEARESTPEL(area->ending.x - area->origin.x);
    string_glyph.metrics.advanceY=-NEARESTPEL(area->ending.y - area->origin.y);
    string_glyph.metrics.rightSideBearing=0; 
    string_glyph.metrics.descent=0;  
    string_glyph.metrics.ascent=0; 
  }
  

  /* make sure to get rid of area if it's there */
  if (area){
    KillRegion (area);
  }
  /* Check for writing direction and re-compute dimensions appropriately: */
  if (modflag & T1_RIGHT_TO_LEFT){
    string_glyph.metrics.advanceX *= -1;
    string_glyph.metrics.advanceY *= -1;
    string_glyph.metrics.leftSideBearing += string_glyph.metrics.advanceX;
    string_glyph.metrics.rightSideBearing += string_glyph.metrics.advanceX;
    string_glyph.metrics.descent += string_glyph.metrics.advanceY;
    string_glyph.metrics.ascent += string_glyph.metrics.advanceY;
  } 
  return(&string_glyph);
}

Here is the call graph for this function: