diff options
Diffstat (limited to 'Xprint/ps/psout_ft.c')
-rw-r--r-- | Xprint/ps/psout_ft.c | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/Xprint/ps/psout_ft.c b/Xprint/ps/psout_ft.c new file mode 100644 index 000000000..914e2e57b --- /dev/null +++ b/Xprint/ps/psout_ft.c @@ -0,0 +1,330 @@ + +/* +Copyright (c) 2003-2004 Roland Mainz <roland.mainz@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); +} + |