/* Copyright 1996, 1998 The Open Group Permission to use, copy, modify, distribute, and sell this software and its 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. 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 OPEN GROUP 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. Except as contained in this notice, the name of The Open Group shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from The Open Group. */ /* * (c) Copyright 1996 Hewlett-Packard Company * (c) Copyright 1996 International Business Machines Corp. * (c) Copyright 1996 Sun Microsystems, Inc. * (c) Copyright 1996 Novell, Inc. * (c) Copyright 1996 Digital Equipment Corp. * (c) Copyright 1996 Fujitsu Limited * (c) Copyright 1996 Hitachi, Ltd. * * 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 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. * * Except as contained in this notice, the names of the copyright holders * shall not be used in advertising or otherwise to promote the sale, use * or other dealings in this Software without prior written authorization * from said copyright holders. */ /******************************************************************* ** ** ********************************************************* ** * ** * File: PsFonts.c ** * ** * Contents: Font code for PS driver. ** * ** * Created By: Roger Helmendach (Liberty Systems) ** * ** * Copyright: Copyright 1996 The Open Group, Inc. ** * ** ********************************************************* ** ********************************************************************/ #ifdef HAVE_DIX_CONFIG_H #include #endif #include "regionstr.h" #include #include "dixfontstr.h" #include "scrnintstr.h" #include #include #include #include "Ps.h" #include #include #include Bool PsRealizeFont( ScreenPtr pscr, FontPtr pFont) { return TRUE; } Bool PsUnrealizeFont( ScreenPtr pscr, FontPtr pFont) { return TRUE; } char * PsGetFontName(FontPtr pFont) { int i; int nprops = pFont->info.nprops; FontPropPtr props = pFont->info.props; Atom name = MakeAtom("FONT", 4, True); Atom value = (Atom)0; for( i=0 ; iinfo.nprops; FontPropPtr props = pFont->info.props; /* "_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 ; iinfo.nprops; FontPropPtr props = pFont->info.props; Atom reg = MakeAtom("CHARSET_REGISTRY", 16, True); Atom enc = MakeAtom("CHARSET_ENCODING", 16, True); Atom rv = 0, ev = 0; char *rp = 0; char *ep = 0; for( i=0 ; iinfo.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 ; ifpe->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; char buf[512]; char *front, *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:""); #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; 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); #ifdef XP_USE_FREETYPE rec->ft_download_encoding = PsGetEncodingName(pFont); rec->ft_download_font_type = PsGetFTDownloadFontType(); #endif /* XP_USE_FREETYPE */ 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) :("")), ((rec->adobe_ps_name) ?(rec->adobe_ps_name):("")), ((rec->download_ps_name)?(rec->download_ps_name):(""))); #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):(""))); #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; }