[xorg-commit-diffs] xc/programs/Xserver/Xprint/ps PsFTFonts.c, NONE, 1.1.4.1 psout_ft.c, NONE, 1.1.4.1 psout_ftpstype1.c, NONE, 1.1.4.1 psout_ftpstype3.c, NONE, 1.1.4.1 Imakefile, 1.1.4.2, 1.1.4.3 Ps.h, 1.1.4.3, 1.1.4.4 PsArea.c, 1.1.4.1, 1.1.4.2 PsAttVal.c, 1.1.4.2, 1.1.4.3 PsAttr.c, 1.1.4.2, 1.1.4.3 PsCache.c, 1.1.4.1, 1.1.4.2 PsColor.c, 1.1.4.2, 1.1.4.3 PsFonts.c, 1.1.4.3, 1.1.4.4 PsGC.c, 1.1.4.3, 1.1.4.4 PsInit.c, 1.1.4.3, 1.1.4.4 PsLine.c, 1.1.4.2, 1.1.4.3 PsMisc.c, 1.1.4.2, 1.1.4.3 PsPixel.c, 1.1.4.2, 1.1.4.3 PsPixmap.c, 1.1.4.2, 1.1.4.3 PsPolygon.c, 1.1.4.2, 1.1.4.3 PsPrint.c, 1.1.4.2, 1.1.4.3 PsText.c, 1.1.4.3, 1.1.4.4 PsWindow.c, 1.1.4.3, 1.1.4.4 psout.c, 1.1.4.2, 1.1.4.3 psout.h, 1.1.4.2, 1.1.4.3

Roland Mainz xorg-commit at pdx.freedesktop.org
Wed Apr 21 20:03:42 EST 2004


Committed by: gisburn

Update of /cvs/xorg/xc/programs/Xserver/Xprint/ps
In directory pdx:/tmp/cvs-serv5532/programs/Xserver/Xprint/ps

Modified Files:
      Tag: XORG-CURRENT
	Imakefile Ps.h PsArea.c PsAttVal.c PsAttr.c PsCache.c 
	PsColor.c PsFonts.c PsGC.c PsInit.c PsLine.c PsMisc.c 
	PsPixel.c PsPixmap.c PsPolygon.c PsPrint.c PsText.c PsWindow.c 
	psout.c psout.h 
Added Files:
      Tag: XORG-CURRENT
	PsFTFonts.c psout_ft.c psout_ftpstype1.c psout_ftpstype3.c 
Log Message:
Fix for http://pdx.freedesktop.org/cgi-bin/bugzilla/show_bug.cgi?id=530 - Land XPRINT branch on XORG-CURRENT

--- NEW FILE: PsFTFonts.c ---

/*
Copyright (c) 2003-2004 Roland Mainz <roland.mainz at nrubsig.org>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <ctype.h>
#include <limits.h>
#include <sys/stat.h>

#include "regionstr.h"
#include "fontstruct.h"
#include "dixfontstr.h"
#include "scrnintstr.h"
#include "fontxlfd.h"
#include "fntfil.h"
#include "fntfilst.h"

#include "Ps.h"

#include <ft2build.h>
#include FT_FREETYPE_H

#include "ft.h"
#include "ftfuncs.h"

char *
PsGetFTFontFileName(FontPtr pFont)
{
  FTFontPtr tf = (FTFontPtr)pFont->fontPrivate;
  return tf->instance->face->filename;
}
   
Bool
PsIsFreeTypeFont(FontPtr pFont)
{
  int         i;
  int         nprops = pFont->info.nprops;
  FontPropPtr props  = pFont->info.props;
  /* "RASTERIZER_NAME" must match the rasterizer name set in
   * xc/lib/font/FreeType/ftfuncs.c */
  Atom        name   = MakeAtom("RASTERIZER_NAME", 15, True); 
  Atom        value  = (Atom)0;
  char       *rv;

  for( i=0 ; i<nprops ; i++ )
  {
    if( props[i].name==name )
      { value = props[i].value; break; }
  }
  if( !value )
    return False; 

  rv = NameForAtom(value);
  if( !rv )
    return False; 

  if( memcmp(rv, "FreeType", 8) == 0 )
    return  True;

  return False;
}


--- NEW FILE: psout_ft.c ---

/*
Copyright (c) 2003-2004 Roland Mainz <roland.mainz at nrubsig.org>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <stdlib.h>
#include <stdio.h>
#include "os.h"
#define USE_PSOUT_PRIVATE 1
#include "psout.h"

#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_TYPE1_TABLES_H

#include "Xproto.h"
#include "font.h"
#include "fontstruct.h"
#include "fntfilst.h"
#include "fontutil.h"
#include "fontenc.h"
#include "ft.h"
#include "ftfuncs.h"
#include "servermd.h" /* needed for endian test (IMAGE_BYTE_ORDER) */

#define USE_FT_PS_NAMES 1

#ifdef USE_FT_PS_NAMES
void PsOut_Get_FreeType_Glyph_Name( char *destbuf, FontPtr pFont, unsigned long x11fontindex)
{
  FTFontPtr      tf     = (FTFontPtr)pFont->fontPrivate;
  FT_Face        ttface = tf->instance->face->face;
  FT_Error       error;
  char           buf[256];
  unsigned long  ftindex;

  /* Remap X11 font index to FreeType font index */
  ftindex = FTRemap(ttface, &tf->mapping, x11fontindex);

  if( FT_Has_PS_Glyph_Names(ttface) )
  {
    error = FT_Get_Glyph_Name(ttface, ftindex, buf, 64);
  }
  else
  {
    error = 1;
  }
  
  if( error )
  {
    /* Check for unicode mapping
     * See Adobe document "Unicode and Glyph Names"
     * (http://partners.adobe.com/asn/tech/type/unicodegn.jsp)
     */
    if( (tf->mapping.mapping->type == FONT_ENCODING_UNICODE) &&
        (ftindex < 0xFFFE) )
    {
      sprintf(buf, "uni%04lx", ftindex);
    }
    else
    {
      sprintf(buf, "ch%02lx", ftindex);
    }
  }
  
  strcpy(destbuf, buf);
}
#endif /* USE_FT_PS_NAMES */

int PsOut_DownloadFreeType(PsOutPtr self, PsFTDownloadFontType downloadfonttype, const char *psfontname, FontPtr pFont, long block_offset)
{
  switch(downloadfonttype)
  {
    case PsFontType3:
        return PsOut_DownloadFreeType3(self, psfontname, pFont, block_offset);
    case PsFontType1:
        return PsOut_DownloadFreeType1(self, psfontname, pFont, block_offset);
    default:
        FatalError("PS DDX: PsOut_DownloadFreeType(downloadfonttype='%d' not implemented\n",
                   (int)downloadfonttype);
        return 0; /* NO-OP, FatalError() will call |exit()| */
  }
}

/* cloned from |PsOut_TextAttrs16| */
void
PsOut_FreeType_TextAttrs16(PsOutPtr self, char *fnam, int siz, int iso)
{
  int i;
  if( self->FontName && strcmp(fnam, self->FontName)==0 &&
      siz==self->FontSize ) return;
  if( self->FontName ) xfree(self->FontName);
  self->FontName = (char *)xalloc(strlen(fnam)+1);
  strcpy(self->FontName, fnam);
  self->FontSize = siz;
  for( i=0 ; i<4 ; i++ ) self->FontMtx[i] = -1.;
}

/* cloned from |PsOut_TextAttrsMtx16| */
void
PsOut_FreeType_TextAttrsMtx16(PsOutPtr self, char *fnam, float *mtx, int iso)
{
  int i;
  if( self->FontName && strcmp(fnam, self->FontName)==0 &&
      mtx[0]==self->FontMtx[0] && mtx[1]==self->FontMtx[1] &&
      mtx[2]==self->FontMtx[2] && mtx[3]==self->FontMtx[3] ) return;
  if( self->FontName ) xfree(self->FontName);
  self->FontName = (char *)xalloc(strlen(fnam)+1);
  strcpy(self->FontName, fnam);
  for( i=0 ; i<4 ; i++ ) self->FontMtx[i] = mtx[i];
  self->FontSize = -1;
}

static
int FT_Get_CharcellMetricsCharacterHeight(FontPtr pFont)
{
  FTFontPtr ftfont = (FTFontPtr)pFont->fontPrivate;

  return ftfont->instance->charcellMetrics->ascent + 
         ftfont->instance->charcellMetrics->descent;
}

static
int FT_Get_CharcellMetricsCharacterWidth(FontPtr pFont)
{
  FTFontPtr ftfont = (FTFontPtr)pFont->fontPrivate;

  if( ftfont->instance->spacing != FT_PROPORTIONAL )
  {
    int width = ftfont->instance->charcellMetrics->characterWidth;
    
    /* If the font uses a matrix make sure we transform the |characterWidth|
     * back to it's original value since we download the untransformed font
     * and use a PostScript transformation matrix to transform the font when
     * rendering the text
     */
    if( ftfont->instance->transformation.nonIdentity )
    {
      FT_Vector v;
    
      FT_Matrix m = ftfont->instance->transformation.matrix;
      (void)FT_Matrix_Invert(&m); /* FixMe: We should check the return code */
      v.x = width;
      v.y = FT_Get_CharcellMetricsCharacterHeight(pFont);
      FT_Vector_Transform(&v, &m);
      width = v.x;
    }
    
    return width;
  }

  return 0;
}

void
PsOut_FreeType_Text(FontPtr pFont, PsOutPtr self, int x, int y, char *text, int textl)
{
  int i;
  int xo = self->XOff,
      yo = self->YOff;
  char buf[256];
  int  cwidth = FT_Get_CharcellMetricsCharacterWidth(pFont);

  if( self->InFrame || self->InTile ) xo = yo = 0;
  x += xo; y += yo;

  S_OutNum(self, (float)x);
  S_OutNum(self, (float)y);
  S_OutTok(self, "moveto", 1);
  
  S_OutTok(self, "[ ", 0);
  
  for( i = 0 ; i < textl ; i++ )
  {
#ifdef USE_FT_PS_NAMES
    char namebuf[256];
    unsigned int  ch           = text[i]&0xFF;
    unsigned long block_offset = 0;
    PsOut_Get_FreeType_Glyph_Name(namebuf, pFont, ch+block_offset);

    sprintf(buf, "/%s ", namebuf);
#else
    sprintf(buf, "/ch%02x ", text[i]&0xFF);
#endif /* USE_FT_PS_NAMES */
    S_OutTok(self, buf, 0);
  }

  /* Check whether we have any special spacing requirements (e.g. non-proportional fonts) ... */
  if( cwidth != 0 )
  {
    /* If the we use a matrix to render the font (instead of using |self->FontSize|)
     * we must apply the matrix to the "rmoveto" which is used to force the exact
     * character width. The "trmoveto" macro will do that for us...
     */
    if( self->FontSize == -1 )
    {  
      sprintf(buf, "]{gs glyphshow gr %d 0 trmoveto}fa",  cwidth);
    }
    else
    {
      sprintf(buf, "]{gs glyphshow gr %d 0 rm}fa", cwidth);
    }
  }
  else
  {
    sprintf(buf, "]{glyphshow}fa");
  }
  S_OutTok(self, buf, 0);
}

/* XXX: |PsOut_FreeType_Text16| should be rewritten - currently it uses lame,
 * slow hacks and makes some risky assumtions about how |PsOut_Text16|
 * allocates memory */
void
PsOut_FreeType_Text16(FontPtr pFont, PsOutPtr self, int x, int y, unsigned short *text, int textl)
{
  int i;
  int xo = self->XOff,
      yo = self->YOff;
  unsigned short c,
                 c_hiByte,
                 c_lowByte,
                 fontPage;
  long           lastFontPage = -1;
  char           baseFontName[256];
  char           buf[256];

  if( self->InFrame || self->InTile ) xo = yo = 0;
  x += xo; y += yo;

  strcpy(baseFontName, self->FontName);

  S_OutNum(self, (float)x);
  S_OutNum(self, (float)y);
  S_OutTok(self, "moveto", 1);
  
  for( i = 0 ; i < textl ; i++ )
  {
    c = text[i];
#if IMAGE_BYTE_ORDER == LSBFirst
    c_hiByte = c & 0x00FF;
    c_lowByte = (c >> 8) & 0x00FF;
#elif IMAGE_BYTE_ORDER == MSBFirst
    c_hiByte  = (c >> 8) & 0x00FF;
    c_lowByte = c & 0x00FF;
#else
#error Unsupported byte order
#endif
    fontPage  = c_hiByte;

    if( fontPage != lastFontPage )
    {
      if( fontPage > 0 )
      {
        sprintf(buf, "%s_%x", baseFontName, fontPage);
      }
      else
      {
        sprintf(buf, "%s", baseFontName);
      }

      if( self->FontSize == -1 )
      {
        PsOut_TextAttrsMtx(self, buf, self->FontMtx, FALSE);
      }
      else
      {
        PsOut_TextAttrs(self, buf, self->FontSize, FALSE);
      }
      lastFontPage = fontPage;
    }

#ifdef USE_FT_PS_NAMES
    {
      char namebuf[256];
      unsigned int  ch           = c_lowByte;
      unsigned long block_offset = c_hiByte * 0x100 /* same as c_hiByte << 8 */;
      int           cwidth       = FT_Get_CharcellMetricsCharacterWidth(pFont);
      PsOut_Get_FreeType_Glyph_Name(namebuf, pFont, ch+block_offset);
      
      /* Check whether we have any special spacing requirements (e.g. non-proportional fonts) ... */
      if( cwidth != 0 )
      {
        /* If the we use a matrix to render the font (instead of using |self->FontSize|)
         * we must apply the matrix to the "rmoveto" which is used to force the exact
         * character width. The "trmoveto" macro will do that for us...
         */
        if( self->FontSize == -1 )
        {
          sprintf(buf, "gs /%s glyphshow gr %d 0 trmoveto", namebuf, cwidth);
        }
        else
        {
          sprintf(buf, "gs /%s glyphshow gr %d 0 rm",  namebuf, cwidth);
        }
      }
      else
      {
        sprintf(buf, "/%s glyphshow", namebuf);
      }
    }
#else
    sprintf(buf, "/ch%02x glyphshow", c_lowByte);
#endif /* USE_FT_PS_NAMES */    
    S_OutTok(self, buf, 1); 
  }

  if( self->FontName ) xfree(self->FontName);
  self->FontName = (char *)xalloc(strlen(baseFontName)+1);
  strcpy(self->FontName, baseFontName);
}


--- NEW FILE: psout_ftpstype1.c ---

/*
Copyright (c) 2003-2004 Roland Mainz <roland.mainz at nrubsig.org>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/


#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/wait.h>

#include "os.h"
#define USE_PSOUT_PRIVATE 1
#include "psout.h"

#include <ft2build.h>
#include FT_FREETYPE_H

#include "Xproto.h"
#include "font.h"
#include "fontstruct.h"
#include "fntfilst.h"
#include "fontutil.h"
#include "fontenc.h"
#include "ft.h"
#include "ftfuncs.h"

int do_debug_ft2pt1             = FALSE;
int do_enable_ft2pt1_optimizer  = FALSE;

/* Defined in ttf2pt1.c */
int ft2pt1_main(int argc, char **argv,
                FTFontPtr tf, const char *download_psfontname, unsigned long download_font_block_offset);

/* Download FreeType outlines as PS Type1 font */
int PsOut_DownloadFreeType1(PsOutPtr self, const char *psfontname, FontPtr pFont, long block_offset)
{
  FTFontPtr tf;
  FT_Face   face;
  int       ft2pt1_numargs = 0;
  char     *ft2pt1_args[40];
  char     *pstype1filename_prefix;
  char      pstype1filename[PATH_MAX+1];
  int       ft2pt1_main_retval;
  pid_t     childpid;
  
  tf = (FTFontPtr)pFont->fontPrivate;
  face = tf->instance->face->face;
  
  /* Set debugging flags */
  do_debug_ft2pt1             = (getenv("XPRT_PSDDX_DO_DEBUG_FT2PT1") != NULL);
  do_enable_ft2pt1_optimizer  = (getenv("XPRT_PSDDX_DO_ENABLE_FT2PT1_OPTIMIZER") != NULL);

  if( do_debug_ft2pt1 )
  {
    fprintf(stderr, "# Converting FT2 font to PS Type1 filename='%s', ttface=%lx\n", tf->instance->face->filename, (long)face);
  }

  pstype1filename_prefix = tempnam(NULL, "Xprt_");

  ft2pt1_args[ft2pt1_numargs] = "ft2pt1";                        ft2pt1_numargs++;
  ft2pt1_args[ft2pt1_numargs] = "-Ob";                           ft2pt1_numargs++;
  ft2pt1_args[ft2pt1_numargs] = "-e";                            ft2pt1_numargs++;
  ft2pt1_args[ft2pt1_numargs] = "-a";                            ft2pt1_numargs++;
  ft2pt1_args[ft2pt1_numargs] = "-Ga";                           ft2pt1_numargs++;
  if( do_enable_ft2pt1_optimizer )
  {
    /* Scale fonts to a 1000x1000 matrix */
    ft2pt1_args[ft2pt1_numargs] = "-Ot";                         ft2pt1_numargs++;
  }
  else
  {
    /* Disable the ttf2pt1 optimisations */
    ft2pt1_args[ft2pt1_numargs] = "-Ou";                         ft2pt1_numargs++;
    ft2pt1_args[ft2pt1_numargs] = "-Oo";                         ft2pt1_numargs++;
    ft2pt1_args[ft2pt1_numargs] = "-Os";                         ft2pt1_numargs++;
    ft2pt1_args[ft2pt1_numargs] = "-Oh";                         ft2pt1_numargs++;
  }
  
  if( !do_debug_ft2pt1 )
  {
    ft2pt1_args[ft2pt1_numargs] = "-W 0";                        ft2pt1_numargs++;
  }
  ft2pt1_args[ft2pt1_numargs] = tf->instance->face->filename;    ft2pt1_numargs++;
  ft2pt1_args[ft2pt1_numargs] = pstype1filename_prefix;          ft2pt1_numargs++;
  ft2pt1_args[ft2pt1_numargs] = NULL;

/* XXX: ttf2pt1 has lots of leaks and global vars which are not cleaned-up
 * As long this problem exists we will simply fork() and call the converter
 * from the child process (all resources are free'ed when the child process
 * exists) as a workaround.
 */
#define FT2PT1_NEEDS_SEPERATE_PROCESS 1

#ifdef FT2PT1_NEEDS_SEPERATE_PROCESS
  /* Flush internal buffer and then the stdio stream before fork()! */
  S_Flush(self);
  fflush(self->Fp);

  childpid = fork();
  switch(childpid)
  {
    case -1:
        FatalError("PS DDX internal error: Cannot fork() converter child process, errno=%d\n", (int)errno);
        break;
    case 0: /* child */
        fclose(self->Fp);
        self->Fp = NULL;
            
        ft2pt1_main_retval = ft2pt1_main(ft2pt1_numargs, ft2pt1_args, tf, psfontname, block_offset);
        if( do_debug_ft2pt1 )
        {
          fprintf(stderr, "## ft2pt1_main returned %d (child)\n", ft2pt1_main_retval);
        }
        exit(ft2pt1_main_retval);
        break;
    default: /* parent */
        waitpid(childpid, &ft2pt1_main_retval, 0);
        break;
  }

  if( do_debug_ft2pt1 )
  {
    fprintf(stderr, "## ft2pt1_main returned %d (parent)\n", ft2pt1_main_retval);
  }
#else
  S_Flush(self);

  ft2pt1_main_retval = ft2pt1_main(ft2pt1_numargs, ft2pt1_args, tf, psfontname, block_offset);
  if( do_debug_ft2pt1 )
  {
    fprintf(stderr, "## ft2pt1_main returned %d (child)\n", ft2pt1_main_retval);
  }
#endif /* FT2PT1_NEEDS_SEPERATE_PROCESS */

  if( ft2pt1_main_retval != EXIT_SUCCESS )
  {
    FatalError("PS DDX internal error while converting FreeType font '%s' to PS Type1, error=%d\n",
               tf->instance->face->filename, ft2pt1_main_retval);
  }

  sprintf(pstype1filename, "%s.pfa", pstype1filename_prefix);
  if( do_debug_ft2pt1 )
  {
    fprintf(stderr, "# Downloading converted FT2/PS Type1 filename='%s'\n", pstype1filename);
  }

  PsOut_DownloadType1(self, "PsOut_DownloadFreeType1", psfontname, pstype1filename);
  
  if( !do_debug_ft2pt1 )
  {
    unlink(pstype1filename);
  }
  
  free(pstype1filename_prefix);

  S_Flush(self);

  return 0;
}



--- NEW FILE: psout_ftpstype3.c ---

/*
Copyright (c) 2003-2004 Roland Mainz <roland.mainz at nrubsig.org>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <stdlib.h>
#include <stdio.h>
#include "os.h"
#define USE_PSOUT_PRIVATE 1
#include "psout.h"

#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_TRUETYPE_TABLES_H
#include FT_BBOX_H
#include FT_GLYPH_H

#include FT_CONFIG_CONFIG_H
#include FT_CONFIG_OPTIONS_H
#include FT_ERRORS_H
#include FT_SYSTEM_H
#include FT_IMAGE_H
#include FT_TYPES_H
#include FT_OUTLINE_H
#include FT_MODULE_H
#include FT_RENDER_H
#include FT_TYPE1_TABLES_H
#include FT_TRUETYPE_IDS_H
#include FT_TRUETYPE_TAGS_H
#include FT_CACHE_H
#include FT_CACHE_IMAGE_H
#include FT_CACHE_SMALL_BITMAPS_H
#include FT_MULTIPLE_MASTERS_H
#include FT_SFNT_NAMES_H

#define USE_FT_INTERNALS 1
#ifdef USE_FT_INTERNALS
#include FT_INTERNAL_TYPE1_TYPES_H
#include "t42types.h"
#include FT_INTERNAL_OBJECTS_H
#endif /* USE_FT_INTERNALS */

#include "Xproto.h"
#include "font.h"
#include "fontstruct.h"
#include "fntfilst.h"
#include "fontutil.h"
#include "fontenc.h"
#include "ft.h"
#include "ftfuncs.h"

struct ft2info
{
  FontPtr         pFont;
  FTFontPtr       tf;
  FT_Face         ttface;
  struct
  {
    char *full_name;
    char *copyright;
    char *family;
    char *subfamily;
    char *version;
  } nameid;
  TT_Postscript  *ttpostscript;
  TT_Header      *ttheader;
};

/* Local prototypes */
static FT_Error PSType3_createOutlineGlyphs(FILE *out, struct ft2info *ti, unsigned long unicode, const char *psglyphname);
static int      PSType3_generateOutlineFont(FILE *out, const char *psfontname, struct ft2info *ti, long block_offset);

extern FT_Library ftypeLibrary; /* defined in xc/lib/font/FreeType/ftfuncs.c */

#define USE_FT_PS_NAMES 1

static
FT_Error PSType3_createOutlineGlyphs( FILE *out, struct ft2info *ti, unsigned long x11fontindex, const char *psglyphname )
{
  unsigned long  ftindex;
  FT_BBox        bbox;
  FT_Error       error;
  FT_Outline     outline;

  /* Remap X11 font index to FreeType font index */
  ftindex = FTRemap(ti->ttface, &ti->tf->mapping, x11fontindex);

  error = FT_Load_Glyph(ti->ttface, ftindex, (FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING));
  if( error )
  {
    fprintf(stderr, "PSType3_createOutlineGlyphs: FT_Load_Glyph() failure, error=%d\n", (int)error);
    return error;
  }

  outline = ti->ttface->glyph->outline;

  FT_Outline_Get_CBox(&outline, &bbox);

  fprintf(out, "/%s {\n", psglyphname);
  fprintf(out, "%ld 0 %ld %ld %ld %ld setcachedevice\n",
          (signed long)ti->ttface->glyph->metrics.horiAdvance,
          (long)bbox.xMin,
          (long)bbox.yMin,
          (long)bbox.xMax,
          (long)bbox.yMax);

  if( outline.n_contours > 0 )
  {
    long            i,
                    j,
                    k, k1,
                    cs, ce,
                    nguide,
                    contour_start,
                    contour_end,
                    last_point;
    Bool            first;
    FT_Vector      *vec;

    contour_start = ce = 0;

    vec        = outline.points;
    last_point = outline.n_points;

    i = j = k = 0;
    first = TRUE;

    while( i <= outline.contours[outline.n_contours - 1] )
    {
      contour_end = outline.contours[j];

      if( first )
      {
        fprintf(out, "%ld %ld moveto\n", vec[i].x, vec[i].y);
        contour_start = i;
        first = FALSE;
      }
      else if( outline.tags[i] & FT_CURVE_TAG_ON )
      {
        fprintf(out, "%ld %ld lineto\n", vec[i].x, vec[i].y);
      }
      else
      {
        Bool finished = FALSE;

        cs       = i-1;
        nguide   = 0;
        while( !finished )
        {
          if( i == contour_end+1 )
          {
            ce = contour_start;
            finished = TRUE;
          }
          else if( outline.tags[i] & FT_CURVE_TAG_ON )
          {
            ce = i;
            finished = TRUE;
          }
          else
          {
            i++;
            nguide++;
          }
        }

        switch( nguide )
        {
          case 0: 
              fprintf(out, "%ld %ld lineto\n", vec[ce].x, vec[ce].y);
              break;

          case 1:
              fprintf(out, "%ld %ld %ld %ld %ld %ld curveto\n",
                      (vec[cs].x+2*vec[cs+1].x)/3,
                      (vec[cs].y+2*vec[cs+1].y)/3,
                      (2*vec[cs+1].x+vec[ce].x)/3,
                      (2*vec[cs+1].y+vec[ce].y)/3,
                      vec[ce].x, vec[ce].y);
              break;

          case 2:
              fprintf(out, "%ld %ld %ld %ld %ld %ld curveto\n",
                      (-vec[cs].x+4*vec[cs+1].x)/3,
                      (-vec[cs].y+4*vec[cs+1].y)/3,
                      (4*vec[cs+2].x-vec[ce].x)/3,
                      (4*vec[cs+2].y-vec[ce].y)/3,
                      vec[ce].x, vec[ce].y);
              break;

          case 3:
              fprintf(out, "%ld %ld %ld %ld %ld %ld curveto\n",
                      (vec[cs].x+2*vec[cs+1].x)/3,
                      (vec[cs].y+2*vec[cs+1].y)/3,
                      (5*vec[cs+1].x+vec[cs+2].x)/6,
                      (5*vec[cs+1].y+vec[cs+2].y)/6,
                      (vec[cs+1].x+vec[cs+2].x)/2,
                      (vec[cs+1].y+vec[cs+2].y)/2);

              fprintf(out, "%ld %ld %ld %ld %ld %ld curveto\n",
                      (vec[cs+1].x+5*vec[cs+2].x)/6,
                      (vec[cs+1].y+5*vec[cs+2].y)/6,
                      (5*vec[cs+2].x+vec[cs+3].x)/6,
                      (5*vec[cs+2].y+vec[cs+3].y)/6,
                      (vec[cs+3].x+vec[cs+2].x)/2,
                      (vec[cs+3].y+vec[cs+2].y)/2);

              fprintf(out, "%ld %ld %ld %ld %ld %ld curveto\n",
                      (vec[cs+2].x+5*vec[cs+3].x)/6,
                      (vec[cs+2].y+5*vec[cs+3].y)/6,
                      (2*vec[cs+3].x+vec[ce].x)/3,
                      (2*vec[cs+3].y+vec[ce].y)/3,
                      vec[ce].x, vec[ce].y);
              break;

          default: /* anything |nguide > 3| */
              k1 = cs + nguide;

              fprintf(out, "%ld %ld %ld %ld %ld %ld curveto\n",
                      (vec[cs].x+2*vec[cs+1].x)/3,
                      (vec[cs].y+2*vec[cs+1].y)/3,
                      (5*vec[cs+1].x+vec[cs+2].x)/6,
                      (5*vec[cs+1].y+vec[cs+2].y)/6,
                      (vec[cs+1].x+vec[cs+2].x)/2,
                      (vec[cs+1].y+vec[cs+2].y)/2);

              for( k = cs+2 ; k <= k1-1 ; k++ )
              {
                fprintf(out, "%ld %ld %ld %ld %ld %ld curveto\n",
                        (vec[k-1].x+5*vec[k].x)/6,
                        (vec[k-1].y+5*vec[k].y)/6,
                        (5*vec[k].x+vec[k+1].x)/6,
                        (5*vec[k].y+vec[k+1].y)/6,
                        (vec[k].x+vec[k+1].x)/2,
                        (vec[k].y+vec[k+1].y)/2);
              }

              fprintf(out, "%ld %ld %ld %ld %ld %ld curveto\n",
                      (vec[k1-1].x+5*vec[k1].x)/6,
                      (vec[k1-1].y+5*vec[k1].y)/6,
                      (2*vec[k1].x+vec[ce].x)/3,
                      (2*vec[k1].y+vec[ce].y)/3,
                      vec[ce].x, vec[ce].y);
              break;
        }
      }

      if( i >= contour_end )
      {
        fprintf(out, "closepath\n");
        first = TRUE;
        i = contour_end + 1;
        j++;
      }
      else
      {
        i++;
      }
    }
  }

  fprintf(out, "fill } bind def\n");

  return 0;
}

#ifdef USE_FT_INTERNALS
static FT_BBox *
FT_Get_PS_Font_BBox( FT_Face face )
{
  const char *driver_name;
  FT_BBox    *font_bbox = NULL;

  if ( face && face->driver && face->driver->root.clazz )
  {
    driver_name = face->driver->root.clazz->module_name;
    if ( ft_strcmp( driver_name, "type1" ) == 0 )
      font_bbox = &(((T1_Face)face)->type1.font_bbox);
    else if ( ft_strcmp( driver_name, "t1cid" ) == 0 )
      font_bbox = &(((CID_Face)face)->cid.font_bbox);
    else if ( ft_strcmp( driver_name, "type42" ) == 0 )
      font_bbox = &(((T42_Face)face)->type1.font_bbox);
  }
  
  return font_bbox;
}
#endif /* USE_FT_INTERNALS */

static
int PSType3_generateOutlineFont(FILE *out, const char *psfontname, struct ft2info *ti, long block_offset)
{
        long   i;
        double scaler;
  const int    numchars = 256;
#ifdef USE_FT_PS_NAMES
        int    linewidth = 0;
#endif /* USE_FT_PS_NAMES */

  fprintf(out, "%%%%BeginFont: %s\n", psfontname);
  fprintf(out, "22 dict begin\n");
  fprintf(out, "/FontType 3 def\n");
  fprintf(out, "/StrokeWidth 0 def\n");
  fprintf(out, "/PaintType 0 def\n");
  fprintf(out, "/FontName (%s) def\n",     psfontname);
  fprintf(out, "/FontInfo 9 dict dup begin\n");
  fprintf(out, "  /FullName (%s) def\n",   ti->nameid.full_name?ti->nameid.full_name:psfontname);
  fprintf(out, "  /Notice (%s) def\n",     ti->nameid.copyright?ti->nameid.copyright:"nothing here");
  fprintf(out, "  /FamilyName (%s) def\n", ti->nameid.family?ti->nameid.family:psfontname);
  fprintf(out, "  /Weight (%s) def\n",     ti->nameid.subfamily?ti->nameid.subfamily:"Regular");
  fprintf(out, "  /version (%s) def\n",    ti->nameid.version?ti->nameid.version:"0.1");

  if( ti->ttpostscript )
  {
    fprintf(out, "  /italicAngle %.9g def\n",     (double)ti->ttpostscript->italicAngle);
    fprintf(out, "  /underlineThickness %d def\n", (int)ti->ttpostscript->underlineThickness);
    fprintf(out, "  /underlinePosition %d def\n",  (int)ti->ttpostscript->underlinePosition);
    fprintf(out, "  /isFixedPitch %s def\n",       ((ti->ttpostscript->isFixedPitch)?("true"):("false")));
  }
  else
  {
    fprintf(out, "  /italicAngle %.9g def\n",      0.0);
    fprintf(out, "  /underlineThickness %d def\n", 100);
    fprintf(out, "  /underlinePosition %d def\n",  0);
    fprintf(out, "  /isFixedPitch false def\n");
  }

  fprintf(out, "end def\n");

  scaler = (1000.0 / (double)ti->ttface->units_per_EM) / 1000.0;
  fprintf(out, "/FontMatrix [%.9g 0 0 %.9g 0 0] def\n", scaler, scaler);

  if( ti->ttheader )
  {
    fprintf(out, "/FontBBox [%d %d %d %d] def\n",
            (int)ti->ttheader->xMin,
            (int)ti->ttheader->yMin,
            (int)ti->ttheader->xMax,
            (int)ti->ttheader->yMax);
  }
  else
  {
    FT_BBox *font_bbox = FT_Get_PS_Font_BBox(ti->ttface);
    fprintf(out, "/FontBBox [%d %d %d %d] def\n",
                 (int)font_bbox->xMin,
                 (int)font_bbox->yMin,
                 (int)font_bbox->xMax,
                 (int)font_bbox->yMax);
  }

  fprintf(out, "/Encoding [\n");
  for( i = 0 ; i < 256 ; i++ )
  {
#ifdef USE_FT_PS_NAMES
    char namebuf[256];
    PsOut_Get_FreeType_Glyph_Name(namebuf, ti->pFont, i+block_offset);
    linewidth += strlen(namebuf) + 2;
    fprintf(out, "/%s%s", namebuf, (linewidth > 70)?(linewidth = 0, "\n"):(" "));
#else
    fprintf(out, "/ch%02x%s", i, (((i % 10) == 9)?("\n"):(" ")));
#endif /* USE_FT_PS_NAMES */
  }
  fprintf(out, "] def\n");

  fprintf(out, "/CharProcs %d dict def CharProcs begin\n", (int)(numchars + 1));
  fprintf(out, "/.notdef {\n"
               "1000 0 0 0 0 0 setcachedevice\n"
               "fill } bind def\n");
  for( i = 0 ; i < numchars ; i++ )
  {
    char buf[32];
#ifdef USE_FT_PS_NAMES
    char namebuf[256];
    PsOut_Get_FreeType_Glyph_Name(namebuf, ti->pFont, i+block_offset);
    sprintf(buf, "%s ", namebuf);
#else
    sprintf(buf, "ch%02lx ", i);
#endif /* USE_FT_PS_NAMES */
    PSType3_createOutlineGlyphs(out, ti, i+block_offset, buf);
  }
  fprintf(out, "end\n"
               "/BuildGlyph {\n"
               "  exch /CharProcs get exch\n"
               "  2 copy known not {pop /.notdef} if get exec } bind def\n"
               "/BuildChar { 1 index /Encoding get exch get\n"
               "  1 index /Encoding get exec } bind def\n");
  fprintf(out, "currentdict end /%s exch definefont pop\n", psfontname);
  fprintf(out, "%%EndFont\n");

  return 0;
}

static
char *FT_Get_TT_NAME_ID(FT_Face ttface, int index)
{
  FT_SfntName  name;
  char        *s;

  if( index >= FT_Get_Sfnt_Name_Count(ttface) )
    return NULL;

  FT_Get_Sfnt_Name(ttface, index, &name);
  s = (char *)malloc(name.string_len+2);
  if( !s )
    return NULL;
  memcpy(s, (char *)name.string, name.string_len);
  s[name.string_len] = '\0';
  return s;
}

int PsOut_DownloadFreeType3(PsOutPtr self, const char *psfontname, FontPtr pFont, long block_offset)
{
  struct ft2info  cft2info = { 0 };
  struct ft2info *ti       = &cft2info;

  S_Flush(self);

  ti->tf     = (FTFontPtr)pFont->fontPrivate;
  ti->ttface = ti->tf->instance->face->face;
  ti->pFont  = pFont;
#ifdef DEBUG_gisburn
  fprintf(stderr, "# Downloading FT2 font filename='%s', ttface=%lx\n", ti->tf->instance->face->filename, (long)ti->ttface);
#endif /* DEBUG_gisburn */

  ti->nameid.full_name = FT_Get_TT_NAME_ID(ti->ttface, TT_NAME_ID_FULL_NAME);
  ti->nameid.copyright = FT_Get_TT_NAME_ID(ti->ttface, TT_NAME_ID_COPYRIGHT);
  ti->nameid.family    = FT_Get_TT_NAME_ID(ti->ttface, TT_NAME_ID_FONT_FAMILY);
  ti->nameid.subfamily = FT_Get_TT_NAME_ID(ti->ttface, TT_NAME_ID_FONT_SUBFAMILY);
  ti->nameid.version   = FT_Get_TT_NAME_ID(ti->ttface, TT_NAME_ID_VERSION_STRING);

  ti->ttheader     =     (TT_Header *)FT_Get_Sfnt_Table(ti->ttface, ft_sfnt_head);
  ti->ttpostscript = (TT_Postscript *)FT_Get_Sfnt_Table(ti->ttface, ft_sfnt_post);

  PSType3_generateOutlineFont(self->Fp, psfontname, ti, block_offset);

  free(ti->nameid.full_name);
  free(ti->nameid.copyright);
  free(ti->nameid.family);
  free(ti->nameid.subfamily);
  free(ti->nameid.version);

  S_Flush(self);

  return 0;
}


Index: Imakefile
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/Imakefile,v
retrieving revision 1.1.4.2
retrieving revision 1.1.4.3
diff -u -d -r1.1.4.2 -r1.1.4.3
--- a/Imakefile	5 Mar 2004 13:39:53 -0000	1.1.4.2
+++ b/Imakefile	21 Apr 2004 10:03:37 -0000	1.1.4.3
@@ -1,11 +1,21 @@
-XCOMM $Xorg: Imakefile,v 1.4 2000/08/17 19:48:09 cpqbld Exp $
-
-
+XCOMM $Xorg: Imakefile,v 1.5 2001/03/14 18:26:56 pookie Exp $
 
+#include <Server.tmpl>
 
-XCOMM $XFree86: xc/programs/Xserver/Xprint/ps/Imakefile,v 1.8 2001/12/21 21:02:05 dawes Exp $
+#if BuildFreeType
+FT2SOURCEDIR    = $(TOP)/extras/freetype2/src
+FT2INCDIR       = $(TOP)/extras/freetype2/include
+FT2INCS         = -I$(FT2INCDIR) \
+                  -I$(FT2SOURCEDIR)/type42
+TTF2PT1OURCEDIR = $(TOP)/extras/ttf2pt1
+FT_DEFINES      = -DXP_USE_FREETYPE
+FTSRCS          = psout_ft.c psout_ftpstype1.c psout_ftpstype3.c PsFTFonts.c
+FTOBJS          = psout_ft.o psout_ftpstype1.o psout_ftpstype3.o PsFTFonts.o
 
-#include <Server.tmpl>
+TTF2PT1SRCS = ft.c pt1.c runt1asm.c ttf2pt1.c
+TTF2PT1OBJS = ft.o pt1.o runt1asm.o ttf2pt1.o
+TTF2PT1_DEFINES = -DUSE_FREETYPE -DXP_ONLY_BLOCKS
+#endif /* BuildFreeType */
 
 SRCS1 =	PsInit.c PsPrint.c PsGC.c PsMisc.c PsSpans.c PsArea.c PsPixel.c \
         PsLine.c PsPolygon.c PsArc.c PsText.c PsWindow.c PsFonts.c \
@@ -15,15 +25,45 @@
         PsLine.o PsPolygon.o PsArc.o PsText.o PsWindow.o PsFonts.o \
         PsAttr.o PsAttVal.o PsColor.o PsPixmap.o psout.o PsCache.o
 
-SRCS =	$(SRCS1)
+SRCS = $(SRCS1) $(TTF2PT1SRCS) $(FTSRCS)
 
-OBJS = $(OBJS1)
+OBJS = $(OBJS1) $(TTF2PT1OBJS) $(FTOBJS)
 
-   DEFINES = -UXFree86LOADER -DXP_PSTEXT -D_XP_PRINT_SERVER_ -DBM_CACHE
+#if BuildFreeType
+LinkSourceFile(ttf2pt1.c,$(TTF2PT1OURCEDIR)/)
+LinkSourceFile(pt1.c,$(TTF2PT1OURCEDIR)/)
+LinkSourceFile(pt1.h,$(TTF2PT1OURCEDIR)/)
+LinkSourceFile(ft.c,$(TTF2PT1OURCEDIR)/)
+LinkSourceFile(runt1asm.c,$(TTF2PT1OURCEDIR)/)
+LinkSourceFile(t1asm.c,$(TTF2PT1OURCEDIR)/)
+LinkSourceFile(ttf.h,$(TTF2PT1OURCEDIR)/)
+LinkSourceFile(global.h,$(TTF2PT1OURCEDIR)/)
+LinkSourceFile(version.h,$(TTF2PT1OURCEDIR)/)
+#endif /* BuildFreeType */
+
+#ifdef XVendorString
+VENDORSTRING = XVendorString
+   VENDOR_STRING = -DVENDOR_STRING=\"$(VENDORSTRING)\"
+#endif
+
+#ifdef XVendorRelease
+VENDORRELEASE = XVendorRelease
+   VENDOR_RELEASE = -DVENDOR_RELEASE="$(VENDORRELEASE)"
+#endif
+
+VENDOR_DEFINES = $(VENDOR_STRING) $(VENDOR_RELEASE)
+
+XCOMM DEFINES = -DPIXPRIV
+
+XCOMM BM_CACHE disabled because it causes PostScript errors
+XCOMM (see http://xprint.mozdev.org/bugs/show_bug.cgi?id=1489)
+XCOMM   DEFINES = -DXP_PSTEXT -DBM_CACHE $(VENDOR_DEFINES) $(TTF2PT1_DEFINES) $(FT_DEFINES)
+   DEFINES = -UXFree86LOADER -DXP_PSTEXT -D_XP_PRINT_SERVER_ $(VENDOR_DEFINES) $(TTF2PT1_DEFINES) $(FT_DEFINES)
 
    INCLUDES = -I. -I../../cfb -I../../mi -I../../mfb -I$(LIBSRC) \
-	      -I$(XINCLUDESRC) -I../../include -I.. -I$(TOP)/include \
-	      -I$(EXTINCSRC) -I$(FONTINCSRC) -I$(FONTLIBSRC)/include
+             -I$(XINCLUDESRC) -I../../include -I.. -I$(TOP)/include \
+             -I$(EXTINCSRC) -I$(FONTINCSRC) -I$(FONTLIBSRC)/include \
+             $(FT2INCS) -I../../../../lib/font/FreeType
 
    LINTLIBS = $(TOP)/server/dix/llib-ldix.ln $(TOP)/server/os/llib-los.ln \
 	      $(TOP)/server/ddx/mfb/llib-lmfb.ln \

Index: Ps.h
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/Ps.h,v
retrieving revision 1.1.4.3
retrieving revision 1.1.4.4
diff -u -d -r1.1.4.3 -r1.1.4.4
--- a/Ps.h	5 Mar 2004 13:39:54 -0000	1.1.4.3
+++ b/Ps.h	21 Apr 2004 10:03:37 -0000	1.1.4.4
@@ -7,6 +7,7 @@
 documentation for any purpose is hereby granted without fee, provided that
 the above copyright notice appear in all copies and that both that
 copyright notice and this permission notice appear in supporting
+documentation.
 
 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.
@@ -73,7 +74,6 @@
 **    *********************************************************
 ** 
 ********************************************************************/
-/* $XFree86: xc/programs/Xserver/Xprint/ps/Ps.h,v 1.13 2001/12/21 21:02:05 dawes Exp $ */
 
 #ifndef _PS_H_
 #define _PS_H_
@@ -113,6 +113,7 @@
 #include <X11/Xresource.h>
 #include "attributes.h"
 
+
 /*
  *  Public index variables from PsInit.c
  */
@@ -249,6 +250,63 @@
   Bool        (*DestroyWindow)(WindowPtr);
 } PsScreenPrivRec, *PsScreenPrivPtr;
 
+typedef struct PsFontTypeInfoRec PsFontTypeInfoRec;
+
+/* Structure to hold information about one font on disk
+ * Notes:
+ * - multiple XLFD names can refer to the same |PsFontTypeInfoRec| (if
+ *   they all use the same font on the disk)
+ * - the FreeType font download code uses multiple |PsFontTypeInfoRec|
+ *   records for one font on disk if they differ in the encoding being
+ *   used (this is an exception from the
+ *   'one-|PsFontTypeInfoRec|-per-font-on-disk'-design; maybe it it is better
+ *   to rework that in a later step and add a new per-encoding structure). 
+ */
+struct PsFontTypeInfoRec
+{
+  PsFontTypeInfoRec *next;                    /* Next record in list...         */
+  char              *adobe_ps_name;           /* PostScript font name (from the
+                                               * "_ADOBE_POSTSCRIPT_FONTNAME" atom) */
+  char              *download_ps_name;        /* PostScript font name used for font download */
+  char              *filename;                /* File name of font              */
+#ifdef XP_USE_FREETYPE
+  char              *ft_download_encoding;    /* encoding used for download     */
+  PsFTDownloadFontType ft_download_font_type; /* PS font type used for download (e.g. Type1/Type3/CID/etc.) */
+#endif /* XP_USE_FREETYPE */
+  int                is_iso_encoding;         /* Is this font encoded in ISO Latin 1 ? */
+  int                font_type;               /* See PSFTI_FONT_TYPE_* below... */
+  Bool               downloadableFont;        /* Font can be downloaded         */
+  Bool               alreadyDownloaded[256];  /* Font has been downloaded (for 256 8bit "sub"-font) */
+};
+
+#define PSFTI_FONT_TYPE_OTHER        (0)
+#define PSFTI_FONT_TYPE_PMF          (1)
+#define PSFTI_FONT_TYPE_PS_TYPE1_PFA (2)
+#define PSFTI_FONT_TYPE_PS_TYPE1_PFB (3)
+#define PSFTI_FONT_TYPE_TRUETYPE     (4)
+/* PSFTI_FONT_TYPE_FREETYPE is means the font is handled by the freetype engine */
+#define PSFTI_FONT_TYPE_FREETYPE     (5)
+
+typedef struct PsFontInfoRec PsFontInfoRec;
+
+/* Structure which represents our context info for a single XLFD font
+ * Note that multiple |PsFontInfoRec| records can share the same
+ * |PsFontTypeInfoRec| record - the |PsFontInfoRec| records represent
+ * different appearances of the same font on disk(=|PsFontTypeInfoRec|)).
+ */
+struct PsFontInfoRec
+{
+  PsFontInfoRec     *next;          /* Next record in list...             */
+  /* |font| and |font_fontPrivate| are used by |PsFindFontInfoRec()| to
+   * identify a font */
+  FontPtr            font;          /* The font this record is for        */
+  pointer            font_fontPrivate;
+  PsFontTypeInfoRec *ftir;          /* Record about the font file on disk */
+  const char        *dfl_name;      /* XLFD for this font                 */
+  int                size;          /* Font size. Use |mtx| if |size==0|  */
+  float              mtx[4];        /* Transformation matrix (see |size|) */
+};
+
 typedef struct
 {
   char              *jobFileName;
@@ -259,6 +317,8 @@
   ClientPtr          getDocClient;
   int                getDocBufSize;
   PsOutPtr           pPsOut;
+  PsFontTypeInfoRec *fontTypeInfoRecords;
+  PsFontInfoRec     *fontInfoRecords;
 } PsContextPrivRec, *PsContextPrivPtr;
 
 typedef struct
@@ -291,6 +351,7 @@
 
 extern Bool InitializePsDriver(int ndx, ScreenPtr pScreen, int argc,
     char **argv);
+static Bool         PsDestroyContext(XpContextPtr pCon);
 extern XpContextPtr PsGetContextFromWindow(WindowPtr win);
 
 /*
@@ -314,6 +375,10 @@
  */
 
 extern Bool PsCreateGC(GCPtr pGC);
+static int  PsGetDrawablePrivateStuff(DrawablePtr pDrawable, GC *gc,
+                                      unsigned long *valid, PsOutPtr *psOut,
+                                      ColormapPtr *cMap);
+extern PsContextPrivPtr PsGetPsContextPriv( DrawablePtr pDrawable );
 extern int  PsUpdateDrawableGC(GCPtr pGC, DrawablePtr pDrawable,
                                PsOutPtr *psOut, ColormapPtr *cMap);
 extern void PsValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable);
@@ -366,9 +431,8 @@
 extern void PsPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
                        int x, int y, int w, int h, int leftPad, int format,
                        char *pImage);
-extern void PsPutImageMask(DrawablePtr pDrawable, GCPtr pGC, int depth,
-                           int x, int y, int w, int h, int leftPad, int format,
-                           char *pImage);
+extern void PsPutImageMask(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
+                           int w, int h, int leftPad, int format, char *pImage);
 extern RegionPtr PsCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
                             int srcx, int srcy, int width, int height,
                             int dstx, int dsty);
@@ -456,7 +520,19 @@
 extern char *PsGetFontName(FontPtr pFont);
 extern int PsGetFontSize(FontPtr pFont, float *mtx);
 extern char *PsGetPSFontName(FontPtr pFont);
+extern char *PsGetPSFaceOrFontName(FontPtr pFont);
 extern int PsIsISOLatin1Encoding(FontPtr pFont);
+extern char *PsGetEncodingName(FontPtr pFont);
+extern PsFontInfoRec *PsGetFontInfoRec(DrawablePtr pDrawable, FontPtr pFont);
+extern void PsFreeFontInfoRecords(PsContextPrivPtr priv);
+extern PsFTDownloadFontType PsGetFTDownloadFontType(void);
+
+/*
+ *  Functions in PsFTFonts.c
+ */
+ 
+extern char *PsGetFTFontFileName(FontPtr pFont);
+extern Bool  PsIsFreeTypeFont(FontPtr pFont);
 
 /*
  *  Functions in PsAttr.c
@@ -503,14 +579,4 @@
 extern PsElmPtr PsCloneFillElementList(int nElms, PsElmPtr elms);
 extern void PsDestroyFillElementList(int nElms, PsElmPtr elms);
 
-/*
- *  Functions in PsCache.c
- */
-
-#ifdef BM_CACHE
-extern int PsBmIsImageCached(int gWidth, int gHeight, char *pBuffer);
-extern int PsBmPutImageInCache(int gWidth, int gHeight, char *pBuffer);
-extern void PsBmClearImageCache(void);
-#endif
-
 #endif  /* _PS_H_ */

Index: PsArea.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/PsArea.c,v
retrieving revision 1.1.4.1
retrieving revision 1.1.4.2
diff -u -d -r1.1.4.1 -r1.1.4.2
--- a/PsArea.c	17 Nov 2003 19:03:44 -0000	1.1.4.1
+++ b/PsArea.c	21 Apr 2004 10:03:37 -0000	1.1.4.2
@@ -228,7 +228,7 @@
   return;
 }
 
-static void
+void
 PsPutScaledImageIM(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
            int w, int h, int leftPad, int format, int imageRes, char *pImage)
 {
@@ -269,9 +269,9 @@
     ColormapPtr  cMap;
     int          pageRes, sw, sh;
 #ifdef BM_CACHE
-    long   cache_id = 0;
+    long	 cache_id = 0;
 #endif
-    
+
     if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) return;
     if (!imageRes) {
         sw = w;
@@ -296,100 +296,100 @@
 
       PsOut_BeginImageCache(psOut, cache_id);
 #endif
-    if( depth==24 )
-    {
-      PsOut_BeginImageIM(psOut, 0, 0, x, y, w, h, sw, sh, 3);
-      if( format==XYPixmap )
+      if( depth==24 )
       {
-        int   rowsiz = PixmapBytePad(w, depth);
-        char *planes[3];
-        planes[0] = pImage;
-        planes[1] = &pImage[rowsiz*h];
-        planes[2] = &pImage[rowsiz*h*2];
-        for( r=0 ; r<h ; r++ )
+        PsOut_BeginImageIM(psOut, 0, 0, x, y, w, h, sw, sh, 3);
+        if( format==XYPixmap )
         {
-          char *pt[3];
-          for( i=0 ; i<3 ;  i++ ) pt[i] = &planes[i][rowsiz*r];
-          for( c=0 ; c<w ; c++ )
+          int   rowsiz = PixmapBytePad(w, depth);
+          char *planes[3];
+          planes[0] = pImage;
+          planes[1] = &pImage[rowsiz*h];
+          planes[2] = &pImage[rowsiz*h*2];
+          for( r=0 ; r<h ; r++ )
           {
-            for( i=0 ; i<3 ; i++ )
-              { PsOut_OutImageBytes(psOut, 1, &pt[i][c]); pt[i]++; }
+            char *pt[3];
+            for( i=0 ; i<3 ;  i++ ) pt[i] = &planes[i][rowsiz*r];
+            for( c=0 ; c<w ; c++ )
+            {
+              for( i=0 ; i<3 ; i++ )
+                { PsOut_OutImageBytes(psOut, 1, &pt[i][c]); pt[i]++; }
+            }
+          }
+        }
+        else if( format==ZPixmap )
+        {
+          int  rowsiz = PixmapBytePad(w, depth);
+          for( r=0 ; r<h ; r++ )
+          {
+            char *pt = &pImage[rowsiz*r];
+            for( c=0 ; c<w ; c++,pt+=4 )
+            {
+              if( swap )
+              {
+                char tmp[4];
+                tmp[0] = pt[3]; tmp[1] = pt[2]; tmp[2] = pt[1]; tmp[3] = pt[0];
+                PsOut_OutImageBytes(psOut, 3, &tmp[1]);
+              }
+              else
+                PsOut_OutImageBytes(psOut, 3, &pt[1]);
+            }
           }
         }
+        else goto error;
+        PsOut_EndImage(psOut);
       }
-      else if( format==ZPixmap )
+      else if( depth==8 )
       {
         int  rowsiz = PixmapBytePad(w, depth);
+        PsOut_BeginImageIM(psOut, 0, 0, x, y, w, h, sw, sh, 3);
         for( r=0 ; r<h ; r++ )
         {
           char *pt = &pImage[rowsiz*r];
-          for( c=0 ; c<w ; c++,pt+=4 )
+          for( c=0 ; c<w ; c++,pt++ )
           {
+            int   val = PsGetPixelColor(cMap, (int)(*pt)&0xFF);
+            char *ipt = (char *)&val;
             if( swap )
             {
               char tmp[4];
-              tmp[0] = pt[3]; tmp[1] = pt[2]; tmp[2] = pt[1]; tmp[3] = pt[0];
+              tmp[0] = ipt[3]; tmp[1] = ipt[2]; tmp[2] = ipt[1]; tmp[3] = ipt[0];
               PsOut_OutImageBytes(psOut, 3, &tmp[1]);
             }
             else
-              PsOut_OutImageBytes(psOut, 3, &pt[1]);
-          }
-        }
-      }
-      else goto error;
-      PsOut_EndImage(psOut);
-    }
-    else if( depth==8 )
-    {
-      int  rowsiz = PixmapBytePad(w, depth);
-      PsOut_BeginImageIM(psOut, 0, 0, x, y, w, h, sw, sh, 3);
-      for( r=0 ; r<h ; r++ )
-      {
-        char *pt = &pImage[rowsiz*r];
-        for( c=0 ; c<w ; c++,pt++ )
-        {
-          int   val = PsGetPixelColor(cMap, (int)(*pt)&0xFF);
-          char *ipt = (char *)&val;
-          if( swap )
-          {
-            char tmp[4];
-            tmp[0] = ipt[3]; tmp[1] = ipt[2]; tmp[2] = ipt[1]; tmp[3] = ipt[0];
-            PsOut_OutImageBytes(psOut, 3, &tmp[1]);
+              PsOut_OutImageBytes(psOut, 3, &ipt[1]);
           }
-          else
-            PsOut_OutImageBytes(psOut, 3, &ipt[1]);
         }
+        PsOut_EndImage(psOut);
       }
-      PsOut_EndImage(psOut);
-    }
-    else if( depth==1 )
-    {
+      else if( depth==1 )
       {
-        int  rowsiz = BitmapBytePad(w);
-        int  psrsiz = (w+7)/8;
-        PsOut_BeginImageIM(psOut, PsGetPixelColor(cMap, pGC->bgPixel),
-                         PsGetPixelColor(cMap, pGC->fgPixel),
-                         x, y, w, h, sw, sh, 1);
-        for( r=0 ; r<h ; r++ )
         {
-          char *pt = &pImage[rowsiz*r];
-          for( i=0 ; i<psrsiz ; i++ )
+          int  rowsiz = BitmapBytePad(w);
+          int  psrsiz = (w+7)/8;
+          PsOut_BeginImageIM(psOut, PsGetPixelColor(cMap, pGC->bgPixel),
+                           PsGetPixelColor(cMap, pGC->fgPixel),
+                           x, y, w, h, sw, sh, 1);
+          for( r=0 ; r<h ; r++ )
           {
-            int  iv_, iv = (int)pt[i]&0xFF;
-            char c;
-            if( swap )
-              { for( j=0,iv_=0 ; j<8 ; j++ ) iv_ |= (((iv>>j)&1)<<(7-j)); }
-            else
-              iv_ = iv;
-            c = iv_;
-            PsOut_OutImageBytes(psOut, 1, &c);
+            char *pt = &pImage[rowsiz*r];
+            for( i=0 ; i<psrsiz ; i++ )
+            {
+              int  iv_, iv = (int)pt[i]&0xFF;
+              char c;
+              if( swap )
+                { for( j=0,iv_=0 ; j<8 ; j++ ) iv_ |= (((iv>>j)&1)<<(7-j)); }
+              else
+                iv_ = iv;
+              c = iv_;
+              PsOut_OutImageBytes(psOut, 1, &c);
+            }
           }
+          PsOut_EndImage(psOut);
         }
-        PsOut_EndImage(psOut);
       }
-    }
 #ifdef BM_CACHE
-    PsOut_EndImageCache(psOut);
+      PsOut_EndImageCache(psOut);
     }
     PsOut_ImageCache(psOut, x, y, cache_id, PsGetPixelColor(cMap, pGC->bgPixel),
                            PsGetPixelColor(cMap, pGC->fgPixel));

Index: PsAttVal.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/PsAttVal.c,v
retrieving revision 1.1.4.2
retrieving revision 1.1.4.3
diff -u -d -r1.1.4.2 -r1.1.4.3
--- a/PsAttVal.c	5 Mar 2004 13:39:54 -0000	1.1.4.2
+++ b/PsAttVal.c	21 Apr 2004 10:03:37 -0000	1.1.4.3
@@ -32,7 +32,6 @@
 dealings in this Software without prior written authorization from said
 copyright holders.
 */
-/* $XFree86: xc/programs/Xserver/Xprint/ps/PsAttVal.c,v 1.4 2001/01/17 22:36:31 dawes Exp $ */
 
 #include "Ps.h"
 #include "AttrValid.h"
@@ -73,7 +72,16 @@
 };
 
 static unsigned long ValidPrinterResolutionsCards[] = {
+    75,
+    100,
+    120,
+    150,
+    180,
+    200,
+    240,
     300,
+    360,
+    400,
     600,
     720,
     940,
@@ -86,7 +94,20 @@
 };
 
 static unsigned long DefaultPrinterResolutionsCards[] = {
-    300
+     75,
+     100,
+     120,
+     150,
+     180,
+     200,
+     240,
+     300,
+     360,
+     400,
+     600,
+     720,
+     940,
+     1200
 };
 static XpOidCardList DefaultPrinterResolutions = {
     DefaultPrinterResolutionsCards, XpNumber(DefaultPrinterResolutionsCards)
@@ -143,13 +164,6 @@
     DefaultEmbeddedFormatsSupportedFmts, XpNumber(DefaultEmbeddedFormatsSupportedFmts)
 };
 
-/*
-**	So filtered printers that accept other raw formats can be
-**	used with this driver.
-**
-**		Noah Roberts (jik-)
-*/
-#if 0
 static XpOidDocFmt ValidRawFormatsSupportedFmts[] = {
     { "Postscript", "2", NULL }
     
@@ -157,7 +171,6 @@
 static XpOidDocFmtList ValidRawFormatsSupported = {
     ValidRawFormatsSupportedFmts, XpNumber(ValidRawFormatsSupportedFmts)
 };
-#endif
 
 static XpOidDocFmt DefaultRawFormatsSupportedFmts[] = {
     { "Postscript", "2", NULL }
@@ -178,12 +191,74 @@
 };
 
 static XpOid ValidMediumSizesOids[] = {
+    xpoid_val_medium_size_iso_a0,
+    xpoid_val_medium_size_iso_a1,
+    xpoid_val_medium_size_iso_a2,
+    xpoid_val_medium_size_iso_a3,
     xpoid_val_medium_size_iso_a4,
+    xpoid_val_medium_size_iso_a5,
+    xpoid_val_medium_size_iso_a6,
+    xpoid_val_medium_size_iso_a7,
+    xpoid_val_medium_size_iso_a8,
+    xpoid_val_medium_size_iso_a9,
+    xpoid_val_medium_size_iso_a10,
+    xpoid_val_medium_size_iso_b0,
+    xpoid_val_medium_size_iso_b1,
+    xpoid_val_medium_size_iso_b2,
+    xpoid_val_medium_size_iso_b3,
+    xpoid_val_medium_size_iso_b4,
+    xpoid_val_medium_size_iso_b5,
+    xpoid_val_medium_size_iso_b6,
+    xpoid_val_medium_size_iso_b7,
+    xpoid_val_medium_size_iso_b8,
+    xpoid_val_medium_size_iso_b9,
+    xpoid_val_medium_size_iso_b10,
     xpoid_val_medium_size_na_letter,
     xpoid_val_medium_size_na_legal,
     xpoid_val_medium_size_executive,
+    xpoid_val_medium_size_folio,
+    xpoid_val_medium_size_invoice,
+    xpoid_val_medium_size_ledger,
+    xpoid_val_medium_size_quarto,
+    xpoid_val_medium_size_iso_c3,
+    xpoid_val_medium_size_iso_c4,
+    xpoid_val_medium_size_iso_c5,
+    xpoid_val_medium_size_iso_c6,
     xpoid_val_medium_size_iso_designated_long,
-    xpoid_val_medium_size_na_number_10_envelope
+    xpoid_val_medium_size_na_10x13_envelope,
+    xpoid_val_medium_size_na_9x12_envelope,
+    xpoid_val_medium_size_na_number_10_envelope,
+    xpoid_val_medium_size_na_7x9_envelope,
+    xpoid_val_medium_size_na_9x11_envelope,
+    xpoid_val_medium_size_na_10x14_envelope,
+    xpoid_val_medium_size_na_number_9_envelope,
+    xpoid_val_medium_size_na_6x9_envelope,
+    xpoid_val_medium_size_na_10x15_envelope,
+    xpoid_val_medium_size_monarch_envelope,
+    xpoid_val_medium_size_a,
+    xpoid_val_medium_size_b,
+    xpoid_val_medium_size_c,
+    xpoid_val_medium_size_d,
+    xpoid_val_medium_size_e,
+    xpoid_val_medium_size_jis_b0,
+    xpoid_val_medium_size_jis_b1,
+    xpoid_val_medium_size_jis_b2,
+    xpoid_val_medium_size_jis_b3,
+    xpoid_val_medium_size_jis_b4,
+    xpoid_val_medium_size_jis_b5,
+    xpoid_val_medium_size_jis_b6,
+    xpoid_val_medium_size_jis_b7,
+    xpoid_val_medium_size_jis_b8,
+    xpoid_val_medium_size_jis_b9,
+    xpoid_val_medium_size_jis_b10,
+    xpoid_val_medium_size_hp_2x_postcard,
+    xpoid_val_medium_size_hp_european_edp,
+    xpoid_val_medium_size_hp_mini,
+    xpoid_val_medium_size_hp_postcard,
+    xpoid_val_medium_size_hp_tabloid,
+    xpoid_val_medium_size_hp_us_edp,
+    xpoid_val_medium_size_hp_us_government_legal,
+    xpoid_val_medium_size_hp_us_government_letter,
 };
 static XpOidList ValidMediumSizes = {
     ValidMediumSizesOids, XpNumber(ValidMediumSizesOids)
@@ -205,7 +280,7 @@
     &ValidPrinterResolutions, &DefaultPrinterResolutions,
     &ValidEmbeddedFormatsSupported, &DefaultEmbeddedFormatsSupported,
     &ValidListfontsModes, &DefaultListfontsModes,
-    NULL /* Any raw format specified (NR)*/, &DefaultRawFormatsSupported,
+    &ValidRawFormatsSupported, &DefaultRawFormatsSupported,
     &ValidSetupProviso,
     &DefaultDocumentFormat
 };

Index: PsAttr.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/PsAttr.c,v
retrieving revision 1.1.4.2
retrieving revision 1.1.4.3
diff -u -d -r1.1.4.2 -r1.1.4.3
--- a/PsAttr.c	5 Mar 2004 13:39:54 -0000	1.1.4.2
+++ b/PsAttr.c	21 Apr 2004 10:03:37 -0000	1.1.4.3
@@ -57,7 +57,6 @@
  * or other dealings in this Software without prior written authorization
  * from said copyright holders.
  */
-/* $XFree86: xc/programs/Xserver/Xprint/ps/PsAttr.c,v 1.4 2001/01/17 22:36:32 dawes Exp $ */
 
 /*******************************************************************
 **
@@ -76,6 +75,7 @@
 ********************************************************************/
 
 #include "Ps.h"
+#include "attributes.h"
 
 char *
 PsGetAttributes(

Index: PsCache.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/PsCache.c,v
retrieving revision 1.1.4.1
retrieving revision 1.1.4.2
diff -u -d -r1.1.4.1 -r1.1.4.2
--- a/PsCache.c	17 Nov 2003 19:03:44 -0000	1.1.4.1
+++ b/PsCache.c	21 Apr 2004 10:03:37 -0000	1.1.4.2
@@ -79,21 +79,21 @@
 #include "fntfil.h"
 #include "fntfilst.h"
 
-#define  GET  0
-#define  RESET    1
+#define  GET	0
+#define  RESET	1
 
 struct bm_cache_list {
-  struct bm_cache_list *next;
-  struct bm_cache_list *prev;
+	struct bm_cache_list *next;
+	struct bm_cache_list *prev;
         int                   height;
-  long                  id;
+	long	              id;
         char                 *pBuffer;
 };
 
 struct bm_cache_head {
-  struct bm_cache_list *head;
-  int           width;
-  struct bm_cache_head *next;
+	struct bm_cache_list *head;
+	int		      width;
+	struct bm_cache_head *next;
         struct bm_cache_head *prev;
 };
 
@@ -106,14 +106,14 @@
 
     if(func == RESET)
     {
-  unique_id = 0;
-  return 0;
+	unique_id = 0;
+	return 0;
     }
     else
-  return ++unique_id;
+	return ++unique_id;
 }
 
-int
+int 
 PsBmIsImageCached(
     int gWidth,
     int gHeight,
@@ -126,28 +126,28 @@
     {
         if(pList->width == gWidth)
         {
-      struct bm_cache_list *pItem = pList->head;
+	    struct bm_cache_list *pItem = pList->head;
 
-      while(pItem != NULL)
-      {
-          if(pItem->height == gHeight)
-          {
-          int length = 4*(gWidth/32+(gWidth%32!=0))*gHeight;
+	    while(pItem != NULL)
+	    {
+	        if(pItem->height == gHeight)
+	        {
+		    int length = 4*(gWidth/32+(gWidth%32!=0))*gHeight;
 
-              if(!memcmp(pItem->pBuffer, pBuffer, sizeof(char)*length))
-              {
-              return_val = pItem->id;
-              break;
-              }
-          }
-      else if(pItem->height > gHeight)
-          break;
+	            if(!memcmp(pItem->pBuffer, pBuffer, sizeof(char)*length))
+	            {
+		        return_val = pItem->id;
+		        break;
+	            }
+	        }
+		else if(pItem->height > gHeight)
+		    break;
 
-          pItem = pItem->next;
-      }
+	        pItem = pItem->next;
+	    }
         }
-  else if(pList->width > gWidth)
-      break;
+	else if(pList->width > gWidth)
+	    break;
 
         pList = pList->next;
     }
@@ -180,39 +180,39 @@
     while(pList != NULL)
     {
         if(pList->width == gWidth)
-  {
-      struct bm_cache_list *pItem = pList->head;
+	{
+	    struct bm_cache_list *pItem = pList->head;
 
-      while(pItem != NULL)
-      {
-      if(pItem->height >= gHeight)
-      {
-          pNew->next = pItem;
-          pNew->prev = pItem->prev;
-          if(pItem->prev != NULL)
-             pItem->prev->next = pNew;
+	    while(pItem != NULL)
+	    {
+		if(pItem->height >= gHeight)
+		{
+		    pNew->next = pItem;
+		    pNew->prev = pItem->prev;
+		    if(pItem->prev != NULL)
+		       pItem->prev->next = pNew;
                     else
-             pList->head = pNew;
+		       pList->head = pNew;
                     pItem->prev = pNew;
 
-          return_val = pNew->id;
+		    return_val = pNew->id;
 
-          break;
-      }
-      else if(pItem->next == NULL)
-      {
-          pNew->prev = pItem;
-          pItem->next = pNew;
+		    break;
+		}
+		else if(pItem->next == NULL)
+		{
+		    pNew->prev = pItem;
+		    pItem->next = pNew;
 
-          return_val = pNew->id;
+		    return_val = pNew->id;
 
-          break;
-      }
+		    break;
+		}
 
-      pItem = pItem->next;
-      }
+		pItem = pItem->next;
+	    }
 
-      break;
+	    break;
         }
 
         pList = pList->next;
@@ -223,50 +223,50 @@
         struct bm_cache_head *pNewList;
 
         pNewList = (struct bm_cache_head *)malloc(sizeof(struct bm_cache_head));
-
+ 
         pNewList->next  = NULL;
         pNewList->prev  = NULL;
         pNewList->width = gWidth;
         pNewList->head  = pNew;
-
+ 
         if(bm_cache == NULL)
         {
-      bm_cache = pNewList;
-      return_val = pNew->id;
+	    bm_cache = pNewList;
+	    return_val = pNew->id;
         }
         else
         {
-      pList = bm_cache;
+ 	    pList = bm_cache;
 
-      while(pList != NULL)
-      {
-          if(pList->width > gWidth)
-      {
-          pNewList->next  = pList;
-          pNewList->prev  = pList->prev;
+	    while(pList != NULL)
+	    {
+	        if(pList->width > gWidth)
+		{
+		    pNewList->next  = pList;
+		    pNewList->prev  = pList->prev;
 
-          if(pList->prev != NULL)
-             pList->prev->next = pNewList;
+		    if(pList->prev != NULL)
+		       pList->prev->next = pNewList;
                     else
-             bm_cache = pNewList;
-          pList->prev = pNewList;
+		       bm_cache = pNewList;
+		    pList->prev = pNewList;
 
-          return_val = pNew->id;
+		    return_val = pNew->id;
 
-          break;
-      }
-      else if(pList->next == NULL)
+		    break;
+		}
+		else if(pList->next == NULL)
                 {
-          pNewList->prev  = pList;
-          pList->next = pNewList;
+		    pNewList->prev  = pList;
+		    pList->next = pNewList;
 
-          return_val = pNew->id;
+		    return_val = pNew->id;
 
-          break;
-      }
+		    break;
+		}
 
-      pList = pList->next;
-      }
+		pList = pList->next;
+	    }
         }
     }
 
@@ -280,35 +280,35 @@
 {
     if(pItem != NULL)
     {
-  if(pItem->pBuffer != NULL)
-     free(pItem->pBuffer);
+	if(pItem->pBuffer != NULL)
+	   free(pItem->pBuffer);
         pItem->pBuffer = NULL;
 
-  if(pItem->next)
-     PsBmClearImageCacheItem(pItem->next);
+	if(pItem->next)
+	   PsBmClearImageCacheItem(pItem->next);
         pItem->next = NULL;
 
-  free(pItem);
-  pItem = NULL;
+	free(pItem);
+	pItem = NULL;
     }
 }
 
-static void
+static void 
 PsBmClearImageCacheList(
     struct bm_cache_head *pList)
 {
     if(pList != NULL)
     {
-  if(pList->head)
-      PsBmClearImageCacheItem(pList->head);
+	if(pList->head)
+	    PsBmClearImageCacheItem(pList->head);
         pList->head = NULL;
 
-  if(pList->next)
-      PsBmClearImageCacheList(pList->next);
+	if(pList->next)
+	    PsBmClearImageCacheList(pList->next);
         pList->next = NULL;
 
-  free(pList);
-  pList = NULL;
+	free(pList);
+	pList = NULL;
     }
 }
 

Index: PsColor.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/PsColor.c,v
retrieving revision 1.1.4.2
retrieving revision 1.1.4.3
diff -u -d -r1.1.4.2 -r1.1.4.3
--- a/PsColor.c	5 Mar 2004 13:39:54 -0000	1.1.4.2
+++ b/PsColor.c	21 Apr 2004 10:03:37 -0000	1.1.4.3
@@ -73,7 +73,6 @@
 **    *********************************************************
 ** 
 ********************************************************************/
-/* $XFree86: xc/programs/Xserver/Xprint/ps/PsColor.c,v 1.2 2001/10/28 03:32:56 tsi Exp $ */
 
 #include "Ps.h"
 #include "gcstruct.h"
@@ -86,6 +85,7 @@
   int            i;
   unsigned short rgb;
   VisualPtr      pVisual = pColor->pVisual;
+  Pixel          pix;
 
   if( pVisual->class==TrueColor )
   {

Index: PsFonts.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/PsFonts.c,v
retrieving revision 1.1.4.3
retrieving revision 1.1.4.4
diff -u -d -r1.1.4.3 -r1.1.4.4
--- a/PsFonts.c	5 Mar 2004 13:39:54 -0000	1.1.4.3
+++ b/PsFonts.c	21 Apr 2004 10:03:37 -0000	1.1.4.4
@@ -57,7 +57,6 @@
  * or other dealings in this Software without prior written authorization
  * from said copyright holders.
  */
-/* $XFree86: xc/programs/Xserver/Xprint/ps/PsFonts.c,v 1.6 2001/12/19 21:55:59 dawes Exp $ */
 
 /*******************************************************************
 **
@@ -80,9 +79,15 @@
 #include "dixfontstr.h"
 #include "scrnintstr.h"
 #include "fontxlfd.h"
+#include "fntfil.h"
+#include "fntfilst.h"
 
 #include "Ps.h"
 
+#include <ctype.h>
+#include <limits.h>
+#include <sys/stat.h>
+
 Bool
 PsRealizeFont(
   ScreenPtr  pscr,
@@ -110,7 +115,7 @@
 
   for( i=0 ; i<nprops ; i++ )
   {
-    if( (Atom)props[i].name == name )
+    if( (Atom)props[i].name==name )
       { value = props[i].value; break; }
   }
   if( !value ) return (char *)0;
@@ -145,12 +150,14 @@
   int         i;
   int         nprops = pFont->info.nprops;
   FontPropPtr props  = pFont->info.props;
-  Atom        name   = MakeAtom("PRINTER_RESIDENT_FONT", 21, True);
+  /* "_ADOBE_POSTSCRIPT_FONTNAME" maps directly to a PMF OBJ_NAME attribute
+   * name - changing the name will break printer-builtin fonts. */
+  Atom        name   = MakeAtom("_ADOBE_POSTSCRIPT_FONTNAME", 26, True); 
   Atom        value  = (Atom)0;
 
   for( i=0 ; i<nprops ; i++ )
   {
-    if( (Atom)props[i].name == name )
+    if( (Atom)props[i].name==name )
       { value = props[i].value; break; }
   }
   if( !value ) return (char *)0; 
@@ -171,8 +178,8 @@
 
   for( i=0 ; i<nprops ; i++ )
   {
-    if( (Atom)props[i].name == reg ) rv = props[i].value;
-    if( (Atom)props[i].name == enc ) ev = props[i].value;
+    if( (Atom)props[i].name==reg ) rv = props[i].value;
+    if( (Atom)props[i].name==enc ) ev = props[i].value;
   }
   if( rv ) rp = NameForAtom(rv);
   if( ev ) ep = NameForAtom(ev);
@@ -184,3 +191,680 @@
       ep[0]!='1' ) return(0);
   return(1);
 }
+
+/* Return the encoding part of the XLFD (e.g. "*-iso8859-6.8x" etc.)*/
+char *PsGetEncodingName(FontPtr pFont)
+{
+  int          i;
+  int          nprops = pFont->info.nprops;
+  FontPropPtr  props  = pFont->info.props;
+  Atom         fnt = MakeAtom("FONT",              4, True);
+  Atom         reg = MakeAtom("CHARSET_REGISTRY", 16, True);
+  Atom         enc = MakeAtom("CHARSET_ENCODING", 16, True);
+  Atom         fv = 0, rv = 0, ev = 0;
+  char        *fp = 0;
+  char        *rp = 0;
+  char        *ep = 0;
+  char        *encname;
+
+  for( i=0 ; i<nprops ; i++ )
+  {
+    if( props[i].name==fnt ) fv = props[i].value;
+    if( props[i].name==reg ) rv = props[i].value;
+    if( props[i].name==enc ) ev = props[i].value;
+  }
+  if( fv ) fp = NameForAtom(fv);
+  if( rv ) rp = NameForAtom(rv);
+  if( ev ) ep = NameForAtom(ev);
+
+  if( (!rp) || (!ep) || (!fp))
+    return(0);
+  
+  encname  = fp;
+  encname += strlen(encname) - (strlen(rp) + strlen(ep) + 1);
+  
+  return encname;
+}
+
+/* strstr(), case-insensitive */
+static 
+char *str_case_str(const char *s, const char *find)
+{
+  size_t len;
+  char   c, 
+         sc;
+
+  if ((c = tolower(*find++)) != '\0')
+  {
+    len = strlen(find);
+    do 
+    {
+      do
+      {
+        if ((sc = tolower(*s++)) == '\0')
+          return NULL;
+      } while (sc != c);
+    } while (strncasecmp(s, find, len) != 0);
+    s--;
+  }
+  return ((char *)s);
+}
+
+/* Check if the font path element is a directory which can be examined
+ * (for example the font may be from a font server
+ * (e.g. pFont->fpe->name == "tcp/:7100"))
+ */
+static
+Bool IsFPEaReadableDir(FontPtr pFont)
+{
+  const char *fpe_name = pFont->fpe->name;
+  if (!fpe_name)
+    return False;
+
+#define MODEL_FONTPATH_PREFIX     "PRINTER:"
+#define MODEL_FONTPATH_PREFIX_LEN 8
+  /* Strip model-specific font path prefix if there is one... */
+  if (!strncmp(fpe_name, MODEL_FONTPATH_PREFIX, MODEL_FONTPATH_PREFIX_LEN))
+    fpe_name += MODEL_FONTPATH_PREFIX_LEN;
+    
+  if (access(fpe_name, F_OK) == 0)
+  {
+    return True;
+  }
+
+  return False;
+}
+
+static
+char *getFontFilename(FontPtr pFont)
+{
+  FontDirectoryPtr   dir;
+  const char        *dlfnam;
+  FILE              *file;
+  struct stat        statb;
+  int                count, i, status;
+  char               buf[512];
+  char              *front, *end, *fn;
+  char               font_dir_fname[PATH_MAX],  /* Full path of fonts.dir */
+                     font_file_fname[PATH_MAX]; /* Name of font file (excluding path) */
+
+#ifdef XP_USE_FREETYPE
+  if( PsIsFreeTypeFont(pFont) )
+  {
+    const char  *fontname = PsGetFTFontFileName(pFont);
+
+#ifdef DEBUG_gisburn
+    fprintf(stderr, "getFontFilename: freetype font, file='%s'\n", fontname?fontname:"<NULL>");
+#endif /* DEBUG_gisburn */  
+
+    if( !fontname )
+      return NULL;
+      
+    return strdup(fontname);
+  }
+#endif /* XP_USE_FREETYPE */
+
+  if (!IsFPEaReadableDir(pFont))
+  {
+#ifdef DEBUG_gisburn
+    fprintf(stderr, "getFontFilename: '%s' no valid font path on disk\n", pFont->fpe->name);
+#endif /* DEBUG_gisburn */  
+    return NULL;
+  }
+
+  dir = pFont->fpe->private;
+  sprintf(font_dir_fname, "%s%s", dir->directory, "fonts.dir");  
+  
+  if (!(dlfnam = PsGetFontName(pFont)))
+    return NULL;
+  
+  file = fopen(font_dir_fname, "r");
+  if (file)
+  {
+    if (fstat (fileno(file), &statb) == -1)
+      return NULL;
+
+    while( fgets(buf, sizeof(buf)-1, file) )
+    {             
+      if ((fn = strstr(buf, " -")))
+      {
+        strcpy(font_file_fname, buf);
+        font_file_fname[fn - buf] = '\0';
+        fn++;
+        if ((front = str_case_str(fn, "normal-")))
+        {
+          fn[front - fn] = '\0';
+          if (str_case_str(dlfnam, fn))        
+          {
+            char full_font_file_path[PATH_MAX];
+
+            fclose(file);
+            
+            sprintf(full_font_file_path, "%s%s", dir->directory, font_file_fname);
+
+#ifdef xDEBUG_gisburn
+            fprintf(stderr, "getFontFilename: returning '%s'\n", full_font_file_path);
+#endif /* DEBUG_gisburn */
+            return strdup(full_font_file_path); 
+          }
+        }
+      }
+    }
+  }
+  font_file_fname[0] = '\0';
+  fclose(file);
+
+#ifdef DEBUG_gisburn
+  fprintf(stderr, "getFontFilename: returning NULL\n");
+#endif /* DEBUG_gisburn */
+
+  return NULL;
+}
+
+static
+PsFontTypeInfoRec *PsFindFontTypeInfoRec(DrawablePtr pDrawable, FontPtr pFont)
+{
+  PsContextPrivRec  *cPriv = PsGetPsContextPriv(pDrawable);
+  PsFontTypeInfoRec *rec;
+  const char        *psname;
+  char              *font_filename;
+  char              *encname;
+#ifdef XP_USE_FREETYPE
+  Bool               is_freetypefont;
+#endif /* XP_USE_FREETYPE */
+  
+#ifdef XP_USE_FREETYPE
+  is_freetypefont = PsIsFreeTypeFont(pFont);
+#endif /* XP_USE_FREETYPE */
+  encname         = PsGetEncodingName(pFont);
+
+  /* First try: Search by PostScript font name */
+  psname = PsGetPSFontName(pFont);
+  if (psname)
+  {
+    for( rec = cPriv->fontTypeInfoRecords ; rec != NULL ; rec = rec->next )
+    {
+#ifdef XP_USE_FREETYPE
+      if (is_freetypefont)
+      {
+        if (rec->adobe_ps_name)
+        {
+          if ((rec->font_type == PSFTI_FONT_TYPE_FREETYPE) &&
+              (!strcmp(rec->adobe_ps_name, psname)) &&
+              (!strcmp(rec->ft_download_encoding, encname)))
+          {
+            return rec;
+          }
+        }
+      }
+      else
+#endif /* XP_USE_FREETYPE */
+      {
+        if (rec->adobe_ps_name)
+        {
+          if ((rec->font_type != PSFTI_FONT_TYPE_FREETYPE) &&
+              (!strcmp(rec->adobe_ps_name, psname)))
+          {
+            return rec;
+          }
+        }
+      }
+    }
+  }
+
+  /* Last attempt: Search by filename */
+  font_filename = getFontFilename(pFont);
+  if (font_filename)
+  {
+    for( rec = cPriv->fontTypeInfoRecords ; rec != NULL ; rec = rec->next )
+    {
+      if (rec->filename)
+      {
+#ifdef XP_USE_FREETYPE
+        if (is_freetypefont)
+        {
+          if ( (rec->font_type == PSFTI_FONT_TYPE_FREETYPE) &&
+               (!strcasecmp(rec->filename, font_filename)) && 
+               (!strcasecmp(rec->ft_download_encoding, encname)) )
+          {
+            free(font_filename);
+            return rec;
+          }
+        }
+        else
+#endif /* XP_USE_FREETYPE */
+        {
+          if ( (rec->font_type != PSFTI_FONT_TYPE_FREETYPE) &&
+               (!strcasecmp(rec->filename, font_filename)) )
+          {
+            free(font_filename);
+            return rec;
+          }
+        }
+      }
+    }
+    
+    free(font_filename);
+  }
+  
+  return NULL;
+}
+
+static
+void PsAddFontTypeInfoRec(DrawablePtr pDrawable, PsFontTypeInfoRec *add_rec)
+{ 
+  PsContextPrivRec *cPriv = PsGetPsContextPriv(pDrawable);
+
+  /* ToDO: Always move the last used entry to the top that the list get's
+   * sorted in an efficient order... :-) */
+  add_rec->next = cPriv->fontTypeInfoRecords;
+  cPriv->fontTypeInfoRecords = add_rec;
+}
+
+static
+Bool strcaseendswith(const char *str, const char *suffix)
+{
+  const char *s;
+
+  s = str + strlen(str) - strlen(suffix);
+
+  if (!strcasecmp(s, suffix))
+    return True;
+
+  return False;
+}
+
+
+static
+int getFontFileType( const char *filename )
+{
+  int type;
+
+  /* Is this a Adobe PostScript Type 1 binary font (PFB) ? */
+  if( strcaseendswith(filename, ".pfb") )
+  {
+    type = PSFTI_FONT_TYPE_PS_TYPE1_PFB;
+  }
+  /* Is this a Adobe PostScript ASCII font (PFA) ? */
+  else if( strcaseendswith(filename, ".pfa") )
+  {
+    type = PSFTI_FONT_TYPE_PS_TYPE1_PFA;
+  }
+  /* Is this a PMF(=Printer Metrics File) ? */
+  else if( strcaseendswith(filename, ".pmf") )
+  {
+    type = PSFTI_FONT_TYPE_PMF;
+  }
+  /* Is this a TrueType font file ? */
+  else if( strcaseendswith(filename, ".ttf") ||
+           strcaseendswith(filename, ".ttc") ||
+           strcaseendswith(filename, ".otf") ||
+           strcaseendswith(filename, ".otc") )
+  {
+    type = PSFTI_FONT_TYPE_TRUETYPE;
+  }
+  else
+  {
+    type = PSFTI_FONT_TYPE_OTHER;
+  }
+
+#ifdef XP_USE_FREETYPE
+  {
+    XpContextPtr  pCon;
+    char         *downloadfonts;
+    pCon = XpGetPrintContext(requestingClient);
+    downloadfonts = XpGetOneAttribute(pCon, XPPrinterAttr, "xp-psddx-download-fonts");
+    if( downloadfonts )
+    {
+      /* Should we download PS Type1 fonts as PS Type1||Type3 ? */
+      if( (type == PSFTI_FONT_TYPE_PS_TYPE1_PFA) &&
+          (strstr(downloadfonts, "pfa") != NULL) )
+      {
+        type = PSFTI_FONT_TYPE_FREETYPE;
+      }
+
+      if( (type == PSFTI_FONT_TYPE_PS_TYPE1_PFB) &&
+          (strstr(downloadfonts, "pfb") != NULL) )
+      {
+        type = PSFTI_FONT_TYPE_FREETYPE;
+      }
+
+      /* Should we download TrueType fonts as PS Type1||Type3 ? */
+      if( (type == PSFTI_FONT_TYPE_TRUETYPE) &&
+          ((strstr(downloadfonts, "ttf") != NULL) || 
+           (strstr(downloadfonts, "ttc") != NULL) || 
+           (strstr(downloadfonts, "otf") != NULL) || 
+           (strstr(downloadfonts, "otc") != NULL)) )
+      {
+        type = PSFTI_FONT_TYPE_FREETYPE;
+      }
+    }
+  }
+#endif /* XP_USE_FREETYPE */
+
+#ifdef DEBUG_gisburn
+  fprintf(stderr, "getFontFileType: '%s' is %d\n", filename, (int)type);
+#endif /* DEBUG_gisburn */
+  return type;
+}
+
+PsFTDownloadFontType PsGetFTDownloadFontType(void)
+{
+  PsFTDownloadFontType  downloadfonttype;
+  XpContextPtr          pCon;
+  char                 *psfonttype;
+
+  pCon       = XpGetPrintContext(requestingClient);
+  psfonttype = XpGetOneAttribute(pCon, XPPrinterAttr, "xp-psddx-download-font-type");
+
+  if( !psfonttype || !strlen(psfonttype) )
+  {
+    return PsFontType1; /* Default download font type is PS Type1 */
+  }
+
+  if( !strcmp(psfonttype, "bitmap") )
+  {
+    downloadfonttype = PsFontBitmap;
+  }
+  else if( !strcmp(psfonttype, "pstype3") )
+  {
+    downloadfonttype = PsFontType3;
+  }
+  else if( !strcmp(psfonttype, "pstype1") )
+  { 
+    downloadfonttype = PsFontType1;
+  }
+  else
+  {
+     FatalError("PS DDX: XPPrinterAttr/xp-psddx-download-freetype-font-type='%s' not implemented\n", psfonttype);
+     return 0; /* NO-OP, FatalError() will call |exit()| */
+  }
+  
+  return downloadfonttype;
+}
+
+static
+PsFontTypeInfoRec *PsCreateFontTypeInfoRec(DrawablePtr pDrawable, FontPtr pFont)
+{
+  char              *dlfnam;
+  PsFontTypeInfoRec *rec;
+  char              *psname;
+  
+  if (!(dlfnam = PsGetFontName(pFont)))
+    return NULL;
+
+  if (!(rec = (PsFontTypeInfoRec *)xalloc(sizeof(PsFontTypeInfoRec))))
+    return NULL;
+  memset(rec, 0, sizeof(PsFontTypeInfoRec));
+
+  rec->next              = NULL;
+
+  if (rec->filename = getFontFilename(pFont))
+  {
+    rec->font_type = getFontFileType(rec->filename);   
+  }
+  else
+  {
+    rec->filename  = NULL;
+    rec->font_type = PSFTI_FONT_TYPE_OTHER;
+  }
+
+  rec->adobe_ps_name         = PsGetPSFontName(pFont);
+  rec->ft_download_encoding  = PsGetEncodingName(pFont);
+  rec->ft_download_font_type = PsGetFTDownloadFontType();
+  rec->download_ps_name      = NULL;
+
+#define SET_FONT_DOWNLOAD_STATUS(rec, downloaded) { int i; for (i = 0 ; i < 256 ; i++) { (rec)->alreadyDownloaded[i]=(downloaded); } }
+
+  /* Set some flags based on the font type */
+  switch( rec->font_type )
+  {
+    case PSFTI_FONT_TYPE_PS_TYPE1_PFA:
+    case PSFTI_FONT_TYPE_PS_TYPE1_PFB:
+      rec->downloadableFont  = True;
+      SET_FONT_DOWNLOAD_STATUS(rec, False);
+      rec->is_iso_encoding = PsIsISOLatin1Encoding(pFont);
+      break;
+
+    case PSFTI_FONT_TYPE_PMF:
+      rec->downloadableFont  = True; /* This font is in printer's ROM */
+      SET_FONT_DOWNLOAD_STATUS(rec, True);
+      rec->is_iso_encoding = PsIsISOLatin1Encoding(pFont);
+      break;
+    
+    case PSFTI_FONT_TYPE_TRUETYPE:
+      /* Note: TrueType font download not implemented */
+      rec->downloadableFont  = False;
+      SET_FONT_DOWNLOAD_STATUS(rec, False);
+      rec->is_iso_encoding = PsIsISOLatin1Encoding(pFont);
+      break;
+
+#ifdef XP_USE_FREETYPE
+    case PSFTI_FONT_TYPE_FREETYPE:
+      if( rec->ft_download_font_type == PsFontType1 ||
+          rec->ft_download_font_type == PsFontType3 )
+      {
+        rec->downloadableFont = True;
+      }
+      else
+      {
+        rec->downloadableFont = False;
+      }
+
+      SET_FONT_DOWNLOAD_STATUS(rec, False);
+      rec->is_iso_encoding   = False; /* Freetype--->PS Type1/Type3 uses always non-iso PS encoding for now */
+      break;
+#endif /* XP_USE_FREETYPE */
+
+    case PSFTI_FONT_TYPE_OTHER:
+    default:
+      rec->downloadableFont  = False;
+      SET_FONT_DOWNLOAD_STATUS(rec, False);
+      rec->is_iso_encoding = PsIsISOLatin1Encoding(pFont);
+      break;
+  }
+  
+#ifdef XP_USE_FREETYPE
+  if( (rec->font_type == PSFTI_FONT_TYPE_FREETYPE) )
+  {
+    char *s;
+    register int c;
+
+    if( rec->adobe_ps_name )
+    {
+      rec->download_ps_name = malloc(strlen(rec->adobe_ps_name) + strlen(rec->ft_download_encoding) + 2);
+      sprintf(rec->download_ps_name, "%s_%s", rec->adobe_ps_name, rec->ft_download_encoding);
+    }
+    else
+    {
+      /* Unfortunately not all TTF fonts have a PostScript font name (like
+       * Solaris TTF fonts in /usr/openwin/lib/locale/ko.UTF-8/X11/fonts/TrueType,
+       * /usr/openwin/lib/locale/ko/X11/fonts/TrueType) - in this case we
+       * have to generate a font name
+       */
+      char        ftfontname[64];
+      static long myfontindex = 0L;
+      sprintf(ftfontname, "psfont_%lx", myfontindex++);
+      
+      rec->download_ps_name = malloc(strlen(ftfontname) + strlen(rec->ft_download_encoding) + 2);
+      sprintf(rec->download_ps_name, "%s_%s", ftfontname, rec->ft_download_encoding);
+      
+      fprintf(stderr, "PsCreateFontTypeInfoRec: Note: '%s' has no PS font name, using '%s' for now.\n", dlfnam, rec->download_ps_name);
+    }
+    
+    /* Make sure the font name we use for download is a valid PS font name */
+    for( s = rec->download_ps_name ; *s != '\0'; s++ )
+    {
+      c = *s;
+      
+      /* Check for allowed chars, invalid ones are replaced with a '_'
+       * (and check that the first char is not a digit) */
+      if( !(isalnum(c) || c == '.' || c == '_' || c == '-') || (s==rec->download_ps_name && isdigit(c)) )
+      {
+        *s = '_';
+      }
+    }
+  }
+  else
+#endif /* XP_USE_FREETYPE */
+  {
+    if( rec->adobe_ps_name )
+    {
+      rec->download_ps_name = strdup(rec->adobe_ps_name);
+    }
+    else
+    {
+      rec->download_ps_name = NULL;
+    }
+  }
+
+  /* Safeguard - only treat font as downloadable when we have a PS font name!! */
+  if (!rec->download_ps_name && rec->downloadableFont)
+  {
+    /* XXX: Log this message to the log when the logging service has been hook'ed up */
+    fprintf(stderr, "PsCreateFontTypeInfoRec: Safeguard: No PS font name for '%s'!\n", dlfnam);
+    rec->downloadableFont = False;
+  }
+
+#ifdef DEBUG_gisburn
+  fprintf(stderr, "PsCreateFontTypeInfoRec: Created PsFontTypeInfoRec '%s' ('%s'/'%s')\n",
+          ((rec->filename)        ?(rec->filename)     :("<null>")),
+          ((rec->adobe_ps_name)   ?(rec->adobe_ps_name):("<null>")),
+          ((rec->download_ps_name)?(rec->download_ps_name):("<null>")));
+#endif /* DEBUG_gisburn */
+
+  return rec;
+}
+
+static
+PsFontTypeInfoRec *PsGetFontTypeInfoRec(DrawablePtr pDrawable, FontPtr pFont)
+{
+  PsFontTypeInfoRec *rec;
+  char              *dlfnam;
+
+  if(!(dlfnam = PsGetFontName(pFont)))
+    return NULL;
+  
+  rec = PsFindFontTypeInfoRec(pDrawable, pFont);
+  if (rec)
+    return rec;
+    
+  rec = PsCreateFontTypeInfoRec(pDrawable, pFont);
+  if (!rec)
+    return NULL;
+  
+  PsAddFontTypeInfoRec(pDrawable, rec);
+
+  return rec;
+}
+
+static
+void PsFreeFontTypeInfoRecords( PsContextPrivPtr priv )
+{
+  PsFontTypeInfoRec *curr, *next;
+  curr = priv->fontTypeInfoRecords;
+  while( curr != NULL )
+  {
+    if (curr->filename)
+      free(curr->filename); /* Free memory allocated by |strdup()| */
+
+    if (curr->download_ps_name)
+      free(curr->download_ps_name);
+      
+    next = curr->next;
+    xfree(curr);
+    curr = next;
+  }
+}
+
+static
+PsFontInfoRec *PsFindFontInfoRec(DrawablePtr pDrawable, FontPtr pFont)
+{
+  PsContextPrivRec *cPriv = PsGetPsContextPriv(pDrawable);
+  PsFontInfoRec    *rec;
+
+  if (!pFont)
+    return NULL;
+
+  for( rec = cPriv->fontInfoRecords ; rec != NULL ; rec = rec->next )
+  {
+    if ((rec->font == pFont) && 
+        (rec->font_fontPrivate == pFont->fontPrivate))
+      return rec;
+  }
+  
+  return NULL;
+}
+
+static
+void PsAddFontInfoRec(DrawablePtr pDrawable, PsFontInfoRec *add_rec)
+{ 
+  PsContextPrivRec *cPriv = PsGetPsContextPriv(pDrawable);
+
+  /* ToDO: Always move the last used entry to the top that the list get's
+   * sorted in an efficient order... :-) */
+  add_rec->next = cPriv->fontInfoRecords;
+  cPriv->fontInfoRecords = add_rec;
+}
+
+static
+PsFontInfoRec *PsCreateFontInfoRec(DrawablePtr pDrawable, FontPtr pFont)
+{
+  PsFontInfoRec     *rec;
+  PsFontTypeInfoRec *ftir;
+  
+  if (!(ftir = PsGetFontTypeInfoRec(pDrawable, pFont)))
+    return NULL;
+
+  if (!(rec = (PsFontInfoRec *)xalloc(sizeof(PsFontInfoRec))))
+    return NULL;
+  memset(rec, 0, sizeof(PsFontInfoRec));
+
+  rec->font     = pFont;
+  rec->font_fontPrivate = pFont->fontPrivate;
+  rec->ftir     = ftir;
+  rec->next     = NULL;
+  rec->dfl_name = PsGetFontName(pFont);
+  rec->size     = PsGetFontSize(pFont, rec->mtx);
+
+#ifdef DEBUG_gisburn
+  fprintf(stderr, "PsCreateFontInfoRec: Created PsFontInfoRec '%s'\n",
+          ((rec->dfl_name)?(rec->dfl_name):("<null>")));
+#endif /* DEBUG_gisburn */
+
+  return rec;
+}
+
+PsFontInfoRec *PsGetFontInfoRec(DrawablePtr pDrawable, FontPtr pFont)
+{
+  PsFontInfoRec *rec;
+
+  rec = PsFindFontInfoRec(pDrawable, pFont);
+  if (rec)
+    return rec;
+    
+  rec = PsCreateFontInfoRec(pDrawable, pFont);
+  if (!rec)
+    return NULL;
+  
+  PsAddFontInfoRec(pDrawable, rec);
+
+  return rec;
+}
+
+void PsFreeFontInfoRecords( PsContextPrivPtr priv )
+{
+  PsFontInfoRec *curr, *next;
+  curr = priv->fontInfoRecords;
+  while( curr != NULL )
+  {  
+    next = curr->next;
+    xfree(curr);
+    curr = next;
+  }
+  
+  PsFreeFontTypeInfoRecords(priv);
+
+  priv->fontTypeInfoRecords = NULL;
+  priv->fontInfoRecords     = NULL;
+}

Index: PsGC.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/PsGC.c,v
retrieving revision 1.1.4.3
retrieving revision 1.1.4.4
diff -u -d -r1.1.4.3 -r1.1.4.4
--- a/PsGC.c	5 Mar 2004 13:39:54 -0000	1.1.4.3
+++ b/PsGC.c	21 Apr 2004 10:03:37 -0000	1.1.4.4
@@ -57,7 +57,6 @@
  * or other dealings in this Software without prior written authorization
  * from said copyright holders.
  */
-/* $XFree86: xc/programs/Xserver/Xprint/ps/PsGC.c,v 1.6tsi Exp $ */
 
 /*******************************************************************
 **
@@ -171,6 +170,26 @@
   }
 }
 
+PsContextPrivPtr
+PsGetPsContextPriv( DrawablePtr pDrawable )
+{
+  XpContextPtr     pCon;
+  PsContextPrivPtr cPriv;
+
+  switch(pDrawable->type)
+  {
+    case DRAWABLE_PIXMAP:
+      return FALSE;
+    case DRAWABLE_WINDOW:
+      pCon = PsGetContextFromWindow((WindowPtr)pDrawable);
+      if (pCon != NULL)
+      {
+        return pCon->devPrivates[PsContextPrivateIndex].ptr;
+      }
+  }
+  return NULL;
+}
+
 int
 PsUpdateDrawableGC(
   GCPtr        pGC,
@@ -181,6 +200,7 @@
   GC               dGC;
   unsigned long    valid;
   int              i;
+  PsContextPrivPtr cPriv;
   BoxPtr           boxes;
 
   if (!PsGetDrawablePrivateStuff(pDrawable, &dGC, &valid, psOut, cMap))
@@ -232,6 +252,8 @@
         PsOut_Offset(*psOut, pDrawable->x, pDrawable->y);
         PsOut_Clip(*psOut, pGC->clientClipType, (PsClipPtr)pGC->clientClip);
       }
+      cPriv = ( PsGetContextFromWindow( (WindowPtr)pDrawable ) )
+             ->devPrivates[PsContextPrivateIndex].ptr;
       break;
   }
   return TRUE;

Index: PsInit.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/PsInit.c,v
retrieving revision 1.1.4.3
retrieving revision 1.1.4.4
diff -u -d -r1.1.4.3 -r1.1.4.4
--- a/PsInit.c	5 Mar 2004 13:39:54 -0000	1.1.4.3
+++ b/PsInit.c	21 Apr 2004 10:03:37 -0000	1.1.4.4
@@ -71,9 +71,8 @@
 **    *  Copyright:	Copyright 1996 The Open Group, Inc.
 **    *
 **    *********************************************************
-**
+** 
 ********************************************************************/
-/* $XFree86: xc/programs/Xserver/Xprint/ps/PsInit.c,v 1.13tsi Exp $ */
 
 #include <stdio.h>
 #include <string.h>
@@ -109,8 +108,12 @@
   char      **argv;
 {
 #if 0
+  int               maxXres, maxYres, maxWidth, maxHeight;
+  int               maxRes, maxDim, numBytes;
   PsScreenPrivPtr   pPriv;
 #endif
+  char            **printerNames;
+  int               numPrinters;
   int               nVisuals;
   int               nDepths;
   VisualPtr         visuals;
@@ -188,7 +191,7 @@
 
   visuals[1].vid             = FakeClientID(0);
   visuals[1].class           = PseudoColor;
-  visuals[1].bitsPerRGBValue = 0;
+  visuals[1].bitsPerRGBValue = 8;
   visuals[1].ColormapEntries = 256;
   visuals[1].nplanes         = 8;
   visuals[1].redMask         = 0x0;
@@ -209,7 +212,7 @@
 /*  THE FOLLOWING CAUSES SERVER DEFAULT VISUAL TO BE 24 BIT  */
 /*  miScreenInit(pScreen, (pointer)0,
 	       pScreen->width, pScreen->height,
-	       pScreen->width / (pScreen->mmWidth / 25.40),
+	       pScreen->width / (pScreen->mmWidth / 25.40), 
 	       pScreen->height / (pScreen->mmHeight / 25.40),
 	       0, 24, nDepths,
                depths, visuals[1].vid, nVisuals, visuals); */
@@ -217,7 +220,7 @@
 /*  THE FOLLOWING CAUSES SERVER DEFAULT VISUAL TO BE 8 BIT  */
   miScreenInit(pScreen, (pointer)0,
 	       pScreen->width, pScreen->height,
-	       (int) (pScreen->width / (pScreen->mmWidth / 25.40)),
+	       (int) (pScreen->width / (pScreen->mmWidth / 25.40)), 
 	       (int) (pScreen->height / (pScreen->mmHeight / 25.40)),
 	       0, 8, nDepths,
                depths, visuals[1].vid, nVisuals, visuals);
@@ -243,7 +246,7 @@
                           sizeof(PsWindowPrivRec));
 
     PsContextPrivateIndex = XpAllocateContextPrivateIndex();
-    XpAllocateContextPrivate(PsContextPrivateIndex,
+    XpAllocateContextPrivate(PsContextPrivateIndex, 
                              sizeof(PsContextPrivRec));
 
     PsPixmapPrivateIndex = AllocatePixmapPrivateIndex();
@@ -278,7 +281,7 @@
   XpDriverFuncsPtr pFuncs;
   PsContextPrivPtr pConPriv;
   char *server, *attrStr;
-
+    
   /*
    * Initialize the attribute store for this printer.
    */
@@ -304,18 +307,23 @@
   pFuncs->GetMediumDimensions = PsGetMediumDimensions;
   pFuncs->GetReproducibleArea = PsGetReproducibleArea;
   pFuncs->SetImageResolution = PsSetImageResolution;
-
+    
   /*
    * Set up the context privates
    */
   pConPriv =
       (PsContextPrivPtr)pCon->devPrivates[PsContextPrivateIndex].ptr;
 
-  pConPriv->jobFileName  = (char *)NULL;
-  pConPriv->pJobFile     = (FILE *)NULL;
-
-  pConPriv->getDocClient = (ClientPtr)NULL;
-  pConPriv->getDocBufSize = 0;
+  memset(pConPriv, 0, sizeof(PsContextPrivRec));
+  pConPriv->jobFileName         = (char *)NULL;
+  pConPriv->pJobFile            = (FILE *)NULL;
+  pConPriv->dash                = (unsigned char *)NULL;
+  pConPriv->validGC             = 0;
+  pConPriv->getDocClient        = (ClientPtr)NULL;
+  pConPriv->getDocBufSize       = 0;
+  pConPriv->pPsOut              = NULL;
+  pConPriv->fontInfoRecords     = NULL;
+  pConPriv->fontTypeInfoRecords = NULL;
 
   /*
    * document-attributes-supported
@@ -323,15 +331,15 @@
   server = XpGetOneAttribute( pCon, XPServerAttr, DOC_ATT_SUPP );
   if ((attrStr = (char *) xalloc(strlen(server) +
 				strlen(DOC_ATT_SUPP) + strlen(DOC_ATT_VAL)
-				+ strlen(PAGE_ATT_VAL) + 6)) == NULL)
+				+ strlen(PAGE_ATT_VAL) + 6)) == NULL) 
   {
       return BadAlloc;
   }
-  sprintf(attrStr, "*%s:\t%s %s %s",
+  sprintf(attrStr, "*%s:\t%s %s %s", 
 	  DOC_ATT_SUPP, server, DOC_ATT_VAL, PAGE_ATT_VAL);
   XpAugmentAttributes( pCon, XPPrinterAttr, attrStr);
   xfree(attrStr);
-
+    
   /*
    * job-attributes-supported
    */
@@ -344,7 +352,7 @@
   sprintf(attrStr, "*%s:\t%s %s", JOB_ATT_SUPP, server, JOB_ATT_VAL);
   XpAugmentAttributes(pCon, XPPrinterAttr, attrStr);
   xfree(attrStr);
-
+    
   /*
    * xp-page-attributes-supported
    */
@@ -375,7 +383,7 @@
 {
   PsContextPrivPtr pConPriv =
       (PsContextPrivPtr)pCon->devPrivates[PsContextPrivateIndex].ptr;
-
+    
   if( pConPriv->pJobFile!=(FILE *)NULL )
   {
     fclose(pConPriv->pJobFile);
@@ -388,6 +396,11 @@
     pConPriv->jobFileName = (char *)NULL;
   }
 
+  PsFreeFontInfoRecords(pConPriv);
+
+  /* Reset context to make sure we do not use any stale/invalid/obsolete data */
+  memset(pConPriv, 0, sizeof(PsContextPrivRec));
+
 /*### free up visuals/depths ###*/
 
   return Success;

Index: PsLine.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/PsLine.c,v
retrieving revision 1.1.4.2
retrieving revision 1.1.4.3
diff -u -d -r1.1.4.2 -r1.1.4.3
--- a/PsLine.c	5 Mar 2004 13:39:54 -0000	1.1.4.2
+++ b/PsLine.c	21 Apr 2004 10:03:37 -0000	1.1.4.3
@@ -73,7 +73,6 @@
 **    *********************************************************
 ** 
 ********************************************************************/
-/* $XFree86: xc/programs/Xserver/Xprint/ps/PsLine.c,v 1.5 2001/01/17 22:36:32 dawes Exp $ */
 
 #include "Ps.h"
 #include "gcstruct.h"

Index: PsMisc.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/PsMisc.c,v
retrieving revision 1.1.4.2
retrieving revision 1.1.4.3
diff -u -d -r1.1.4.2 -r1.1.4.3
--- a/PsMisc.c	5 Mar 2004 13:39:54 -0000	1.1.4.2
+++ b/PsMisc.c	21 Apr 2004 10:03:37 -0000	1.1.4.3
@@ -73,7 +73,6 @@
 **    *********************************************************
 ** 
 ********************************************************************/
-/* $XFree86: xc/programs/Xserver/Xprint/ps/PsMisc.c,v 1.5 2001/01/17 22:36:32 dawes Exp $ */
 
 #include "Xos.h"	/* for SIGCLD on pre-POSIX systems */
 #include <stdio.h>

Index: PsPixel.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/PsPixel.c,v
retrieving revision 1.1.4.2
retrieving revision 1.1.4.3
diff -u -d -r1.1.4.2 -r1.1.4.3
--- a/PsPixel.c	5 Mar 2004 13:39:54 -0000	1.1.4.2
+++ b/PsPixel.c	21 Apr 2004 10:03:37 -0000	1.1.4.3
@@ -73,7 +73,6 @@
 **    *********************************************************
 ** 
 ********************************************************************/
-/* $XFree86: xc/programs/Xserver/Xprint/ps/PsPixel.c,v 1.5 2001/01/17 22:36:32 dawes Exp $ */
 
 #include <stdio.h>
 

Index: PsPixmap.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/PsPixmap.c,v
retrieving revision 1.1.4.2
retrieving revision 1.1.4.3
diff -u -d -r1.1.4.2 -r1.1.4.3
--- a/PsPixmap.c	5 Mar 2004 13:39:54 -0000	1.1.4.2
+++ b/PsPixmap.c	21 Apr 2004 10:03:37 -0000	1.1.4.3
@@ -57,7 +57,7 @@
  * or other dealings in this Software without prior written authorization
  * from said copyright holders.
  */
-/* $XFree86: xc/programs/Xserver/Xprint/ps/PsPixmap.c,v 1.4 2001/01/17 22:36:32 dawes Exp $ */
+
 /*******************************************************************
 **
 **    *********************************************************
@@ -79,6 +79,10 @@
 
 #include "Ps.h"
 
+#define BitsPerPixel(d) (\
+  (1 << PixmapWidthPaddingInfo[d].padBytesLog2) * 8 / \
+  (PixmapWidthPaddingInfo[d].padRoundUp+1))
+
 PixmapPtr
 PsCreatePixmap(
   ScreenPtr pScreen,
@@ -199,7 +203,7 @@
   return(disp);
 }
 
-static void
+void
 PsReplay(DisplayElmPtr elm, DrawablePtr pDrawable)
 {
   switch(elm->type)
@@ -488,8 +492,6 @@
         case PolyFillArcCmd:
           *nElms += elm->c.arcs.nArcs;
           break;
-        default:
-          break;
       }
     }
   }
@@ -552,8 +554,6 @@
                 *nElms += 1;
               }
               break;
-            default:
-              break;
           }
         }
       }

Index: PsPolygon.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/PsPolygon.c,v
retrieving revision 1.1.4.2
retrieving revision 1.1.4.3
diff -u -d -r1.1.4.2 -r1.1.4.3
--- a/PsPolygon.c	5 Mar 2004 13:39:54 -0000	1.1.4.2
+++ b/PsPolygon.c	21 Apr 2004 10:03:37 -0000	1.1.4.3
@@ -73,7 +73,6 @@
 **    *********************************************************
 ** 
 ********************************************************************/
-/* $XFree86: xc/programs/Xserver/Xprint/ps/PsPolygon.c,v 1.6 2001/01/17 22:36:32 dawes Exp $ */
 
 #include "Ps.h"
 #include "gcstruct.h"
@@ -176,7 +175,8 @@
     }
     else
     {
-      pts[0].x = pPoints[0].x; pts[0].y = pPoints[0].y;
+      i = 0;
+      pts[0].x = pPoints[i].x; pts[0].y = pPoints[i].y;
       for( i=1 ; i<nPoints ;  i++ )
       {
         pts[i].x = pts[i-1].x+pPoints[i].x;

Index: PsPrint.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/PsPrint.c,v
retrieving revision 1.1.4.2
retrieving revision 1.1.4.3
diff -u -d -r1.1.4.2 -r1.1.4.3
--- a/PsPrint.c	5 Mar 2004 13:39:54 -0000	1.1.4.2
+++ b/PsPrint.c	21 Apr 2004 10:03:37 -0000	1.1.4.3
@@ -73,7 +73,6 @@
 **    *********************************************************
 ** 
 ********************************************************************/
-/* $XFree86: xc/programs/Xserver/Xprint/ps/PsPrint.c,v 1.10 2001/12/14 19:59:17 dawes Exp $ */
 
 #include <stdio.h>
 #include <string.h>
@@ -91,6 +90,7 @@
 #include "Ps.h"
 
 #include "windowstr.h"
+#include "attributes.h"
 #include "Oid.h"
 
 /* static utility function to get document/page attributes */
@@ -206,6 +206,8 @@
     unlink(priv->jobFileName);
     xfree(priv->jobFileName);
     priv->jobFileName = (char *)NULL;
+    
+    PsFreeFontInfoRecords(priv);
 
     return Success;
   }
@@ -214,6 +216,7 @@
    * Append any trailing information here
    */
   PsOut_EndFile(priv->pPsOut, 0);
+  priv->pPsOut = NULL;
   
   /* this is where we find out if we're out of space */
   error = (fclose(priv->pJobFile) == EOF);
@@ -233,6 +236,8 @@
     xfree(priv->jobFileName);
     priv->jobFileName = (char *)NULL;
 
+    PsFreeFontInfoRecords(priv);
+
     return BadAlloc;
   }
     
@@ -265,10 +270,12 @@
   xfree(priv->jobFileName);
   priv->jobFileName = (char *)NULL;
 
+  PsFreeFontInfoRecords(priv);
+    
 #ifdef BM_CACHE
   PsBmClearImageCache();
 #endif
-        
+
   return r;
 }
 
@@ -281,10 +288,13 @@
 {
   int                iorient, iplex, icount, ires;
   unsigned short     iwd, iht;
+  register WindowPtr pChild;
   PsContextPrivPtr   pConPriv =
      (PsContextPrivPtr)pCon->devPrivates[PsContextPrivateIndex].ptr;
   PsWindowPrivPtr    pWinPriv =
      (PsWindowPrivPtr)pWin->devPrivates[PsWindowPrivateIndex].ptr;
+  char               s[80];
+  xEvent event;
 
 /*
  * Put a pointer to the context in the window private structure
@@ -298,9 +308,16 @@
    *  Start the page
    */
   if (pConPriv->pPsOut == NULL) {
-      pConPriv->pPsOut = PsOut_BeginFile(pConPriv->pJobFile,
-				   iorient, icount, iplex, ires,
-				   (int)iwd, (int)iht, False);
+    char *title;
+    
+    /* get job level attributes */ 
+    title = XpGetOneAttribute(pCon, XPJobAttr, "job-name");
+
+    pConPriv->pPsOut = PsOut_BeginFile(pConPriv->pJobFile,
+                                       title, iorient, icount, iplex, ires,
+                                       (int)iwd, (int)iht, False);
+    pConPriv->fontInfoRecords     = NULL;
+    pConPriv->fontTypeInfoRecords = NULL;
   }
   PsOut_BeginPage(pConPriv->pPsOut, iorient, icount, iplex, ires,
 		  (int)iwd, (int)iht);
@@ -348,15 +365,22 @@
 {
   int                iorient, iplex, icount, ires;
   unsigned short     iwd, iht;
+  char              *title;
   PsContextPrivPtr   pConPriv = 
       (PsContextPrivPtr)pCon->devPrivates[PsContextPrivateIndex].ptr;
 
+  /* get job level attributes */ 
+  title = XpGetOneAttribute(pCon, XPJobAttr, "job-name");
+ 
   /* get document level attributes */
   S_GetPageAttributes(pCon,&iorient,&icount,&iplex,&ires,&iwd,&iht);
 
   pConPriv->pPsOut = PsOut_BeginFile(pConPriv->pJobFile,
-                                   iorient, icount, iplex, ires,
-                                   (int)iwd, (int)iht, (type == XPDocRaw));
+                                     title, iorient, icount, iplex, ires,
+                                     (int)iwd, (int)iht, (Bool)(type == XPDocRaw));
+
+  pConPriv->fontInfoRecords     = NULL;
+  pConPriv->fontTypeInfoRecords = NULL;
 
   return Success;
 }
@@ -391,8 +415,11 @@
     PsContextPrivPtr cPriv;
     PsOutPtr psOut;
 
-    if (len_fmt != 12 || !strcmp(pFmt, "PostScript 2") || len_opt)
+    if (len_fmt != 12 ||
+        strncasecmp(pFmt, "PostScript 2", len_fmt) != 0 ||
+        len_opt)
 	return BadValue;
+
     cPriv = pCon->devPrivates[PsContextPrivateIndex].ptr;
     psOut = cPriv->pPsOut;
 

Index: PsText.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/PsText.c,v
retrieving revision 1.1.4.3
retrieving revision 1.1.4.4
diff -u -d -r1.1.4.3 -r1.1.4.4
--- a/PsText.c	5 Mar 2004 13:39:54 -0000	1.1.4.3
+++ b/PsText.c	21 Apr 2004 10:03:37 -0000	1.1.4.4
@@ -73,49 +73,13 @@
 **    *********************************************************
 ** 
 ********************************************************************/
-/* $XFree86: xc/programs/Xserver/Xprint/ps/PsText.c,v 1.12tsi Exp $ */
 
 #include "Ps.h"
 #include "gcstruct.h"
 #include "windowstr.h"
+#include "fntfil.h"
 #include "fntfilst.h"
-#include <sys/stat.h>
-
-static int readFontName(char *fileName, char *file_name, char *dlfnam)
-{
-    FILE        *file;
-    struct stat statb;
-    char        buf[256];
-    char 	*front, *fn;
-
-    file = fopen(fileName, "r");
-    if(file)
-    {
-        if (fstat (fileno(file), &statb) == -1)
-            return 0;
-	while(fgets(buf, 255, file))
-	{
-	    if((fn = strstr(buf, " -")))
-	    {
-		strcpy(file_name, buf);
-		file_name[fn - buf - 4] = '\0';
-	        fn++;
-	        if((front = strstr(fn, "normal-")))
-	        {
-		    fn[front - fn] = '\0';
-	 	    if(strstr(dlfnam, fn))	
-		    {
-		        fclose(file);
-		        return 1; 
-		    }
-	        }
-	    }
-	}
-    }
-    file_name[0] = '\0';
-    fclose(file);
-    return 0;
-}
+#include <limits.h>
 
 int
 PsPolyText8(
@@ -147,70 +111,97 @@
     elm->c.text8.string = (char *)xalloc(count);
     memcpy(elm->c.text8.string, string, count);
     disp->nelms += 1;
+    
+    return x;
   }
   else
   {
-    char  *fnam, ffname[512], *dlfnam;
-    FontDirectoryPtr    dir;
-    char        file_name[MAXFONTNAMELEN];
+    PsFontInfoRec *firec;
 
-    dir = pGC->font->fpe->private;
-    sprintf(ffname, "%s%s", dir->directory, "fonts.dir"); 
+    /* We need a context for rendering... */
+    if (PsGetPsContextPriv(pDrawable) == NULL)
+      return x;
 
-    fnam = PsGetPSFontName(pGC->font); 
-    if(!fnam){
-	if(!(dlfnam = PsGetFontName(pGC->font))) 
-	    return x;
-	/* If Type1 font, try to download to printer first */
-	if(strstr(ffname, "Type1") && readFontName(ffname, file_name, dlfnam)) 
-	{
-            int          siz;
-            float        mtx[4];
-            PsOutPtr     psOut;
-            ColormapPtr  cMap;
+    firec = PsGetFontInfoRec(pDrawable, pGC->font);
+    if (!firec)
+        return x;
 
-	    if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) 
-		return x; 
-	    sprintf(ffname, "%s%s%s", dir->directory, file_name, ".pfa");
-	    PsOut_DownloadType1(psOut, file_name, ffname);
-            PsOut_Offset(psOut, pDrawable->x, pDrawable->y);
-       	    PsOut_Color(psOut, PsGetPixelColor(cMap, pGC->fgPixel)); 
-       	    siz = PsGetFontSize(pGC->font, mtx);
-       	    if( !siz ) PsOut_TextAttrsMtx(psOut, file_name, mtx, 1); 
-            else PsOut_TextAttrs(psOut, file_name, siz, 1); 
-       	    PsOut_Text(psOut, x, y, string, count, -1);
-	    return x;
-	}
-	{
-	    unsigned long n, i;
-	    int w;
-	    CharInfoPtr charinfo[255];  
+#ifdef XP_USE_FREETYPE    
+    if (firec->ftir->downloadableFont && 
+        (firec->ftir->font_type == PSFTI_FONT_TYPE_FREETYPE))
+    {
+        PsOutPtr       psOut;
+        ColormapPtr    cMap;
+        
+	if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) 
+	    return x; 
 
-	    GetGlyphs(pGC->font, (unsigned long)count, 
-		(unsigned char *)string, Linear8Bit,&n, charinfo);
-	    w = 0;
-	    for (i=0; i < n; i++) w += charinfo[i]->metrics.characterWidth;
-	    if (n != 0)
-	        PsPolyGlyphBlt(pDrawable, pGC, x, y, n, 
-			charinfo, FONTGLYPHS(pGC->font));
-	    x += w;
-	}  
-    }else{
-	int          iso;
-	int          siz;
-	float        mtx[4];
-	PsOutPtr     psOut;
-	ColormapPtr  cMap;
+        if (firec->ftir->alreadyDownloaded[0] == False)
+        {
+            PsOut_DownloadFreeType(psOut,
+                                   firec->ftir->ft_download_font_type,
+                                   firec->ftir->download_ps_name, pGC->font, 0);              
+            firec->ftir->alreadyDownloaded[0] = True;
+        }
 
-	if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) return x;
-	PsOut_Offset(psOut, pDrawable->x, pDrawable->y);
-	PsOut_Color(psOut, PsGetPixelColor(cMap, pGC->fgPixel));
-	siz = PsGetFontSize(pGC->font, mtx);
-	iso = PsIsISOLatin1Encoding(pGC->font);
-	if( !siz ) PsOut_TextAttrsMtx(psOut, fnam, mtx, iso);
-	else       PsOut_TextAttrs(psOut, fnam, siz, iso);
-	PsOut_Text(psOut, x, y, string, count, -1);
+        PsOut_Offset(psOut, pDrawable->x, pDrawable->y);
+       	PsOut_Color(psOut, PsGetPixelColor(cMap, pGC->fgPixel)); 
+       	if (!firec->size)
+            PsOut_TextAttrsMtx(psOut, firec->ftir->download_ps_name, firec->mtx, firec->ftir->is_iso_encoding); 
+        else
+            PsOut_TextAttrs(psOut, firec->ftir->download_ps_name, firec->size, firec->ftir->is_iso_encoding); 
+        PsOut_FreeType_Text(pGC->font, psOut, x, y, string, count);
+
+	return x;	
     }
+    else
+#endif /* XP_USE_FREETYPE */
+         if (firec->ftir->downloadableFont && 
+             (firec->ftir->font_type != PSFTI_FONT_TYPE_FREETYPE))
+    {
+        PsOutPtr       psOut;
+        ColormapPtr    cMap;
+        
+	if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) 
+	    return x; 
+
+        if (firec->ftir->alreadyDownloaded[0] == False)
+        {
+            PsOut_DownloadType1(psOut, "PsPolyText8",
+                                firec->ftir->download_ps_name, firec->ftir->filename);
+            firec->ftir->alreadyDownloaded[0] = True;
+        }
+
+        PsOut_Offset(psOut, pDrawable->x, pDrawable->y);
+       	PsOut_Color(psOut, PsGetPixelColor(cMap, pGC->fgPixel)); 
+       	if (!firec->size)
+            PsOut_TextAttrsMtx(psOut, firec->ftir->download_ps_name, firec->mtx, firec->ftir->is_iso_encoding); 
+        else
+            PsOut_TextAttrs(psOut, firec->ftir->download_ps_name, firec->size, firec->ftir->is_iso_encoding); 
+        PsOut_Text(psOut, x, y, string, count, -1);
+
+	return x;	
+    }    
+    
+    /* Render glyphs as bitmaps */
+    {
+        unsigned long n, i;
+        int w;
+        CharInfoPtr charinfo[255];  
+
+        GetGlyphs(pGC->font, (unsigned long)count, 
+            (unsigned char *)string, Linear8Bit, &n, charinfo);
+        w = 0;
+        for (i=0; i < n; i++)
+          w += charinfo[i]->metrics.characterWidth;
+
+        if (n != 0)
+            PsPolyGlyphBlt(pDrawable, pGC, x, y, n, 
+                    charinfo, FONTGLYPHS(pGC->font));
+        x += w;
+        
+        return x;
+    }  
   }
   return x;
 }
@@ -246,21 +237,136 @@
       (unsigned short *)xalloc(count*sizeof(unsigned short));
     memcpy(elm->c.text16.string, string, count*sizeof(unsigned short));
     disp->nelms += 1;
+
+    return x;
   }
   else
   {
-    unsigned long n, i;
-    int w;
-    CharInfoPtr charinfo[255];  /* encoding only has 1 byte for count */
+    PsFontInfoRec *firec;
 
-    GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)string,
-              (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit,
-              &n, charinfo);
-    w = 0;
-    for (i=0; i < n; i++) w += charinfo[i]->metrics.characterWidth;
-    if (n != 0)
-	PsPolyGlyphBlt(pDrawable, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font));
-    x += w;
+    /* We need a context for rendering... */
+    if (PsGetPsContextPriv(pDrawable) == NULL)
+      return x;
+
+    firec = PsGetFontInfoRec(pDrawable, pGC->font);
+    if (!firec)
+        return x;
+
+#ifdef XP_USE_FREETYPE    
+    if (firec->ftir->downloadableFont &&
+        (firec->ftir->font_type == PSFTI_FONT_TYPE_FREETYPE))
+    {
+        PsOutPtr       psOut;
+        ColormapPtr    cMap;
+        unsigned short c,
+                       c_hiByte,
+                       c_lowByte,
+                       fontPage;
+        int            i;
+        
+	if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) 
+	    return x; 
+
+        /* Scan the string we want to render and download all neccesary parts
+         * of the font (one part(="font page") has 256 glyphs)
+         */
+        for( i = 0 ; i < count ; i++ )
+        {
+            c = string[i];
+#if IMAGE_BYTE_ORDER == LSBFirst
+            c_hiByte = c & 0x00FF;
+            c_lowByte = (c >> 8) & 0x00FF;
+#elif IMAGE_BYTE_ORDER == MSBFirst
+            c_hiByte  = (c >> 8) & 0x00FF;
+            c_lowByte = c & 0x00FF;
+#else
+#error Unsupported byte order
+#endif
+            fontPage  = c_hiByte;
+          
+            if (firec->ftir->alreadyDownloaded[fontPage] == False)
+            {
+                char        buffer[256];
+                const char *ps_name;
+
+                if (fontPage > 0)
+                {
+                    sprintf(buffer, "%s_%x", firec->ftir->download_ps_name, (int)fontPage);
+                    ps_name = buffer;
+                }
+                else
+                {
+                    ps_name = firec->ftir->download_ps_name;
+                }
+
+                PsOut_DownloadFreeType(psOut,
+                                       firec->ftir->ft_download_font_type,
+                                       ps_name, pGC->font, (fontPage * 0x100)); /* same as (fontPage << 8) */    
+                                 
+                firec->ftir->alreadyDownloaded[fontPage] = True;
+            }
+        }
+
+
+        PsOut_Offset(psOut, pDrawable->x, pDrawable->y);
+       	PsOut_Color(psOut, PsGetPixelColor(cMap, pGC->fgPixel)); 
+       	if (!firec->size)
+            PsOut_FreeType_TextAttrsMtx16(psOut, firec->ftir->download_ps_name, firec->mtx, firec->ftir->is_iso_encoding); 
+        else
+            PsOut_FreeType_TextAttrs16(psOut, firec->ftir->download_ps_name, firec->size, firec->ftir->is_iso_encoding); 
+        PsOut_FreeType_Text16(pGC->font, psOut, x, y, string, count);
+        
+	return x;	
+    }
+    else
+#endif /* XP_USE_FREETYPE */
+         if (firec->ftir->downloadableFont &&
+             (firec->ftir->font_type != PSFTI_FONT_TYPE_FREETYPE))
+    {
+        PsOutPtr       psOut;
+        ColormapPtr    cMap;
+        unsigned short c,
+                       c_hiByte,
+                       c_lowByte,
+                       fontPage;
+        int            i;
+        
+	if( PsUpdateDrawableGC(pGC, pDrawable, &psOut, &cMap)==FALSE ) 
+	    return x; 
+
+        PsOut_DownloadType1(psOut, "PsPolyText16",
+                            firec->ftir->download_ps_name, firec->ftir->filename);
+        firec->ftir->alreadyDownloaded[fontPage] = True;
+
+        PsOut_Offset(psOut, pDrawable->x, pDrawable->y);
+       	PsOut_Color(psOut, PsGetPixelColor(cMap, pGC->fgPixel)); 
+       	if (!firec->size)
+            PsOut_TextAttrsMtx(psOut, firec->ftir->download_ps_name, firec->mtx, firec->ftir->is_iso_encoding); 
+        else
+            PsOut_TextAttrs(psOut, firec->ftir->download_ps_name, firec->size, firec->ftir->is_iso_encoding); 
+        PsOut_Text16(psOut, x, y, string, count, -1);
+        
+	return x;	
+    }
+    
+    /* Render glyphs as bitmaps */
+    {
+        unsigned long n, i;
+        int w;
+        CharInfoPtr charinfo[255];  /* encoding only has 1 byte for count */
+
+        GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)string,
+                  (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit,
+                  &n, charinfo);
+        w = 0;
+        for (i=0; i < n; i++)
+          w += charinfo[i]->metrics.characterWidth;
+        if (n != 0)
+	    PsPolyGlyphBlt(pDrawable, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font));
+        x += w;
+        
+        return x;
+    }  
   }
   return x;
 }
@@ -386,7 +492,7 @@
   pointer       pGlyphBase)
 {
     int width, height;
-    PixmapPtr pPixmap = NullPixmap;
+    PixmapPtr pPixmap;
     int nbyLine;                        /* bytes per line of padded pixmap */
     FontPtr pfont;
     GCPtr pGCtmp;
@@ -399,7 +505,7 @@
     int gWidth, gHeight;                /* width and height of glyph */
     register int nbyGlyphWidth;         /* bytes per scanline of glyph */
     int nbyPadGlyph;                    /* server padded line of glyph */
-    int w;
+    int w, tmpx;
     XID gcvals[3];
 
     pfont = pGC->font;
@@ -435,6 +541,7 @@
         PsDestroyPixmap(pPixmap);
         return;
     }
+    tmpx = 0;
     while(nGlyphs--)
     {
         pci = *pCharInfo++;
@@ -466,8 +573,9 @@
 		   1, x + pci->metrics.leftSideBearing, 
 		   y - pci->metrics.ascent, gWidth, gHeight,
                    0, XYBitmap, (char *)pb);
-	    x  += pci->metrics.characterWidth;
 	}
+        
+        x  += pci->metrics.characterWidth;
     }
     DEALLOCATE_LOCAL(pbits);
     FreeScratchGC(pGCtmp);

Index: PsWindow.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/PsWindow.c,v
retrieving revision 1.1.4.3
retrieving revision 1.1.4.4
diff -u -d -r1.1.4.3 -r1.1.4.4
--- a/PsWindow.c	5 Mar 2004 13:39:54 -0000	1.1.4.3
+++ b/PsWindow.c	21 Apr 2004 10:03:37 -0000	1.1.4.4
@@ -73,11 +73,9 @@
 **    *********************************************************
 ** 
 ********************************************************************/
-/* $XFree86: xc/programs/Xserver/Xprint/ps/PsWindow.c,v 1.12tsi Exp $ */
 
 #include <stdio.h>
 #include <string.h>
-#include <sys/types.h>
 #include <sys/wait.h>
 
 #include "mistruct.h"
@@ -87,7 +85,8 @@
 
 #include "Ps.h"
 
-#if 0
+extern WindowPtr *WindowTable;
+
 /*
  * The following list of strings defines the properties which will be
  * placed on the screen's root window if the property was defined in
@@ -104,7 +103,7 @@
 	DT_PRINT_PAGE_COMMAND,
 	(char *)NULL
 };
-#endif
+
 
 /*
  * PsCreateWindow - watch for the creation of the root window.
@@ -219,6 +218,8 @@
   RegionPtr pRegion,
   int       what)
 {
+  int       status;
+  WindowPtr pRoot;
 
 #define FUNCTION        0
 #define FOREGROUND      1
@@ -298,6 +299,7 @@
   gcmask |= GCFunction | GCClipMask;
 
   i = pScreen->myNum;
+  pRoot = WindowTable[i];
 
   pBgWin = pWin;
   if (what == PW_BORDER)
@@ -375,14 +377,14 @@
         }
         break;
       case GCClipMask:
-        if( (pointer)(long)pGC->clientClipType!=(pointer)CT_NONE )
+        if( (pointer)pGC->clientClipType!=(pointer)CT_NONE )
         {
           gcmask |= index;
           gcval[i++] = (pointer)CT_NONE;
         }
         break;
       case GCSubwindowMode:
-        if( (pointer)(long)pGC->subWindowMode!=newValues[SUBWINDOW] )
+        if( (pointer)pGC->subWindowMode!=newValues[SUBWINDOW] )
         {
           gcmask |= index;
           gcval[i++] = newValues[SUBWINDOW];
@@ -396,7 +398,7 @@
         }
         break;
       case GCFillStyle:
-        if( (pointer)(long)pGC->fillStyle!=newValues[FILLSTYLE] )
+        if( (pointer)pGC->fillStyle!=newValues[FILLSTYLE] )
         {
           gcmask |= index;
           gcval[i++] = newValues[FILLSTYLE];

Index: psout.c
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/psout.c,v
retrieving revision 1.1.4.2
retrieving revision 1.1.4.3
diff -u -d -r1.1.4.2 -r1.1.4.3
--- a/psout.c	5 Mar 2004 13:39:54 -0000	1.1.4.2
+++ b/psout.c	21 Apr 2004 10:03:37 -0000	1.1.4.3
@@ -73,79 +73,17 @@
 **    *********************************************************
 **
 ********************************************************************/
-/* $XFree86: xc/programs/Xserver/Xprint/ps/psout.c,v 1.11 2001/12/19 21:55:59 dawes Exp $ */
-
-/*      
- * For XFree86 3.3.3:  
- *      
- * As a *quick* way of preventing some buffers overflowing onto the stack,
- * they have been made static.  There are potential problems with
- * PsOutRec.Buf overflowing too which should be investigated as part of a
- * review of this code, but that is at least always allocated with malloc
- * and shouldn't pose an immediate stack trashing problem.
- *
- */
 
 #include <stdlib.h>
+#include <stdio.h>
 #include "os.h"
-#include "Ps.h"
+#define USE_PSOUT_PRIVATE 1
 #include "psout.h"
+/* For VENDOR_STRING and VENDOR_RELEASE */
+#include "site.h"
 
-typedef void *voidPtr;
-
-typedef struct PsPatRec_
-{
-  PsFillEnum type;
-  voidPtr    tag;
-} PsPatRec;
-
-typedef PsPatRec *PsPatPtr;
-
-typedef struct PsOutRec_
-{
-  FILE       *Fp;
-  char        Buf[256];
-  int         CurColor;
-  int         LineWidth;
-  PsCapEnum   LineCap;
-  PsJoinEnum  LineJoin;
-  int         NDashes;
-  int        *Dashes;
-  int         DashOffset;
-  int         LineBClr;
-  PsRuleEnum  FillRule;
-  char       *FontName;
-  int         FontSize;
-  float       FontMtx[4];
-  int         ImageFormat;
-  int         RevImage;
-  int         NPatterns;
-  int         MxPatterns;
-  PsPatPtr    Patterns;
-  int         ClipType;
-  PsClipRec   Clip;
-  int         InFrame;
-  int         XOff;
-  int         YOff;
-
-  PsFillEnum  InTile;
-  int         ImgSkip;
-  int         ImgBClr;
-  int         ImgFClr;
-  int         ImgX;
-  int         ImgY;
-  int         ImgW;
-  int         ImgH;
-  int         SclW;
-  int         SclH;
-
-  int         NDownloads;
-  int         MxDownloads;
-  char      **Downloads;
-  Bool        isRaw;
-
-  int         start_image;
-} PsOutRec;
+extern PsElmPtr PsCloneFillElementList(int nElms, PsElmPtr elms);
+extern void PsDestroyFillElementList(int nElms, PsElmPtr elms);
 
 /*
  *  Standard definitions
@@ -174,6 +112,7 @@
 /ie{ifelse}bd\
 /len{length}bd\
 /m{moveto}bd\
+/rm{rmoveto}bd\
 /l{lineto}bd\
 /rl{rlineto}bd\
 /a{arc}bd\
@@ -236,7 +175,11 @@
 /mp{makepattern}bd\
 /spt{setpattern}bd\
 /spd{setpagedevice}bd\
-";
+"
+#ifdef XP_USE_FREETYPE
+"/trmoveto{currentfont /FontMatrix get transform rm}d"
+#endif /* XP_USE_FREETYPE */
+;
 
 /*
  *  Composite definitions
@@ -341,7 +284,6 @@
 /mtx{scl t [3 i 0 0 5 i 0 0]}bd \
 ";
 
-int  pagenum = 0;
 char *pg_orient[] = {"Portrait","Landscape","Reverse Portrait","Reverse Landscape"};
 /*
  *  Setup definitions
@@ -360,7 +302,7 @@
  *                       PRIVATE FUNCTIONS                         *
  *******************************************************************/
 
-static void
+void
 S_Flush(PsOutPtr self)
 {
   if( self->Buf[0] )
@@ -388,7 +330,7 @@
 {
   int  i, k=0;
   S_Flush(self);
-  memset(self->Buf, 0, 256);
+  memset(self->Buf, 0, sizeof(self->Buf));
   for( i=0 ; defs[i]!='\0' ;)
   {
     if( k>70 && (i==0 || (i && defs[i-1]!='/')) &&
@@ -396,7 +338,7 @@
     {
       S_Flush(self);
       k = 0;
-      memset(self->Buf, 0, 256);
+      memset(self->Buf, 0, sizeof(self->Buf));
     }
     if( k && self->Buf[k-1]==' ' && defs[i]==' ' ) { i++; continue; }
     self->Buf[k] = defs[i];
@@ -405,11 +347,11 @@
   S_Flush(self);
 }
 
-static void
+void
 S_OutNum(PsOutPtr self, float num)
 {
   int  i;
-  static char buf[64];
+  char buf[64];
   sprintf(buf, "%.3f", num);
   for( i=strlen(buf)-1 ; buf[i]=='0' ; i-- ); buf[i+1] = '\0';
   if( buf[strlen(buf)-1]=='.' ) buf[strlen(buf)-1] = '\0';
@@ -422,7 +364,7 @@
 S_OutStr(PsOutPtr self, char *txt, int txtl)
 {
   int  i, k;
-  static char buf[512];
+  char buf[1024];
   for( i=0,k=0 ; i<txtl ; i++ )
   {
     if( (txt[i]>=' ' && txt[i]<='~') &&
@@ -430,7 +372,9 @@
       { buf[k] = txt[i]; k++; continue; }
     buf[k] = '\\'; k++;
     sprintf(&buf[k], "%03o", txt[i]&0xFF);
-    k += 3;
+    /* Skip to the end of the buffer */
+    while( buf[k] != '\0' )
+      k++;
   }
   strcat(self->Buf, "(");
   i = strlen(self->Buf);
@@ -440,7 +384,32 @@
   if( strlen(self->Buf)>70 ) S_Flush(self);
 }
 
+/* Same as S_OutStr() but takes |short *| instead of |char *| */
 static void
+S_OutStr16(PsOutPtr self, unsigned short *txt, int txtl)
+{
+  int  i, k;
+  char buf[2048];
+  for( i=0,k=0 ; i<txtl ; i++ )
+  {
+    if( (txt[i]>=' ' && txt[i]<='~') &&
+        txt[i]!='(' && txt[i]!=')' && txt[i]!='\\' )
+      { buf[k] = txt[i]; k++; continue; }
+    buf[k] = '\\'; k++;
+    sprintf(&buf[k], "%03o", txt[i]&0xFFFF);
+    /* Skip to the end of the buffer */
+    while( buf[k] != '\0' )
+      k++;
+  }
+  strcat(self->Buf, "(");
+  i = strlen(self->Buf);
+  memcpy(&self->Buf[i], buf, k);
+  self->Buf[i+k] = '\0';
+  strcat(self->Buf, ")");
+  if( strlen(self->Buf)>70 ) S_Flush(self);
+}
+
+void
 S_OutTok(PsOutPtr self, char *tok, int cr)
 {
   if( self->Buf[0] ) strcat(self->Buf, " ");
@@ -471,6 +440,27 @@
     float fwd = ((float)wd/(float)res)*72.;
     float fht = ((float)ht/(float)res)*72.;
 
+#define USE_WORKAROUND_COPY_COUNT_BUG 1
+
+#ifdef USE_WORKAROUND_COPY_COUNT_BUG
+    /* Workaround (see http://xprint.mozdev.org/bugs/show_bug.cgi?id=1861 -
+     * 'Need workaround for bug 1378 ...') to avoid that we print n^2 copies
+     * instead of n copies.
+     * The problem is that we use both /NumCopies here but pass the
+     * %copy-count% to the spooler, too.
+     * But we only have to use _one_ way...
+     *
+     * The final fix for bug 1378 (http://xprint.mozdev.org/bugs/show_bug.cgi?id=1378 -
+     * "PS DDX creates n^2 copies of a job instead of n copies") will back this
+     * workaround out and replace it with a better solution.
+     * (see mozilla.org bug 140030
+     * (http://bugzilla.mozilla.org/show_bug.cgi?id=140030 - "Setting number
+     * of copies causes too many copies to print") for the initial report for
+     * this issue...)
+     */
+    count = 1;
+#endif /* USE_WORKAROUND_COPY_COUNT_BUG */
+
     S_OutTok(self, "/pWd", 0);
     S_OutNum(self, fwd);
     S_OutTok(self, "d /pHt", 0);
@@ -577,10 +567,11 @@
 }
 
 PsOutPtr
-PsOut_BeginFile(FILE *fp, int orient, int count, int plex, int res,
+PsOut_BeginFile(FILE *fp, char *title, int orient, int count, int plex, int res,
                 int wd, int ht, Bool raw)
 {
   int  i;
+  char buffer[256+32]; /* enougth space for a title with 256 chars... */
 /*
  *  Get ready to output PostScript header
  */
@@ -589,15 +580,25 @@
   memset(psout, 0, sizeof(PsOutRec));
   psout->Fp = fp;
   psout->isRaw = raw;
-  pagenum = 0;
+  psout->pagenum = 0;
 
   if (!raw) {
 /*
  *  Output PostScript header
  */
-      S_Comment(psout, "%!PS-Adobe-3.0 EPSF-3.0");
-      S_Comment(psout, "%%Creator: The Open Group PostScript Print Server");
-      /*### BoundingBox ###*/
+      /* GhostScript will rant about the missing BoundingBox if we use
+       * "%!PS-Adobe-3.0 EPSF-3.0" here... */
+      S_Comment(psout, "%!PS-Adobe-3.0");
+      sprintf(buffer, 
+              "%%%%Creator: The X Print Server's PostScript DDX (%s, release %d)",
+              VENDOR_STRING, VENDOR_RELEASE);
+      S_Comment(psout, buffer);
+
+      if (title)
+      {
+        sprintf(buffer, "%%%%Title: %.256s", title);
+        S_Comment(psout, buffer);
+      }
       S_Comment(psout, "%%EndComments");
       S_Comment(psout, "%%BeginProlog");
       S_Comment(psout, "%%BeginProcSet: XServer_PS_Functions");
@@ -634,10 +635,13 @@
 {
   char coms[50];
   int  i;
+  
+  if (!self)
+    return;
 
   if (!self->isRaw) {
       S_Comment(self,"%%Trailer");
-      sprintf(coms,"%%%%Pages: %d",pagenum);
+      sprintf(coms,"%%%%Pages: %d", self->pagenum);
       S_Comment(self, coms);
       S_Comment(self, "%%EOF");
   }
@@ -646,9 +650,6 @@
   if( self->Patterns ) xfree(self->Patterns);
   if( self->Clip.rects ) xfree(self->Clip.rects);
   if( closeFile ) fclose(self->Fp);
-  for( i=0 ; i<self->NDownloads ; i++ ) xfree(self->Downloads[i]);
-  if( self->Downloads ) xfree(self->Downloads);
-  pagenum = 0; /* reset page num back to 0 */
   xfree(self);
 }
 
@@ -661,8 +662,8 @@
 /*** comment for pagenumbers *****/
 
   S_Comment(self,"%%PageHeader");
-  pagenum++;
-  sprintf(coms,"%%%%Page: %d %d",pagenum,pagenum);
+  self->pagenum++;
+  sprintf(coms,"%%%%Page: %d %d", self->pagenum, self->pagenum);
   S_Comment(self, coms);
   sprintf(coms,"%%%%PageOrientation: %s",pg_orient[orient]);
   S_Comment(self, coms);
@@ -959,7 +960,7 @@
 PsOut_TextAttrs(PsOutPtr self, char *fnam, int siz, int iso)
 {
   int       i;
-  static char      buf[256];
+  char      buf[256];
   if( self->FontName && strcmp(fnam, self->FontName)==0 &&
       siz==self->FontSize ) return;
   if( self->FontName ) xfree(self->FontName);
@@ -979,7 +980,7 @@
 PsOut_TextAttrsMtx(PsOutPtr self, char *fnam, float *mtx, int iso)
 {
   int       i;
-  static char      buf[256];
+  char      buf[256];
   if( self->FontName && strcmp(fnam, self->FontName)==0 &&
       mtx[0]==self->FontMtx[0] && mtx[1]==self->FontMtx[1] &&
       mtx[2]==self->FontMtx[2] && mtx[3]==self->FontMtx[3] ) return;
@@ -1171,6 +1172,30 @@
   }
 }
 
+void
+PsOut_Text16(PsOutPtr self, int x, int y, unsigned short *text, int textl, int bclr)
+{
+  int  xo = self->XOff;
+  int  yo = self->YOff;
+
+  if( self->InFrame || self->InTile ) xo = yo = 0;
+  x += xo; y += yo;
+  S_OutStr16(self, text, textl);
+  S_OutNum(self, (float)x);
+  S_OutNum(self, (float)y);
+  if( bclr<0 ) S_OutTok(self, "T", 1);
+  else
+  {
+    int ir = bclr>>16;
+    int ig = (bclr>>8)&0xFF;
+    int ib = bclr&0xFF;
+    S_OutNum(self, (float)ir/255.);
+    S_OutNum(self, (float)ig/255.);
+    S_OutNum(self, (float)ib/255.);
+    S_OutTok(self, "Tb", 1);
+  }
+}
+
 #ifdef BM_CACHE
 void  /* new */
 PsOut_ImageCache(PsOutPtr self, int x, int y, long cache_id, int bclr, int fclr)
@@ -1181,7 +1206,7 @@
 
   if( self->InFrame || self->InTile ) xo = yo = 0;
   x += xo; y += yo;
-  sprintf(cacheID, "c%ldi", cache_id);
+  sprintf(cacheID, "c%di", cache_id);
 
   S_OutNum(self, (float)x);
   S_OutNum(self, (float)y);
@@ -1214,7 +1239,7 @@
 {
   char cacheID[10];
 
-  sprintf(cacheID, "/c%ldi {", cache_id);
+  sprintf(cacheID, "/c%di {", cache_id);
 
   S_OutTok(self, cacheID, 0);
 }     /* new */
@@ -1225,7 +1250,7 @@
   S_OutTok(self, "}bd", 1);
 }     /* new */
 #endif
-              
+
 void
 PsOut_BeginImage(PsOutPtr self, int bclr, int fclr, int x, int y,
                  int w, int h, int sw, int sh, int format)
@@ -1488,13 +1513,11 @@
   }
   self->Patterns[self->NPatterns].tag  = tag;
   self->Patterns[self->NPatterns].type = type;
-  sprintf(key, "/ %ld", (long)tag);
+  sprintf(key, "/ %d", (int)tag);
   switch(type) {
     case PsTile:   key[1] = 't'; break;
     case PsStip:   key[1] = 's'; break;
-    case PsOpStip: key[1] = 'o'; break;
-    default: break;
-  }
+    case PsOpStip: key[1] = 'o'; break; }
   S_OutTok(self, key, 0);
   S_OutTok(self, "db/PatternType 1 d/PaintType 1 d", 0);
   S_OutTok(self, "/TilingType 1 d/BBox[0 0", 0);
@@ -1535,13 +1558,11 @@
   for( i=0 ; i<self->NPatterns ; i++ )
     { if( tag==self->Patterns[i].tag && type==self->Patterns[i].type ) break; }
   if( i>=self->NPatterns ) return;
-  sprintf(key, " %ld", (long)tag);
+  sprintf(key, " %d", (int)tag);
   switch(type) {
     case PsTile:   key[0] = 't'; break;
     case PsStip:   key[0] = 's'; break;
-    case PsOpStip: key[0] = 'o'; break;
-    default: break;
-  }
+    case PsOpStip: key[0] = 'o'; break; }
   S_OutTok(self, key, 0);
   S_OutTok(self, "spt", 1);
   self->CurColor = 0xFFFFFFFF;
@@ -1556,83 +1577,141 @@
     }
 }
 
-void
-PsOut_DownloadType1(PsOutPtr self, char *name, char *fname)
+typedef enum PsDownfontFontType_  
+{ 
+  PsDFT_Type1PFA=0,
+  PsDFT_Type1PFB,
+  PsDFT_TrueType /* not implemented yet */
+} PsDownfontFontType;
+
+/* Download a PS Type1 font */
+int
+PsOut_DownloadType1(PsOutPtr self, const char *auditmsg, const char *name, const char *fname)
 {
   int     i;
   int     stt;
-  static char    buf[256];
+  char    buf[256];
   FILE   *fp;
+  PsDownfontFontType type;
 
-  for( i=0 ; i<self->NDownloads ; i++ )
-    { if( strcmp(name, self->Downloads[i])==0 ) break; }
-  if( i<self->NDownloads ) return;
+  fp = fopen(fname, "r");
+  if( !fp )
+    return 0;
 
-  if( (self->NDownloads+1)>self->MxDownloads )
+#ifdef DEBUG_gisburn
+  /* This should be log-able! */
+  fprintf(stderr, "PsOut_DownloadType1: %s: Downloading '%s' from '%s'\n", auditmsg, name, fname);
+#endif /* DEBUG_gisburn */
+
+  fread(buf, 32, 1, fp);
+  fseek(fp, (long)0, 0);
+
+  /* Is this a Adobe PostScript Type 1 binary font (PFB) ? */
+  if( (buf[0]&0xFF)==0x80 && (buf[1]&0xFF)==0x01 )
   {
-    if( self->NDownloads )
-    {
-      self->MxDownloads *= 2;
-      self->Downloads = (char **)xrealloc(self->Downloads,
-                                self->MxDownloads*sizeof(char *));
-    }
-    else
-    {
-      self->MxDownloads = 32;
-      self->Downloads = (char **)xalloc(self->MxDownloads*sizeof(char *));
-    }
+    type = PsDFT_Type1PFB;
+  }  
+  /* Is this a Adobe PostScript ASCII font (PFA) ? */
+  else if (!strncmp(buf, "%!PS-AdobeFont", 14))
+  {
+    type = PsDFT_Type1PFA;
   }
-
-  self->Downloads[self->NDownloads] = (char *)xalloc(strlen(name)+1);
-  strcpy(self->Downloads[self->NDownloads], name);
-  self->NDownloads += 1;
+  else
+  {
+    /* This should be log-able! */
+    fprintf(stderr, "PsOut_DownloadType1: Unknown font type for '%s'\n", fname);
+    return 0;
+  }      
 
   S_Flush(self);
   sprintf(buf, "%%%%BeginFont: %s", name);
   S_Comment(self, buf);
-  fp = fopen(fname, "r");
-  if( !fp ) return;
-  fread(buf, 1, 1, fp);
-  fseek(fp, (long)0, 0);
-  if( (buf[0]&0xFF)==0x80 )
+
+  if( type == PsDFT_Type1PFB )
   {
-    int  len;
+    char *buf, 
+         *pt;
+    int   len, 
+          ch,
+          stype;
 
-    for(;;)
+    ch = fgetc(fp);  
+    /* Strip out the binary headers and de-binary it */
+    while( (ch&0xFF) == 0x80 ) 
     {
-      stt = fread(buf, 1, 2, fp);
-      if( stt!=2 || (buf[0]&0xFF)!=0x80 ) break;
-      if( (int)buf[1]<1 || (int)buf[1]>2 ) break;
-      stt = fread(buf, 1, 4, fp);
-      if( stt!=4 ) break;
-      len = ((buf[3]&0xFF)<<24)|((buf[2]&0xFF)<<16)|
-            ((buf[1]&0xFF)<<8)|(buf[0]&0xFF);
-      for(; len ;)
+      stype = fgetc(fp);
+      if( stype==3 ) /* eof mark */
+        break;
+      len = fgetc(fp);
+      len |= fgetc(fp)<<8;
+      len |= fgetc(fp)<<16;
+      len |= fgetc(fp)<<24;
+      buf = (char *)xalloc(len+1);
+      if( stype==1 ) 
       {
-        i = len<256 ? len : 256;
-        stt = fread(buf, 1, i, fp);
-        if( stt<=0 ) break;
-        if (!ferror(self->Fp)) {
-	    (void) fwrite(buf, 1, stt, self->Fp);
-	}
-        if( stt<i ) break;
-        len -= i;
+        /* Process ASCII section */
+        len = fread(buf, 1, len, fp);
+        /* convert any lone CRs (ie Mac eol) to LFs */
+        for( pt = buf ; (pt = memchr(pt, '\r', len-(pt-buf))) != NULL ; pt++ ) 
+        {
+          if ( pt[1]!='\n' ) 
+            *pt = '\n';
+        }
+        fwrite(buf, 1, len, self->Fp);
+      } 
+      else if( stype==2 ) 
+      {
+        int i;
+        
+        /* Process binary section */
+        len = fread(buf, 1, len, fp);
+        for( i=0 ; i<len ; i++ ) 
+        {
+          ch = buf[i];
+          if( ((ch>>4)&0xf) <= 9 )
+            fputc('0'+((ch>>4)&0xf), self->Fp);
+          else
+            fputc('A'-10+((ch>>4)&0xf), self->Fp);
+          
+          if( (ch&0xf) <= 9 )
+            fputc('0'+(ch&0xf), self->Fp);
+          else
+            fputc('A'-10+(ch&0xf), self->Fp);
+          
+          if( (i&0x1f)==0x1f )
+              fputc('\n', self->Fp);
+        }
       }
+      xfree(buf);
+      
+      /* Next block... */
+      ch = fgetc(fp);
     }
   }
-  else
+  /* Is this a Adobe PostScript ASCII font (PFA) ? */
+  else if (type == PsDFT_Type1PFA)
   {
     for(;;)
     {
       stt = fread(buf, 1, 256, fp);
       if( stt<=0 ) break;
       if (!ferror(self->Fp)) {
-	  (void) fwrite(buf, 1, stt, self->Fp);
+        (void) fwrite(buf, 1, stt, self->Fp);
       }
-      if( stt<256 ) break;
+      if( stt<256 )
+        break;
     }
   }
   fclose(fp);
   S_Flush(self);
   S_Comment(self, "%%EndFont");
+  
+  /* Success... */
+  return 1;
 }
+
+
+
+
+
+

Index: psout.h
===================================================================
RCS file: /cvs/xorg/xc/programs/Xserver/Xprint/ps/psout.h,v
retrieving revision 1.1.4.2
retrieving revision 1.1.4.3
diff -u -d -r1.1.4.2 -r1.1.4.3
--- a/psout.h	5 Mar 2004 13:39:54 -0000	1.1.4.2
+++ b/psout.h	21 Apr 2004 10:03:37 -0000	1.1.4.3
@@ -57,7 +57,6 @@
  * or other dealings in this Software without prior written authorization
  * from said copyright holders.
  */
-/* $XFree86: xc/programs/Xserver/Xprint/ps/psout.h,v 1.4 2001/12/14 19:59:18 dawes Exp $ */
 
 /*******************************************************************
 **
@@ -147,10 +146,80 @@
 
 typedef PsClipRec *PsClipPtr;
 
+typedef enum PsFTDownloadFontType_ 
+{ 
+  PsFontBitmap=0,
+  PsFontType1,
+  PsFontType3
+} PsFTDownloadFontType;
+
+#ifdef USE_PSOUT_PRIVATE
+typedef void *voidPtr;
+
+typedef struct PsPatRec_
+{
+  PsFillEnum type;
+  voidPtr    tag;
+} PsPatRec;
+
+typedef PsPatRec *PsPatPtr;
+
+typedef struct PsOutRec_
+{
+  FILE       *Fp;
+  char        Buf[16384];
+  int         CurColor;
+  int         LineWidth;
+  PsCapEnum   LineCap;
+  PsJoinEnum  LineJoin;
+  int         NDashes;
+  int        *Dashes;
+  int         DashOffset;
+  int         LineBClr;
+  PsRuleEnum  FillRule;
+  char       *FontName;
+  int         FontSize;
+  float       FontMtx[4];
+  int         ImageFormat;
+  int         RevImage;
+  int         NPatterns;
+  int         MxPatterns;
+  PsPatPtr    Patterns;
+  int         ClipType;
+  PsClipRec   Clip;
+  int         InFrame;
+  int         XOff;
+  int         YOff;
+
+  PsFillEnum  InTile;
+  int         ImgSkip;
+  int         ImgBClr;
+  int         ImgFClr;
+  int         ImgX;
+  int         ImgY;
+  int         ImgW;
+  int         ImgH;
+  int         SclW;
+  int         SclH;
+
+  Bool        isRaw;
+  
+  int         pagenum;
+
+  int         start_image;
+} PsOutRec;
+
 typedef struct PsOutRec_ *PsOutPtr;
 
-extern PsOutPtr PsOut_BeginFile(FILE *fp, int orient, int count, int plex,
-                              int res, int wd, int ht, Bool raw);
+extern void S_Flush(PsOutPtr self);
+extern void S_OutNum(PsOutPtr self, float num);
+extern void S_OutTok(PsOutPtr self, char *tok, int cr);
+#else
+typedef struct PsOutRec_ *PsOutPtr;
+#endif /* USE_PSOUT_PRIVATE */
+
+extern PsOutPtr PsOut_BeginFile(FILE *fp, char *title, int orient, int count, int plex,
+                                int res, int wd, int ht, Bool raw);
 extern void PsOut_EndFile(PsOutPtr self, int closeFile);
 extern void PsOut_BeginPage(PsOutPtr self, int orient, int count, int plex,
                             int res, int wd, int ht);
@@ -182,8 +251,9 @@
 
 extern void PsOut_Text(PsOutPtr self, int x, int y, char *text, int textl,
                        int bclr);
+extern void PsOut_Text16(PsOutPtr self, int x, int y, unsigned short *text, int textl, int bclr);
 
-extern void PsOut_BeginImage(PsOutPtr self, int bclr, int fclr, int x, int y,
+extern void PsOut_BeginImage(PsOutPtr self, int bclr, int  fclr, int x, int y,
                              int w, int h, int sw, int sh, int format);
 extern void PsOut_BeginImageIM(PsOutPtr self, int bclr, int fclr, int x, int y,
                                int w, int h, int sw, int sh, int format);
@@ -200,16 +270,17 @@
 extern void PsOut_SetPattern(PsOutPtr self, void *tag, PsFillEnum type);
 
 extern void PsOut_RawData(PsOutPtr self, char *data, int len);
-extern void PsOut_DownloadType1(PsOutPtr self, char *name, char *fname);
 
-#ifdef BM_CACHE
-extern void PsOut_BeginImageCache(PsOutPtr self, long cache_id);
-extern void PsOut_EndImageCache(PsOutPtr self);
-extern void PsOut_ImageCache(PsOutPtr self, int x, int y, long cache_id,
-			     int bclr, int fclr);
-#endif
+extern int  PsOut_DownloadType1(PsOutPtr self, const char *auditmsg, const char *name, const char *fname);
 
-extern FILE *PsOut_ChangeFile(PsOutPtr self, FILE *fp);
+extern int  PsOut_DownloadFreeType1(PsOutPtr self, const char *psfontname, FontPtr pFont, long block_offset);
+extern int  PsOut_DownloadFreeType3(PsOutPtr self, const char *psfontname, FontPtr pFont, long block_offset);
 
+extern int  PsOut_DownloadFreeType(PsOutPtr self, PsFTDownloadFontType downloadfonttype, const char *psfontname, FontPtr pFont, long block_offset);
+extern void PsOut_Get_FreeType_Glyph_Name( char *destbuf, FontPtr pFont, unsigned long x11fontindex);
+extern void PsOut_FreeType_Text(FontPtr pFont, PsOutPtr self, int x, int y, char *text, int textl);
+extern void PsOut_FreeType_Text16(FontPtr pFont, PsOutPtr self, int x, int y, unsigned short *text, int textl);
 
+extern void PsOut_FreeType_TextAttrs16(PsOutPtr self, char *fnam, int siz, int iso);
+extern void PsOut_FreeType_TextAttrsMtx16(PsOutPtr self, char *fnam, float *mtx, int iso);
 #endif




More information about the xorg-commit-diffs mailing list