diff options
Diffstat (limited to 'libXfont/src')
65 files changed, 24704 insertions, 24534 deletions
diff --git a/libXfont/src/FreeType/ft.h b/libXfont/src/FreeType/ft.h index 8cf31d4ab..300496fd0 100644 --- a/libXfont/src/FreeType/ft.h +++ b/libXfont/src/FreeType/ft.h @@ -1,87 +1,87 @@ -/* -Copyright (c) 1997 by Mark Leisher -Copyright (c) 1998-2002 by Juliusz Chroboczek - -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. -*/ - -#ifndef _FT_H_ -#define _FT_H_ - -#include <X11/Xfuncproto.h> - -#define FREETYPE_VERSION (FREETYPE_MAJOR * 1000000 + FREETYPE_MINOR * 1000 + FREETYPE_PATCH) - -#undef DEBUG_TRUETYPE - -#ifdef DEBUG_TRUETYPE -#define MUMBLE ErrorF -#else -#define MUMBLE(...) -#endif - -#undef MAX -#define MAX(h,i) ((h) > (i) ? (h) : (i)) -#define ADJUSTMAX(m,v) if((v)>(m)) (m)=(v) -#undef MIN -#define MIN(l,o) ((l) < (o) ? (l) : (o)) -#define ADJUSTMIN(m,v) if ((v)<(m)) (m)=(v) - -/* When comparing floating point values, we want to ignore small errors. */ -#define NEGLIGIBLE ((double)0.001) -/* Are x and y significantly different? */ -#define DIFFER(x,y) (fabs((x)-(y))>=NEGLIGIBLE*fabs(x)) -/* Is x significantly different from 0 w.r.t. y? */ -#define DIFFER0(x,y) (fabs(x)>=NEGLIGIBLE*fabs(y)) - -#ifndef ABS -#define ABS(x) ((x) >= 0 ? (x) : -(x)) -#endif - -/* Two to the sixteenth power, as a double. */ -#define TWO_SIXTEENTH ((double)(1<<16)) -#define TWO_SIXTH ((double)(1<<6)) - -/* Data structures used across files */ - -typedef struct _FTMapping -{ - int named; - FT_CharMap cmap; - int base; - struct _FontMap *mapping; /* allow inclusion without fontenc.h */ -} FTMappingRec, *FTMappingPtr; - -/* Prototypes */ - -/* ftfuncs.c */ - -/* ftenc.c */ - -int FTPickMapping(char*, int, char*, FT_Face, FTMappingPtr); -unsigned FTRemap(FT_Face face, FTMappingPtr, unsigned code); - -/* fttools.c */ - -int FTtoXReturnCode(int); -int FTGetEnglishName(FT_Face, int, char *, int); - -extern void ErrorF(const char*, ...); - -#endif /* _FT_H_ */ +/*
+Copyright (c) 1997 by Mark Leisher
+Copyright (c) 1998-2002 by Juliusz Chroboczek
+
+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.
+*/
+
+#ifndef _FT_H_
+#define _FT_H_
+
+#include <X11/Xfuncproto.h>
+
+#define FREETYPE_VERSION (FREETYPE_MAJOR * 1000000 + FREETYPE_MINOR * 1000 + FREETYPE_PATCH)
+
+#undef DEBUG_TRUETYPE
+
+#ifdef DEBUG_TRUETYPE
+#define MUMBLE ErrorF
+#else
+#define MUMBLE(...)
+#endif
+
+#undef MAX
+#define MAX(h,i) ((h) > (i) ? (h) : (i))
+#define ADJUSTMAX(m,v) if((v)>(m)) (m)=(v)
+#undef MIN
+#define MIN(l,o) ((l) < (o) ? (l) : (o))
+#define ADJUSTMIN(m,v) if ((v)<(m)) (m)=(v)
+
+/* When comparing floating point values, we want to ignore small errors. */
+#define NEGLIGIBLE ((double)0.001)
+/* Are x and y significantly different? */
+#define DIFFER(x,y) (fabs((x)-(y))>=NEGLIGIBLE*fabs(x))
+/* Is x significantly different from 0 w.r.t. y? */
+#define DIFFER0(x,y) (fabs(x)>=NEGLIGIBLE*fabs(y))
+
+#ifndef ABS
+#define ABS(x) ((x) >= 0 ? (x) : -(x))
+#endif
+
+/* Two to the sixteenth power, as a double. */
+#define TWO_SIXTEENTH ((double)(1<<16))
+#define TWO_SIXTH ((double)(1<<6))
+
+/* Data structures used across files */
+
+typedef struct _FTMapping
+{
+ int named;
+ FT_CharMap cmap;
+ int base;
+ struct _FontMap *mapping; /* allow inclusion without fontenc.h */
+} FTMappingRec, *FTMappingPtr;
+
+/* Prototypes */
+
+/* ftfuncs.c */
+
+/* ftenc.c */
+
+int FTPickMapping(char*, int, char*, FT_Face, FTMappingPtr);
+unsigned FTRemap(FT_Face face, FTMappingPtr, unsigned code);
+
+/* fttools.c */
+
+int FTtoXReturnCode(int);
+int FTGetEnglishName(FT_Face, int, char *, int);
+
+extern void ErrorF(const char*, ...);
+
+#endif /* _FT_H_ */
diff --git a/libXfont/src/FreeType/ftenc.c b/libXfont/src/FreeType/ftenc.c index 99defbed6..57de53b3a 100644 --- a/libXfont/src/FreeType/ftenc.c +++ b/libXfont/src/FreeType/ftenc.c @@ -1,239 +1,239 @@ -/* -Copyright (c) 1998-2003 by Juliusz Chroboczek - -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. -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <string.h> - -#include <X11/fonts/fntfilst.h> -#include <X11/fonts/fontutil.h> -#include <X11/fonts/FSproto.h> - -#include <X11/fonts/fontmisc.h> -#include <X11/fonts/fontenc.h> -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_TRUETYPE_IDS_H -#include FT_TRUETYPE_TABLES_H -#include FT_TYPE1_TABLES_H -#include FT_BDF_H -#include FT_XFREE86_H -#include "ft.h" - -static int find_cmap(int, int, int, FT_Face, FT_CharMap *); - -static int -FTEncFontSpecific(char *encoding) -{ - char *p = encoding; - - if(strcasecmp(encoding, "microsoft-symbol") == 0) - return 1; - - while(*p != '-') { - if(*p == '\0') - return 0; - p++; - } - p++; - return (strcasecmp(p, "fontspecific") == 0); -} - -int -FTPickMapping(char *xlfd, int length, char *filename, FT_Face face, - FTMappingPtr tm) -{ - FontEncPtr encoding; - FontMapPtr mapping; - FT_CharMap cmap; - int ftrc; - int symbol = 0; - const char *enc, *reg; - char *encoding_name = 0; - char buf[20]; - - if(xlfd) - encoding_name = FontEncFromXLFD(xlfd, length); - if(!encoding_name) - encoding_name = "iso8859-1"; - - symbol = FTEncFontSpecific(encoding_name); - -#if XFONT_BDFFORMAT - ftrc = FT_Get_BDF_Charset_ID(face, &enc, ®); -#else - ftrc = -1; -#endif - if(ftrc == 0) { - /* Disable reencoding for non-Unicode fonts. This will - currently only work for BDFs. */ - if(strlen(enc) + strlen(reg) > 18) - goto native; - strcpy(buf, enc); - strcat(buf, "-"); - strcat(buf, reg); - ErrorF("%s %s\n", buf, encoding_name); - if(strcasecmp(buf, "iso10646-1") != 0) { - if(strcasecmp(buf, encoding_name) == 0) - goto native; - return BadFontFormat; - } - } else if(symbol) { - ftrc = FT_Select_Charmap(face, ft_encoding_adobe_custom); - if(ftrc == 0) - goto native; - } - - encoding = FontEncFind(encoding_name, filename); - if(symbol && encoding == NULL) - encoding = FontEncFind("microsoft-symbol", filename); - if(encoding == NULL) { - ErrorF("FreeType: couldn't find encoding '%s' for '%s'\n", - encoding_name, filename); - return BadFontName; - } - - if(FT_Has_PS_Glyph_Names(face)) { - for(mapping = encoding->mappings; mapping; mapping = mapping->next) { - if(mapping->type == FONT_ENCODING_POSTSCRIPT) { - tm->named = 1; - tm->base = 0; - tm->mapping = mapping; - return Successful; - } - } - } - - for(mapping = encoding->mappings; mapping; mapping = mapping->next) { - if(find_cmap(mapping->type, mapping->pid, mapping->eid, face, - &cmap)) { - tm->named = 0; - tm->cmap = cmap; - if(symbol) { - /* deal with an undocumented ``feature'' of the - Microsft-Symbol cmap */ - TT_OS2 *os2; - os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2); - if(os2) - tm->base = os2->usFirstCharIndex - 0x20; - else - tm->base = 0; - } else - tm->base = 0; - tm->mapping = mapping; - return Successful; - } - } - - return BadFontFormat; - - native: - tm->named = 0; - tm->cmap = face->charmap; - tm->base = 0; - tm->mapping = NULL; - return Successful; -} - -static int -find_cmap(int type, int pid, int eid, FT_Face face, FT_CharMap *cmap_return) -{ - int i, n; - FT_CharMap cmap = NULL; - - n = face->num_charmaps; - - switch(type) { - case FONT_ENCODING_TRUETYPE: /* specific cmap */ - for(i=0; i<n; i++) { - cmap = face->charmaps[i]; - if(cmap->platform_id == pid && cmap->encoding_id == eid) { - *cmap_return = cmap; - return 1; - } - } - break; - case FONT_ENCODING_UNICODE: /* any Unicode cmap */ - /* prefer Microsoft Unicode */ - for(i=0; i<n; i++) { - cmap = face->charmaps[i]; - if(cmap->platform_id == TT_PLATFORM_MICROSOFT && - cmap->encoding_id == TT_MS_ID_UNICODE_CS) { - *cmap_return = cmap; - return 1; - } - } - break; - /* Try Apple Unicode */ - for(i=0; i<n; i++) { - cmap = face->charmaps[i]; - if(cmap->platform_id == TT_PLATFORM_APPLE_UNICODE) { - *cmap_return = cmap; - return 1; - } - } - /* ISO Unicode? */ - for(i=0; i<n; i++) { - cmap = face->charmaps[i]; - if(cmap->platform_id == TT_PLATFORM_ISO) { - *cmap_return = cmap; - return 1; - } - } - break; - default: - return 0; - } - return 0; -} - -unsigned -FTRemap(FT_Face face, FTMappingPtr tm, unsigned code) -{ - unsigned index; - char *name; - unsigned glyph_index; - - if(tm->mapping) { - if(tm->named) { - name = FontEncName(code, tm->mapping); - if(!name) - return 0; - glyph_index = FT_Get_Name_Index(face, name); - return glyph_index; - } else { - index = FontEncRecode(code, tm->mapping) + tm->base; - FT_Set_Charmap(face, tm->cmap); - glyph_index = FT_Get_Char_Index(face, index); - return glyph_index; - } - } else { - if(code < 0x100) { - index = code; - FT_Set_Charmap(face, tm->cmap); - glyph_index = FT_Get_Char_Index(face, index); - return glyph_index; - } else - return 0; - } -} +/*
+Copyright (c) 1998-2003 by Juliusz Chroboczek
+
+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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <string.h>
+
+#include <X11/fonts/fntfilst.h>
+#include <X11/fonts/fontutil.h>
+#include <X11/fonts/FSproto.h>
+
+#include <X11/fonts/fontmisc.h>
+#include <X11/fonts/fontenc.h>
+#include <config/ftheader.h>
+#include FT_FREETYPE_H
+#include FT_TRUETYPE_IDS_H
+#include FT_TRUETYPE_TABLES_H
+#include FT_TYPE1_TABLES_H
+#include FT_BDF_H
+#include FT_XFREE86_H
+#include "ft.h"
+
+static int find_cmap(int, int, int, FT_Face, FT_CharMap *);
+
+static int
+FTEncFontSpecific(char *encoding)
+{
+ char *p = encoding;
+
+ if(strcasecmp(encoding, "microsoft-symbol") == 0)
+ return 1;
+
+ while(*p != '-') {
+ if(*p == '\0')
+ return 0;
+ p++;
+ }
+ p++;
+ return (strcasecmp(p, "fontspecific") == 0);
+}
+
+int
+FTPickMapping(char *xlfd, int length, char *filename, FT_Face face,
+ FTMappingPtr tm)
+{
+ FontEncPtr encoding;
+ FontMapPtr mapping;
+ FT_CharMap cmap;
+ int ftrc;
+ int symbol = 0;
+ const char *enc, *reg;
+ char *encoding_name = 0;
+ char buf[20];
+
+ if(xlfd)
+ encoding_name = FontEncFromXLFD(xlfd, length);
+ if(!encoding_name)
+ encoding_name = "iso8859-1";
+
+ symbol = FTEncFontSpecific(encoding_name);
+
+#if XFONT_BDFFORMAT
+ ftrc = FT_Get_BDF_Charset_ID(face, &enc, ®);
+#else
+ ftrc = -1;
+#endif
+ if(ftrc == 0) {
+ /* Disable reencoding for non-Unicode fonts. This will
+ currently only work for BDFs. */
+ if(strlen(enc) + strlen(reg) > 18)
+ goto native;
+ strcpy(buf, enc);
+ strcat(buf, "-");
+ strcat(buf, reg);
+ ErrorF("%s %s\n", buf, encoding_name);
+ if(strcasecmp(buf, "iso10646-1") != 0) {
+ if(strcasecmp(buf, encoding_name) == 0)
+ goto native;
+ return BadFontFormat;
+ }
+ } else if(symbol) {
+ ftrc = FT_Select_Charmap(face, ft_encoding_adobe_custom);
+ if(ftrc == 0)
+ goto native;
+ }
+
+ encoding = FontEncFind(encoding_name, filename);
+ if(symbol && encoding == NULL)
+ encoding = FontEncFind("microsoft-symbol", filename);
+ if(encoding == NULL) {
+ ErrorF("FreeType: couldn't find encoding '%s' for '%s'\n",
+ encoding_name, filename);
+ return BadFontName;
+ }
+
+ if(FT_Has_PS_Glyph_Names(face)) {
+ for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
+ if(mapping->type == FONT_ENCODING_POSTSCRIPT) {
+ tm->named = 1;
+ tm->base = 0;
+ tm->mapping = mapping;
+ return Successful;
+ }
+ }
+ }
+
+ for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
+ if(find_cmap(mapping->type, mapping->pid, mapping->eid, face,
+ &cmap)) {
+ tm->named = 0;
+ tm->cmap = cmap;
+ if(symbol) {
+ /* deal with an undocumented ``feature'' of the
+ Microsft-Symbol cmap */
+ TT_OS2 *os2;
+ os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
+ if(os2)
+ tm->base = os2->usFirstCharIndex - 0x20;
+ else
+ tm->base = 0;
+ } else
+ tm->base = 0;
+ tm->mapping = mapping;
+ return Successful;
+ }
+ }
+
+ return BadFontFormat;
+
+ native:
+ tm->named = 0;
+ tm->cmap = face->charmap;
+ tm->base = 0;
+ tm->mapping = NULL;
+ return Successful;
+}
+
+static int
+find_cmap(int type, int pid, int eid, FT_Face face, FT_CharMap *cmap_return)
+{
+ int i, n;
+ FT_CharMap cmap = NULL;
+
+ n = face->num_charmaps;
+
+ switch(type) {
+ case FONT_ENCODING_TRUETYPE: /* specific cmap */
+ for(i=0; i<n; i++) {
+ cmap = face->charmaps[i];
+ if(cmap->platform_id == pid && cmap->encoding_id == eid) {
+ *cmap_return = cmap;
+ return 1;
+ }
+ }
+ break;
+ case FONT_ENCODING_UNICODE: /* any Unicode cmap */
+ /* prefer Microsoft Unicode */
+ for(i=0; i<n; i++) {
+ cmap = face->charmaps[i];
+ if(cmap->platform_id == TT_PLATFORM_MICROSOFT &&
+ cmap->encoding_id == TT_MS_ID_UNICODE_CS) {
+ *cmap_return = cmap;
+ return 1;
+ }
+ }
+ break;
+ /* Try Apple Unicode */
+ for(i=0; i<n; i++) {
+ cmap = face->charmaps[i];
+ if(cmap->platform_id == TT_PLATFORM_APPLE_UNICODE) {
+ *cmap_return = cmap;
+ return 1;
+ }
+ }
+ /* ISO Unicode? */
+ for(i=0; i<n; i++) {
+ cmap = face->charmaps[i];
+ if(cmap->platform_id == TT_PLATFORM_ISO) {
+ *cmap_return = cmap;
+ return 1;
+ }
+ }
+ break;
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+unsigned
+FTRemap(FT_Face face, FTMappingPtr tm, unsigned code)
+{
+ unsigned index;
+ char *name;
+ unsigned glyph_index;
+
+ if(tm->mapping) {
+ if(tm->named) {
+ name = FontEncName(code, tm->mapping);
+ if(!name)
+ return 0;
+ glyph_index = FT_Get_Name_Index(face, name);
+ return glyph_index;
+ } else {
+ index = FontEncRecode(code, tm->mapping) + tm->base;
+ FT_Set_Charmap(face, tm->cmap);
+ glyph_index = FT_Get_Char_Index(face, index);
+ return glyph_index;
+ }
+ } else {
+ if(code < 0x100) {
+ index = code;
+ FT_Set_Charmap(face, tm->cmap);
+ glyph_index = FT_Get_Char_Index(face, index);
+ return glyph_index;
+ } else
+ return 0;
+ }
+}
diff --git a/libXfont/src/FreeType/ftfuncs.c b/libXfont/src/FreeType/ftfuncs.c index fd8e53e5f..f06ebb40d 100644 --- a/libXfont/src/FreeType/ftfuncs.c +++ b/libXfont/src/FreeType/ftfuncs.c @@ -1,3924 +1,3928 @@ -/* -Copyright (c) 1997 by Mark Leisher -Copyright (c) 1998-2003 by Juliusz Chroboczek -Copyright (c) 1998 Go Watanabe, All rights reserved. -Copyright (c) 1998 Kazushi (Jam) Marukawa, All rights reserved. -Copyright (c) 1998 Takuya SHIOZAKI, All rights reserved. -Copyright (c) 1998 X-TrueType Server Project, All rights reserved. -Copyright (c) 2003-2004 After X-TT Project, All rights reserved. - -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. -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fontmisc.h> - -#include <string.h> -#include <math.h> -#include <ctype.h> - -#include <X11/fonts/fntfilst.h> -#include <X11/fonts/fontutil.h> -#include <X11/fonts/FSproto.h> -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_SIZES_H -#include FT_TRUETYPE_IDS_H -#include FT_TRUETYPE_TABLES_H -#include FT_TYPE1_TABLES_H -#include FT_XFREE86_H -#include FT_BBOX_H -#include FT_TRUETYPE_TAGS_H -/* - * If you want to use FT_Outline_Get_CBox instead of - * FT_Outline_Get_BBox, define here. - */ -/* #define USE_GET_CBOX */ -#ifdef USE_GET_CBOX -#include FT_OUTLINE_H -#endif - -#include <X11/fonts/fontenc.h> -#include "ft.h" -#include "ftfuncs.h" -#include "xttcap.h" - -/* Work around FreeType bug */ -#define WORK_AROUND_UPM 2048 - -#ifndef True -#define True (-1) -#endif /* True */ -#ifndef False -#define False (0) -#endif /* False */ - -#define FLOOR64(x) ((x) & -64) -#define CEIL64(x) (((x) + 64 - 1) & -64) - -/* - * If you want very lazy method(vl=y) AS DEFAULT when - * handling large charset, define here. - */ -/* #define DEFAULT_VERY_LAZY 1 */ /* Always */ -#define DEFAULT_VERY_LAZY 2 /* Multi-byte only */ -/* #define DEFAULT_VERY_LAZY 256 */ /* Unicode only */ - -/* Does the X accept noSuchChar? */ -#define X_ACCEPTS_NO_SUCH_CHAR -/* Does the XAA accept NULL noSuchChar.bits?(dangerous) */ -/* #define XAA_ACCEPTS_NULL_BITS */ - -#ifdef X_ACCEPTS_NO_SUCH_CHAR -static CharInfoRec noSuchChar = { /* metrics */{0,0,0,0,0,0}, - /* bits */ NULL }; -#endif - -/* The propery names for all the XLFD properties. */ - -static char *xlfd_props[] = { - "FOUNDRY", - "FAMILY_NAME", - "WEIGHT_NAME", - "SLANT", - "SETWIDTH_NAME", - "ADD_STYLE_NAME", - "PIXEL_SIZE", - "POINT_SIZE", - "RESOLUTION_X", - "RESOLUTION_Y", - "SPACING", - "AVERAGE_WIDTH", - "CHARSET_REGISTRY", - "CHARSET_ENCODING", -}; - - -/* read 2-byte value from a SFNT table */ -static FT_UShort -sfnt_get_ushort( FT_Face face, - FT_ULong table_tag, - FT_ULong table_offset ) -{ - FT_Byte buff[2]; - FT_ULong len = sizeof(buff); - FT_UShort result = 0; - - if ( !FT_Load_Sfnt_Table( face, table_tag, table_offset, buff, &len ) ); - result = (FT_UShort)( (buff[0] << 8) | buff[1] ); - - return result; -} - -#define sfnt_get_short(f,t,o) ((FT_Short)sfnt_get_ushort((f),(t),(o))) - - -static int ftypeInitP = 0; /* is the engine initialised? */ -FT_Library ftypeLibrary; - -static FTFacePtr faceTable[NUMFACEBUCKETS]; - -static unsigned -hash(char *string) -{ - int i; - unsigned u = 0; - for(i = 0; string[i] != '\0'; i++) - u = (u<<5) + (u >> (NUMFACEBUCKETS - 5)) + (unsigned char)string[i]; - return u; -} - -static int -ifloor(int x, int y) -{ - if(x >= 0) - return x/y; - else - return x/y - 1; -} - -static int -iceil(int x, int y) -{ - return ifloor(x + y - 1, y); -} - -static int -FreeTypeOpenFace(FTFacePtr *facep, char *FTFileName, char *realFileName, int faceNumber) -{ - FT_Error ftrc; - int bucket; - FTFacePtr face, otherFace; - - if (!ftypeInitP) { - ftrc = FT_Init_FreeType(&ftypeLibrary); - if (ftrc != 0) { - ErrorF("FreeType: error initializing ftypeEngine: %d\n", ftrc); - return AllocError; - } - ftypeInitP = 1; - } - - /* Try to find a matching face in the hashtable */ - bucket = hash(FTFileName)%NUMFACEBUCKETS; - otherFace = faceTable[bucket]; - while(otherFace) { - if( strcmp(otherFace->filename, FTFileName) == 0 ) break; - otherFace = otherFace->next; - } - if(otherFace) { - MUMBLE("Returning cached face: %s\n", otherFace->filename); - *facep = otherFace; - return Successful; - } - - /* No cached match; need to make a new one */ - face = calloc(1, sizeof(FTFaceRec)); - if (face == NULL) { - return AllocError; - } - - face->filename = strdup(FTFileName); - if (face->filename == NULL) { - free(face); - return AllocError; - } - - ftrc = FT_New_Face(ftypeLibrary, realFileName, faceNumber, &face->face); - if(ftrc != 0) { - ErrorF("FreeType: couldn't open face %s: %d\n", FTFileName, ftrc); - free(face->filename); - free(face); - return BadFontName; - } - - face->bitmap = ((face->face->face_flags & FT_FACE_FLAG_SCALABLE) == 0); - if(!face->bitmap) { - TT_MaxProfile *maxp; - maxp = FT_Get_Sfnt_Table(face->face, ft_sfnt_maxp); - if(maxp && maxp->maxContours == 0) - face->bitmap = 1; - } - - face->num_hmetrics = (FT_UInt) sfnt_get_ushort( face->face, - TTAG_hhea, 34 ); - - /* Insert face in hashtable and return it */ - face->next = faceTable[bucket]; - faceTable[bucket] = face; - *facep = face; - return Successful; -} - -static void -FreeTypeFreeFace(FTFacePtr face) -{ - int bucket; - FTFacePtr otherFace; - - if(!face->instances) { - bucket = hash(face->filename) % NUMFACEBUCKETS; - if(faceTable[bucket] == face) - faceTable[bucket] = face->next; - else { - otherFace = faceTable[bucket]; - while(otherFace) { - if(otherFace->next == face) - break; - otherFace = otherFace->next; - } - if(otherFace && otherFace->next) - otherFace->next = otherFace->next->next; - else - ErrorF("FreeType: freeing unknown face\n"); - } - MUMBLE("Closing face: %s\n", face->filename); - FT_Done_Face(face->face); - free(face->filename); - free(face); - } -} - -static int -TransEqual(FTNormalisedTransformationPtr t1, FTNormalisedTransformationPtr t2) -{ - if(t1->scale != t2->scale) - return 0; - else if(t1->xres != t2->xres || t1->yres != t2->yres) - return 0; - else if(t1->nonIdentity != t2->nonIdentity) - return 0; - else if(t1->nonIdentity && t2->nonIdentity) { - return - t1->matrix.xx == t2->matrix.xx && - t1->matrix.yx == t2->matrix.yx && - t1->matrix.yy == t2->matrix.yy && - t1->matrix.xy == t2->matrix.xy; - } else - return 1; -} - -static int -BitmapFormatEqual(FontBitmapFormatPtr f1, FontBitmapFormatPtr f2) -{ - return - f1->bit == f2->bit && - f1->byte == f2->byte && - f1->glyph == f2->glyph; -} - -static int -TTCapEqual(struct TTCapInfo *t1, struct TTCapInfo *t2) -{ - return - t1->autoItalic == t2->autoItalic && - t1->scaleWidth == t2->scaleWidth && - t1->scaleBBoxWidth == t2->scaleBBoxWidth && - t1->scaleBBoxHeight == t2->scaleBBoxHeight && - t1->doubleStrikeShift == t2->doubleStrikeShift && - t1->adjustBBoxWidthByPixel == t2->adjustBBoxWidthByPixel && - t1->adjustLeftSideBearingByPixel == t2->adjustLeftSideBearingByPixel && - t1->adjustRightSideBearingByPixel == t2->adjustRightSideBearingByPixel && - t1->flags == t2->flags && - t1->scaleBitmap == t2->scaleBitmap && - /* - If we use forceConstantSpacing, - we *MUST* allocate new instance. - */ - t1->forceConstantSpacingEnd < 0 && - t2->forceConstantSpacingEnd < 0; -} - -static int -FTInstanceMatch(FTInstancePtr instance, - char *FTFileName, FTNormalisedTransformationPtr trans, - int spacing, FontBitmapFormatPtr bmfmt, - struct TTCapInfo *tmp_ttcap, FT_Int32 load_flags) -{ - if(strcmp(instance->face->filename, FTFileName) != 0) { - return 0; - } else if(!TransEqual(&instance->transformation, trans)) { - return 0; - } else if( spacing != instance->spacing ) { - return 0; - } else if( load_flags != instance->load_flags ) { - return 0; - } else if(!BitmapFormatEqual(&instance->bmfmt, bmfmt)) { - return 0; - } else if(!TTCapEqual(&instance->ttcap, tmp_ttcap)) { - return 0; - } else { - return 1; - } -} - -static int -FreeTypeActivateInstance(FTInstancePtr instance) -{ - FT_Error ftrc; - if(instance->face->active_instance == instance) - return Successful; - - ftrc = FT_Activate_Size(instance->size); - if(ftrc != 0) { - instance->face->active_instance = NULL; - ErrorF("FreeType: couldn't activate instance: %d\n", ftrc); - return FTtoXReturnCode(ftrc); - } - FT_Set_Transform(instance->face->face, - instance->transformation.nonIdentity ? - &instance->transformation.matrix : 0, - 0); - - instance->face->active_instance = instance; - return Successful; -} - -static int -FTFindSize(FT_Face face, FTNormalisedTransformationPtr trans, - int *x_return, int *y_return) -{ - int tx, ty, x, y; - int i, j; - int d, dd; - - if(trans->nonIdentity) - return BadFontName; - - tx = (int)(trans->scale * trans->xres / 72.0 + 0.5); - ty = (int)(trans->scale * trans->yres / 72.0 + 0.5); - - d = 100; - j = -1; - for(i = 0; i < face->num_fixed_sizes; i++) { - x = face->available_sizes[i].width; - y = face->available_sizes[i].height; - if(ABS(x - tx) <= 1 && ABS(y - ty) <= 1) { - dd = ABS(x - tx) * ABS(x - tx) + ABS(y - ty) * ABS(y - ty); - if(dd < d) { - j = i; - d = dd; - } - } - } - if(j < 0) - return BadFontName; - - *x_return = face->available_sizes[j].width; - *y_return = face->available_sizes[j].height; - return Successful; -} - -static int -FreeTypeOpenInstance(FTInstancePtr *instance_return, FTFacePtr face, - char *FTFileName, FTNormalisedTransformationPtr trans, - int spacing, FontBitmapFormatPtr bmfmt, - struct TTCapInfo *tmp_ttcap, FT_Int32 load_flags) -{ - FT_Error ftrc; - int xrc; - FTInstancePtr instance, otherInstance; - - /* Search for a matching instance */ - for(otherInstance = face->instances; - otherInstance; - otherInstance = otherInstance->next) { - if(FTInstanceMatch(otherInstance, FTFileName, trans, spacing, bmfmt, - tmp_ttcap, load_flags)) break; - } - if(otherInstance) { - MUMBLE("Returning cached instance\n"); - otherInstance->refcount++; - *instance_return = otherInstance; - return Successful; - } - - /* None matching found */ - instance = malloc(sizeof(FTInstanceRec)); - if(instance == NULL) { - return AllocError; - } - - instance->refcount = 1; - instance->face = face; - - instance->load_flags = load_flags; - instance->spacing = spacing; /* Actual spacing */ - instance->pixel_size =0; - instance->pixel_width_unit_x =0; - instance->pixel_width_unit_y =0; - instance->charcellMetrics = NULL; - instance->averageWidth = 0; - instance->rawAverageWidth = 0; - instance->forceConstantMetrics = NULL; - - instance->transformation = *trans; - instance->bmfmt = *bmfmt; - instance->glyphs = NULL; - instance->available = NULL; - - if( 0 <= tmp_ttcap->forceConstantSpacingEnd ) - instance->nglyphs = 2 * instance->face->face->num_glyphs; - else - instance->nglyphs = instance->face->face->num_glyphs; - - /* Store the TTCap info. */ - memcpy((char*)&instance->ttcap, (char*)tmp_ttcap, - sizeof(struct TTCapInfo)); - - ftrc = FT_New_Size(instance->face->face, &instance->size); - if(ftrc != 0) { - ErrorF("FreeType: couldn't create size object: %d\n", ftrc); - free(instance); - return FTtoXReturnCode(ftrc); - } - FreeTypeActivateInstance(instance); - if(!face->bitmap) { - ftrc = FT_Set_Char_Size(instance->face->face, - (int)(trans->scale*(1<<6) + 0.5), - (int)(trans->scale*(1<<6) + 0.5), - trans->xres, trans->yres); - } else { - int xsize, ysize; - xrc = FTFindSize(face->face, trans, &xsize, &ysize); - if(xrc != Successful) { - free(instance); - return xrc; - } - ftrc = FT_Set_Pixel_Sizes(instance->face->face, xsize, ysize); - } - if(ftrc != 0) { - FT_Done_Size(instance->size); - free(instance); - return FTtoXReturnCode(ftrc); - } - - if( FT_IS_SFNT( face->face ) ) { -#if 1 - FT_F26Dot6 tt_char_width, tt_char_height, tt_dim_x, tt_dim_y; - FT_UInt nn; - - instance->strike_index=0xFFFFU; - - tt_char_width = (FT_F26Dot6)(trans->scale*(1<<6) + 0.5); - tt_char_height = (FT_F26Dot6)(trans->scale*(1<<6) + 0.5); - - tt_dim_x = FLOOR64( ( tt_char_width * trans->xres + 36 ) / 72 + 32 ); - tt_dim_y = FLOOR64( ( tt_char_height * trans->yres + 36 ) / 72 + 32 ); - - if ( tt_dim_x && !tt_dim_y ) - tt_dim_y = tt_dim_x; - else if ( !tt_dim_x && tt_dim_y ) - tt_dim_x = tt_dim_y; - - for ( nn = 0; nn < face->face->num_fixed_sizes; nn++ ) - { - FT_Bitmap_Size* sz = &face->face->available_sizes[nn]; - - if ( tt_dim_x == FLOOR64(sz->x_ppem + 32) && tt_dim_y == FLOOR64(sz->y_ppem + 32) ) - { - instance->strike_index = nn; - break; - } - } -#else - /* See Set_Char_Sizes() in ttdriver.c */ - FT_Error err; - TT_Face tt_face; - FT_Long tt_dim_x, tt_dim_y; - FT_UShort tt_x_ppem, tt_y_ppem; - FT_F26Dot6 tt_char_width, tt_char_height; - SFNT_Service sfnt; - tt_face=(TT_Face)face->face; - tt_char_width = (int)(trans->scale*(1<<6) + 0.5); - tt_char_height = (int)(trans->scale*(1<<6) + 0.5); - if ( ( tt_face->header.Flags & 8 ) != 0 ) { - tt_dim_x = ( ( tt_char_width * trans->xres + (36+32*72) ) / 72 ) & -64; - tt_dim_y = ( ( tt_char_height * trans->yres + (36+32*72) ) / 72 ) & -64; - } - else{ - tt_dim_x = ( ( tt_char_width * trans->xres + 36 ) / 72 ); - tt_dim_y = ( ( tt_char_height * trans->yres + 36 ) / 72 ); - } - tt_x_ppem = (FT_UShort)( tt_dim_x >> 6 ); - tt_y_ppem = (FT_UShort)( tt_dim_y >> 6 ); - /* See Reset_SBit_Size() in ttobjs.c */ - sfnt = (SFNT_Service)tt_face->sfnt; - err = sfnt->set_sbit_strike(tt_face,tt_x_ppem,tt_y_ppem,&instance->strike_index); - if ( err ) instance->strike_index=0xFFFFU; -#endif - } - - /* maintain a linked list of instances */ - instance->next = instance->face->instances; - instance->face->instances = instance; - - *instance_return = instance; - return Successful; -} - -static void -FreeTypeFreeInstance(FTInstancePtr instance) -{ - FTInstancePtr otherInstance; - - if( instance == NULL ) return; - - if(instance->face->active_instance == instance) - instance->face->active_instance = NULL; - instance->refcount--; - if(instance->refcount <= 0) { - int i,j; - - if(instance->face->instances == instance) - instance->face->instances = instance->next; - else { - for(otherInstance = instance->face->instances; - otherInstance; - otherInstance = otherInstance->next) - if(otherInstance->next == instance) { - otherInstance->next = instance->next; - break; - } - } - - FT_Done_Size(instance->size); - FreeTypeFreeFace(instance->face); - - if(instance->charcellMetrics) { - free(instance->charcellMetrics); - } - if(instance->forceConstantMetrics) { - free(instance->forceConstantMetrics); - } - if(instance->glyphs) { - for(i = 0; i < iceil(instance->nglyphs, FONTSEGMENTSIZE); i++) { - if(instance->glyphs[i]) { - for(j = 0; j < FONTSEGMENTSIZE; j++) { - if(instance->available[i][j] == - FT_AVAILABLE_RASTERISED) - free(instance->glyphs[i][j].bits); - } - free(instance->glyphs[i]); - } - } - free(instance->glyphs); - } - if(instance->available) { - for(i = 0; i < iceil(instance->nglyphs, FONTSEGMENTSIZE); i++) { - if(instance->available[i]) - free(instance->available[i]); - } - free(instance->available); - } - free(instance); - } -} - -static int -FreeTypeInstanceFindGlyph(unsigned idx_in, int flags, FTInstancePtr instance, - CharInfoPtr **glyphs, int ***available, - int *found, int *segmentP, int *offsetP) -{ - int segment, offset; - unsigned idx = idx_in; - - if( 0 <= instance->ttcap.forceConstantSpacingEnd ){ - if( (flags & FT_FORCE_CONSTANT_SPACING) ) - idx += instance->nglyphs / 2 ; - } - - if(idx > instance->nglyphs) { - *found = 0; - return Successful; - } - - if(*available == NULL) { - *available = calloc(iceil(instance->nglyphs, FONTSEGMENTSIZE), - sizeof(int *)); - if(*available == NULL) - return AllocError; - } - - segment = ifloor(idx, FONTSEGMENTSIZE); - offset = idx - segment * FONTSEGMENTSIZE; - - if((*available)[segment] == NULL) { - (*available)[segment] = calloc(FONTSEGMENTSIZE, sizeof(int *)); - if((*available)[segment] == NULL) - return AllocError; - } - - if(*glyphs == NULL) { - *glyphs = calloc(iceil(instance->nglyphs, FONTSEGMENTSIZE), - sizeof(CharInfoPtr)); - if(*glyphs == NULL) - return AllocError; - } - - if((*glyphs)[segment] == NULL) { - (*glyphs)[segment] = malloc(sizeof(CharInfoRec) * FONTSEGMENTSIZE); - if((*glyphs)[segment] == NULL) - return AllocError; - } - - *found = 1; - *segmentP = segment; - *offsetP = offset; - return Successful; -} - -static int -FreeTypeInstanceGetGlyph(unsigned idx, int flags, CharInfoPtr *g, FTInstancePtr instance) -{ - int found, segment, offset; - int xrc; - int ***available; - CharInfoPtr **glyphs; - - available = &instance->available; - glyphs = &instance->glyphs; - - xrc = FreeTypeInstanceFindGlyph(idx, flags, instance, glyphs, available, - &found, &segment, &offset); - if(xrc != Successful) - return xrc; - - if(!found || (*available)[segment][offset] == FT_AVAILABLE_NO) { - *g = NULL; - return Successful; - } - - if((*available)[segment][offset] == FT_AVAILABLE_RASTERISED) { - *g = &(*glyphs)[segment][offset]; - return Successful; - } - - flags |= FT_GET_GLYPH_BOTH; - - xrc = FreeTypeRasteriseGlyph(idx, flags, - &(*glyphs)[segment][offset], instance, - (*available)[segment][offset] >= FT_AVAILABLE_METRICS); - if(xrc != Successful && (*available)[segment][offset] >= FT_AVAILABLE_METRICS) { - ErrorF("Warning: FreeTypeRasteriseGlyph() returns an error,\n"); - ErrorF("\tso the backend tries to set a white space.\n"); - xrc = FreeTypeRasteriseGlyph(idx, flags | FT_GET_DUMMY, - &(*glyphs)[segment][offset], instance, - (*available)[segment][offset] >= FT_AVAILABLE_METRICS); - } - if(xrc == Successful) { - (*available)[segment][offset] = FT_AVAILABLE_RASTERISED; - /* return the glyph */ - *g = &(*glyphs)[segment][offset]; - } - return xrc; -} - -static int -FreeTypeInstanceGetGlyphMetrics(unsigned idx, int flags, - xCharInfo **metrics, FTInstancePtr instance ) -{ - int xrc; - int found, segment, offset; - - /* Char cell */ - if(instance->spacing == FT_CHARCELL) { - *metrics = instance->charcellMetrics; - return Successful; - } - /* Force constant metrics */ - if( flags & FT_FORCE_CONSTANT_SPACING) { - *metrics = instance->forceConstantMetrics; - return Successful; - } - - /* Not char cell */ - - xrc = FreeTypeInstanceFindGlyph(idx, flags, instance, - &instance->glyphs, &instance->available, - &found, &segment, &offset); - if(xrc != Successful) - return xrc; - if(!found) { - *metrics = NULL; - return Successful; - } - if( instance->available[segment][offset] == FT_AVAILABLE_NO ) { - *metrics = NULL; - return Successful; - } - - if( instance->available[segment][offset] >= FT_AVAILABLE_METRICS ) { - *metrics = &instance->glyphs[segment][offset].metrics; - return Successful; - } - - flags |= FT_GET_GLYPH_METRICS_ONLY; - - xrc = FreeTypeRasteriseGlyph(idx, flags, - &instance->glyphs[segment][offset], - instance, 0); - if(xrc == Successful) { - instance->available[segment][offset] = FT_AVAILABLE_METRICS; - *metrics = &instance->glyphs[segment][offset].metrics; - } - return xrc; -} - -/* - * Pseudo enbolding similar as Microsoft Windows. - * It is useful but poor. - */ -static void -ft_make_up_bold_bitmap( char *raster, int bpr, int ht, int ds_mode) -{ - int x, y; - unsigned char *p = (unsigned char *)raster; - if ( ds_mode & TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT ) { - for (y=0; y<ht; y++) { - unsigned char rev_pat=0; - unsigned char lsb = 0; - for (x=0; x<bpr; x++) { - unsigned char tmp = *p<<7; - if ( (rev_pat & 0x01) && (*p & 0x80) ) p[-1] &= 0xfe; - rev_pat = ~(*p); - *p |= (*p>>1) | lsb; - *p &= ~(rev_pat & (*p << 1)); - lsb = tmp; - p++; - } - } - } - else { - for (y=0; y<ht; y++) { - unsigned char lsb = 0; - for (x=0; x<bpr; x++) { - unsigned char tmp = *p<<7; - *p |= (*p>>1) | lsb; - lsb = tmp; - p++; - } - } - } -} - -static void -ft_make_up_italic_bitmap( char *raster, int bpr, int ht, int shift, - int h_total, int h_offset, double a_italic) -{ - int x, y; - unsigned char *p = (unsigned char *)raster; - if ( a_italic < 0 ) shift = -shift; - for (y=0; y<ht; y++) { - unsigned char *tmp_p = p + y*bpr; - int tmp_shift = shift * (h_total -1 -(y+h_offset)) / h_total; - int tmp_byte_shift; - if ( 0 <= tmp_shift ) { - tmp_byte_shift = tmp_shift/8; - tmp_shift %= 8; - if ( tmp_shift ) { - for (x=bpr-1;0<=x;x--) { - if ( x != bpr-1 ) - tmp_p[x+1] |= tmp_p[x]<<(8-tmp_shift); - tmp_p[x]>>=tmp_shift; - } - } - if ( tmp_byte_shift ) { - for (x=bpr-1;0<x;x--) { - tmp_p[x] = tmp_p[x-1]; - } - tmp_p[x]=0; - } - } - else { - tmp_shift = -tmp_shift; - tmp_byte_shift = tmp_shift/8; - tmp_shift %= 8; - if ( tmp_shift ) { - for (x=0;x<bpr;x++) { - if ( x != 0 ) - tmp_p[x-1] |= tmp_p[x]>>(8-tmp_shift); - tmp_p[x]<<=tmp_shift; - } - } - if ( tmp_byte_shift ) { - for (x=0;x<bpr-1;x++) { - tmp_p[x] = tmp_p[x+1]; - } - tmp_p[x]=0; - } - } - } -} - -/* - * The very lazy method, - * parse the htmx field in TrueType font. - */ - -static void -tt_get_metrics( FT_Face face, - FT_UInt idx, - FT_UInt num_hmetrics, - FT_Short* bearing, - FT_UShort* advance ) -{ - /* read the metrics directly from the horizontal header, we - * parse the SFNT table directly through the standard FreeType API. - * this works with any version of the library and doesn't need to - * peek at its internals. Maybe a bit less - */ - FT_UInt count = num_hmetrics; - FT_ULong length = 0; - FT_ULong offset = 0; - FT_Error error; - - error = FT_Load_Sfnt_Table( face, TTAG_hmtx, 0, NULL, &length ); - - if ( count == 0 || error ) - { - *advance = 0; - *bearing = 0; - } - else if ( idx < count ) - { - offset = idx * 4L; - if ( offset + 4 > length ) - { - *advance = 0; - *bearing = 0; - } - else - { - *advance = sfnt_get_ushort( face, TTAG_hmtx, offset ); - *bearing = sfnt_get_short ( face, TTAG_hmtx, offset+2 ); - } - } - else - { - offset = 4L * (count - 1); - if ( offset + 4 > length ) - { - *advance = 0; - *bearing = 0; - } - else - { - *advance = sfnt_get_ushort ( face, TTAG_hmtx, offset ); - offset += 4 + 2 * ( idx - count ); - if ( offset + 2 > length) - *bearing = 0; - else - *bearing = sfnt_get_short ( face, TTAG_hmtx, offset ); - } - } -} - -static int -ft_get_very_lazy_bbox( FT_UInt index, - FT_Face face, - FT_Size size, - FT_UInt num_hmetrics, - double slant, - FT_Matrix *matrix, - FT_BBox *bbox, - FT_Long *horiAdvance, - FT_Long *vertAdvance) -{ - if ( FT_IS_SFNT( face ) ) { - FT_Size_Metrics *smetrics = &size->metrics; - FT_Short leftBearing = 0; - FT_UShort advance = 0; - FT_Vector p0, p1, p2, p3; - - /* horizontal */ - tt_get_metrics( face, index, num_hmetrics, - &leftBearing, &advance ); - -#if 0 - fprintf(stderr,"x_scale=%f y_scale=%f\n", - (double)smetrics->x_scale,(double)smetrics->y_scale); -#endif - bbox->xMax = *horiAdvance = - FT_MulFix( advance, smetrics->x_scale ); - bbox->xMin = - FT_MulFix( leftBearing, smetrics->x_scale ); - /* vertical */ - bbox->yMin = FT_MulFix( face->bbox.yMin, - smetrics->y_scale ); - bbox->yMax = FT_MulFix( face->bbox.yMax, - smetrics->y_scale ); - /* slant */ - if( 0 < slant ) { - bbox->xMax += slant * bbox->yMax; - bbox->xMin += slant * bbox->yMin; - } - else if( slant < 0 ) { - bbox->xMax += slant * bbox->yMin; - bbox->xMin += slant * bbox->yMax; - } - - *vertAdvance = -1; /* We don't support */ - - p0.x = p2.x = bbox->xMin; - p1.x = p3.x = bbox->xMax; - p0.y = p1.y = bbox->yMin; - p2.y = p3.y = bbox->yMax; - - FT_Vector_Transform(&p0, matrix); - FT_Vector_Transform(&p1, matrix); - FT_Vector_Transform(&p2, matrix); - FT_Vector_Transform(&p3, matrix); - -#if 0 - fprintf(stderr, - "->(%.1f %.1f) (%.1f %.1f)" - " (%.1f %.1f) (%.1f %.1f)\n", - p0.x / 64.0, p0.y / 64.0, - p1.x / 64.0, p1.y / 64.0, - p2.x / 64.0, p2.y / 64.0, - p3.x / 64.0, p3.y / 64.0); -#endif - bbox->xMin = MIN(p0.x, MIN(p1.x, MIN(p2.x, p3.x))); - bbox->xMax = MAX(p0.x, MAX(p1.x, MAX(p2.x, p3.x))); - bbox->yMin = MIN(p0.y, MIN(p1.y, MIN(p2.y, p3.y))); - bbox->yMax = MAX(p0.y, MAX(p1.y, MAX(p2.y, p3.y))); - return 0; /* Successful */ - } - return -1; -} - -static FT_Error -FT_Do_SBit_Metrics( FT_Face ft_face, FT_Size ft_size, FT_ULong strike_index, - FT_UShort glyph_index, FT_Glyph_Metrics *metrics_return, - int *sbitchk_incomplete_but_exist ) -{ -#if 1 - if ( strike_index != 0xFFFFU && ft_face->available_sizes != NULL ) - { - FT_Error error; - FT_Bitmap_Size* sz = &ft_face->available_sizes[strike_index]; - - error = FT_Set_Pixel_Sizes( ft_face, sz->x_ppem/64, sz->y_ppem/64 ); - if ( !error ) - { - error = FT_Load_Glyph( ft_face, glyph_index, FT_LOAD_SBITS_ONLY ); - if ( !error ) - { - if ( metrics_return != NULL ) - *metrics_return = ft_face->glyph->metrics; - - return 0; - } - } - } - return -1; -#elif (FREETYPE_VERSION >= 2001008) - SFNT_Service sfnt; - TT_Face face; - FT_Error error; - FT_Stream stream; - TT_SBit_Strike strike; - TT_SBit_Range range; - TT_SBit_MetricsRec elem_metrics; - FT_ULong ebdt_pos; - FT_ULong glyph_offset; - ; - - if ( ! FT_IS_SFNT( ft_face ) ) - { - error=-1; - goto Exit; - } - - face = (TT_Face)ft_face; - sfnt = (SFNT_Service)face->sfnt; - - if (strike_index != 0xFFFFU && sfnt && sfnt->find_sbit_image && - sfnt->load_sbits) { - /* Check whether there is a glyph sbit for the current index */ - error = sfnt->find_sbit_image( face, glyph_index, strike_index, - &range, &strike, &glyph_offset ); - } - else error=-1; - if ( error ) goto Exit; - - if ( metrics_return == NULL ) goto Exit; - - stream = face->root.stream; - - /* now, find the location of the `EBDT' table in */ - /* the font file */ - error = face->goto_table( face, TTAG_EBDT, stream, 0 ); - if ( error ) - error = face->goto_table( face, TTAG_bdat, stream, 0 ); - if (error) - goto Exit; - - ebdt_pos = FT_STREAM_POS(); - - /* place stream at beginning of glyph data and read metrics */ - if ( FT_STREAM_SEEK( ebdt_pos + glyph_offset ) ) - goto Exit; - - error = sfnt->load_sbit_metrics( stream, range, &elem_metrics ); - if ( error ) - goto Exit; - - metrics_return->width = (FT_Pos)elem_metrics.width << 6; - metrics_return->height = (FT_Pos)elem_metrics.height << 6; - - metrics_return->horiBearingX = (FT_Pos)elem_metrics.horiBearingX << 6; - metrics_return->horiBearingY = (FT_Pos)elem_metrics.horiBearingY << 6; - metrics_return->horiAdvance = (FT_Pos)elem_metrics.horiAdvance << 6; - - metrics_return->vertBearingX = (FT_Pos)elem_metrics.vertBearingX << 6; - metrics_return->vertBearingY = (FT_Pos)elem_metrics.vertBearingY << 6; - metrics_return->vertAdvance = (FT_Pos)elem_metrics.vertAdvance << 6; - - Exit: - return error; -#else /* if (FREETYPE_VERSION < 2001008) */ - TT_Face face; - SFNT_Service sfnt; - if ( ! FT_IS_SFNT( ft_face ) ) return -1; - face = (TT_Face)ft_face; - sfnt = (SFNT_Service)face->sfnt; - if ( strike_index != 0xFFFFU && sfnt->load_sbits ) { - if ( sbitchk_incomplete_but_exist ) *sbitchk_incomplete_but_exist=1; - } - return -1; -#endif -} - -int -FreeTypeRasteriseGlyph(unsigned idx, int flags, CharInfoPtr tgp, - FTInstancePtr instance, int hasMetrics) -{ - FTFacePtr face; - FT_BBox bbox; - FT_Long outline_hori_advance, outline_vert_advance; - FT_Glyph_Metrics sbit_metrics; - FT_Glyph_Metrics *bitmap_metrics=NULL, *metrics = NULL; - char *raster; - int wd, ht, bpr; /* width, height, bytes per row */ - int wd_actual, ht_actual; - int ftrc, is_outline, correct, b_shift=0; - int dx, dy; - int leftSideBearing, rightSideBearing, characterWidth, rawCharacterWidth, - ascent, descent; - int sbitchk_incomplete_but_exist; - double bbox_center_raw; - - face = instance->face; - - FreeTypeActivateInstance(instance); - - if(!tgp) return AllocError; - - /* - * PREPARE METRICS - */ - - if(!hasMetrics) { - if( instance->spacing == FT_CHARCELL || flags & FT_GET_DUMMY ){ - memcpy((char*)&tgp->metrics, - (char*)instance->charcellMetrics, - sizeof(xCharInfo)); - } - else if( flags & FT_FORCE_CONSTANT_SPACING ) { - memcpy((char*)&tgp->metrics, - (char*)instance->forceConstantMetrics, - sizeof(xCharInfo)); - } - /* mono or prop. */ - else{ - int new_width; - double ratio; - - sbitchk_incomplete_but_exist=0; - if( ! (instance->load_flags & FT_LOAD_NO_BITMAP) ) { - if( FT_Do_SBit_Metrics(face->face,instance->size,instance->strike_index, - idx,&sbit_metrics,&sbitchk_incomplete_but_exist)==0 ) { - bitmap_metrics = &sbit_metrics; - } - } - if( bitmap_metrics == NULL ) { - if ( sbitchk_incomplete_but_exist==0 && (instance->ttcap.flags & TTCAP_IS_VERY_LAZY) ) { - if( ft_get_very_lazy_bbox( idx, face->face, instance->size, - face->num_hmetrics, - instance->ttcap.vl_slant, - &instance->transformation.matrix, - &bbox, &outline_hori_advance, - &outline_vert_advance ) == 0 ) { - goto bbox_ok; /* skip exact calculation */ - } - } - ftrc = FT_Load_Glyph(instance->face->face, idx, - instance->load_flags); - if(ftrc != 0) return FTtoXReturnCode(ftrc); - metrics = &face->face->glyph->metrics; - if( face->face->glyph->format == FT_GLYPH_FORMAT_BITMAP ) { - bitmap_metrics = metrics; - } - } - - if( bitmap_metrics ) { - FT_Pos factor; - - leftSideBearing = bitmap_metrics->horiBearingX / 64; - rightSideBearing = (bitmap_metrics->width + bitmap_metrics->horiBearingX) / 64; - bbox_center_raw = (2.0 * bitmap_metrics->horiBearingX + bitmap_metrics->width)/2.0/64.0; - characterWidth = (int)floor(bitmap_metrics->horiAdvance - * instance->ttcap.scaleBBoxWidth / 64.0 + .5); - ascent = bitmap_metrics->horiBearingY / 64; - descent = (bitmap_metrics->height - bitmap_metrics->horiBearingY) / 64 ; - /* */ - new_width = characterWidth; - if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH ) - new_width += instance->ttcap.doubleStrikeShift; - new_width += instance->ttcap.adjustBBoxWidthByPixel; - ratio = (double)new_width/characterWidth; - characterWidth = new_width; - /* adjustment by pixel unit */ - if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE ) - rightSideBearing += instance->ttcap.doubleStrikeShift; - rightSideBearing += instance->ttcap.adjustRightSideBearingByPixel; - leftSideBearing += instance->ttcap.adjustLeftSideBearingByPixel; - rightSideBearing += instance->ttcap.rsbShiftOfBitmapAutoItalic; - leftSideBearing += instance->ttcap.lsbShiftOfBitmapAutoItalic; - /* */ - factor = bitmap_metrics->horiAdvance; - rawCharacterWidth = (unsigned short)(short)(floor(1000 * factor - * instance->ttcap.scaleBBoxWidth * ratio / 64. - / instance->pixel_size)); - } - else { - /* Outline */ -#ifdef USE_GET_CBOX - /* Very fast?? */ - FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox); - ftrc=0; /* FT_Outline_Get_CBox returns nothing. */ -#else - /* Calculate exact metrics */ - ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox); -#endif - if( ftrc != 0 ) return FTtoXReturnCode(ftrc); - outline_hori_advance = metrics->horiAdvance; - outline_vert_advance = metrics->vertAdvance; - bbox_ok: - descent = CEIL64(-bbox.yMin - 32) / 64; - leftSideBearing = FLOOR64(bbox.xMin + 32) / 64; - ascent = FLOOR64(bbox.yMax + 32) / 64; - rightSideBearing = FLOOR64(bbox.xMax + 32) / 64; - bbox_center_raw = (double)(bbox.xMax + bbox.xMin)/2.0/64.; - if ( instance->pixel_width_unit_x != 0 ) - characterWidth = - (int)floor( outline_hori_advance - * instance->ttcap.scaleBBoxWidth - * instance->pixel_width_unit_x / 64. + .5); - else { - characterWidth = - (int)floor( outline_vert_advance - * instance->ttcap.scaleBBoxHeight - * instance->pixel_width_unit_y / 64. + .5); - if(characterWidth <= 0) - characterWidth = instance->charcellMetrics->characterWidth; - } - /* */ - new_width = characterWidth; - if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH ) - new_width += instance->ttcap.doubleStrikeShift; - new_width += instance->ttcap.adjustBBoxWidthByPixel; - ratio = (double)new_width/characterWidth; - characterWidth = new_width; - if ( instance->pixel_width_unit_x != 0 ) - rawCharacterWidth = - (unsigned short)(short)(floor(1000 * outline_hori_advance - * instance->ttcap.scaleBBoxWidth * ratio - * instance->pixel_width_unit_x / 64.)); - else { - rawCharacterWidth = - (unsigned short)(short)(floor(1000 * outline_vert_advance - * instance->ttcap.scaleBBoxHeight * ratio - * instance->pixel_width_unit_y / 64.)); - if(rawCharacterWidth <= 0) - rawCharacterWidth = instance->charcellMetrics->attributes; - } - /* adjustment by pixel unit */ - if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE ) - rightSideBearing += instance->ttcap.doubleStrikeShift; - rightSideBearing += instance->ttcap.adjustRightSideBearingByPixel; - leftSideBearing += instance->ttcap.adjustLeftSideBearingByPixel; - } - - /* Set the glyph metrics. */ - tgp->metrics.attributes = (unsigned short)((short)rawCharacterWidth); - tgp->metrics.leftSideBearing = leftSideBearing; - tgp->metrics.rightSideBearing = rightSideBearing; - tgp->metrics.characterWidth = characterWidth; - tgp->metrics.ascent = ascent; - tgp->metrics.descent = descent; - /* Update the width to match the width of the font */ - if( instance->spacing != FT_PROPORTIONAL ) - tgp->metrics.characterWidth = instance->charcellMetrics->characterWidth; - if(instance->ttcap.flags & TTCAP_MONO_CENTER){ - b_shift = (int)floor((instance->advance/2.0-bbox_center_raw) + .5); - tgp->metrics.leftSideBearing += b_shift; - tgp->metrics.rightSideBearing += b_shift; - } - } - } - - if( flags & FT_GET_GLYPH_METRICS_ONLY ) return Successful; - - /* - * CHECK THE NECESSITY OF BITMAP POSITION'S CORRECTION - */ - - correct=0; - if( instance->spacing == FT_CHARCELL ) correct=1; - else if( flags & FT_FORCE_CONSTANT_SPACING ) correct=1; - else{ - int sbit_available=0; - sbitchk_incomplete_but_exist=0; - if( !(instance->load_flags & FT_LOAD_NO_BITMAP) ) { - if( FT_Do_SBit_Metrics(face->face,instance->size, - instance->strike_index,idx,NULL, - &sbitchk_incomplete_but_exist)==0 ) { - sbit_available=1; - } - } - if( sbit_available == 0 ) { - if ( sbitchk_incomplete_but_exist==0 && (instance->ttcap.flags & TTCAP_IS_VERY_LAZY) ) { - if( FT_IS_SFNT(face->face) ) correct=1; - } - } - } - - /* - * RENDER AND ALLOCATE BUFFER - */ - - if( flags & FT_GET_DUMMY ) is_outline = -1; - else { - if( !metrics ) { - ftrc = FT_Load_Glyph(instance->face->face, idx, - instance->load_flags); - metrics = &face->face->glyph->metrics; - - if(ftrc != 0) return FTtoXReturnCode(ftrc); - } - - if( face->face->glyph->format != FT_GLYPH_FORMAT_BITMAP ) { -#ifdef USE_GET_CBOX - FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox); - ftrc = 0; -#else - ftrc = FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox); -#endif - if( ftrc != 0 ) return FTtoXReturnCode(ftrc); - bbox.yMin = FLOOR64( bbox.yMin ); - bbox.yMax = CEIL64 ( bbox.yMax ); - ht_actual = ( bbox.yMax - bbox.yMin ) >> 6; - /* FreeType think a glyph with 0 height control box is invalid. - * So just let X to create a empty bitmap instead. */ - if ( ht_actual == 0 ) - is_outline = -1; - else - { - ftrc = FT_Render_Glyph(face->face->glyph,FT_RENDER_MODE_MONO); - if( ftrc != 0 ) return FTtoXReturnCode(ftrc); - is_outline = 1; - } - } - else{ - is_outline=0; - } - } - - /* Spacial case */ - if( (instance->ttcap.flags & TTCAP_MONO_CENTER) && hasMetrics ) { - if( is_outline == 1 ){ - if( correct ){ - if( ft_get_very_lazy_bbox( idx, face->face, instance->size, - face->num_hmetrics, - instance->ttcap.vl_slant, - &instance->transformation.matrix, - &bbox, &outline_hori_advance, - &outline_vert_advance ) != 0 ){ - is_outline = -1; /* <- error */ - } - } - else { -#ifdef USE_GET_CBOX - FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox); - ftrc=0; -#else - ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox); -#endif - if( ftrc != 0 ) return FTtoXReturnCode(ftrc); - } - bbox_center_raw = (double)(bbox.xMax + bbox.xMin)/2.0/64.; - } - else if( is_outline == 0 ) - bbox_center_raw = (2.0 * metrics->horiBearingX + metrics->width)/2.0/64.0; - else - bbox_center_raw = 0; - b_shift = (int)floor((instance->advance/2.0-bbox_center_raw) + .5); - } - - wd_actual = tgp->metrics.rightSideBearing - tgp->metrics.leftSideBearing; - ht_actual = tgp->metrics.ascent + tgp->metrics.descent; - - /* The X convention is to consider a character with an empty - * bounding box as undefined. This convention is broken. */ - - if(wd_actual <= 0) wd = 1; - else wd=wd_actual; - if(ht_actual <= 0) ht = 1; - else ht=ht_actual; - - bpr = (((wd + (instance->bmfmt.glyph<<3) - 1) >> 3) & - -instance->bmfmt.glyph); - raster = calloc(1, ht * bpr); - if(raster == NULL) - return AllocError; - - tgp->bits = raster; - - /* If FT_GET_DUMMY is set, we return white space. */ - if ( is_outline == -1 ) return Successful; - - if ( wd_actual <= 0 || ht_actual <= 0 ) return Successful; - - /* - * CALCULATE OFFSET, dx AND dy. - */ - - dx = face->face->glyph->bitmap_left - tgp->metrics.leftSideBearing; - dy = tgp->metrics.ascent - face->face->glyph->bitmap_top; - - if(instance->ttcap.flags & TTCAP_MONO_CENTER) - dx += b_shift; - - /* To prevent chipped bitmap, we correct dx and dy if needed. */ - if( correct && is_outline==1 ){ - int lsb, rsb, asc, des; - int chip_left,chip_right,chip_top,chip_bot; -#ifdef USE_GET_CBOX - FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox); - ftrc=0; -#else - ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox); -#endif - if( ftrc != 0 ) return FTtoXReturnCode(ftrc); - des = CEIL64(-bbox.yMin - 32) / 64; - lsb = FLOOR64(bbox.xMin + 32) / 64; - asc = FLOOR64(bbox.yMax + 32) / 64; - rsb = FLOOR64(bbox.xMax + 32) / 64; - rightSideBearing = tgp->metrics.rightSideBearing; - leftSideBearing = tgp->metrics.leftSideBearing; - if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE ) - rightSideBearing -= instance->ttcap.doubleStrikeShift; - /* special case */ - if(instance->ttcap.flags & TTCAP_MONO_CENTER){ - leftSideBearing -= b_shift; - rightSideBearing -= b_shift; - } - chip_left = lsb - leftSideBearing; - chip_right = rightSideBearing - rsb; - if( flags & FT_FORCE_CONSTANT_SPACING ){ - if( instance->ttcap.force_c_adjust_lsb_by_pixel != 0 || - instance->ttcap.force_c_adjust_rsb_by_pixel != 0 ){ - chip_left=0; - chip_right=0; - } - } - else{ - if( instance->ttcap.adjustRightSideBearingByPixel != 0 || - instance->ttcap.adjustLeftSideBearingByPixel != 0 ){ - chip_left=0; - chip_right=0; - } - } - chip_top = tgp->metrics.ascent - asc; - chip_bot = tgp->metrics.descent - des; - if( chip_left < 0 && 0 < chip_right ) dx++; - else if( chip_right < 0 && 0 < chip_left ) dx--; - if( chip_top < 0 && 0 < chip_bot ) dy++; - else if( chip_bot < 0 && 0 < chip_top ) dy--; - } - - /* - * COPY RASTER - */ - - { - FT_Bitmap *bitmap; - int i, j; - unsigned char *current_raster; - unsigned char *current_buffer; - int mod_dx0,mod_dx1; - int div_dx; - bitmap = &face->face->glyph->bitmap; - if( 0 <= dx ){ - div_dx = dx / 8; - mod_dx0 = dx % 8; - mod_dx1 = 8-mod_dx0; - } - else{ - div_dx = dx / 8 -1; - mod_dx1 = -dx % 8; - mod_dx0 = 8-mod_dx1; - } - for( i = MAX(0, dy) ; i<ht ; i++ ){ - int prev_jj,jj; - if( bitmap->rows <= i-dy ) break; - current_buffer=(unsigned char *)(bitmap->buffer+bitmap->pitch*(i-dy)); - current_raster=(unsigned char *)(raster+i*bpr); - j = MAX(0,div_dx); - jj = j-div_dx; - prev_jj = jj-1; - if( j<bpr ){ - if( 0 <= prev_jj && prev_jj < bitmap->pitch ) - current_raster[j]|=current_buffer[prev_jj]<<mod_dx1; - if( 0 <= jj && jj < bitmap->pitch ){ - current_raster[j]|=current_buffer[jj]>>mod_dx0; - j++; prev_jj++; jj++; - for( ; j<bpr ; j++,prev_jj++,jj++ ){ - current_raster[j]|=current_buffer[prev_jj]<<mod_dx1; - if( bitmap->pitch <= jj ) break; - current_raster[j]|=current_buffer[jj]>>mod_dx0; - } - } - } - } - } - - /* by TTCap */ - if ( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE ) { - int i; - for( i=0 ; i < instance->ttcap.doubleStrikeShift ; i++ ) - ft_make_up_bold_bitmap( raster, bpr, ht, instance->ttcap.flags); - } - if ( is_outline == 0 && - ( instance->ttcap.lsbShiftOfBitmapAutoItalic != 0 || - instance->ttcap.rsbShiftOfBitmapAutoItalic != 0 ) ) { - ft_make_up_italic_bitmap( raster, bpr, ht, - - instance->ttcap.lsbShiftOfBitmapAutoItalic - + instance->ttcap.rsbShiftOfBitmapAutoItalic, - instance->charcellMetrics->ascent - + instance->charcellMetrics->descent, - instance->charcellMetrics->ascent - - tgp->metrics.ascent, - instance->ttcap.autoItalic); - } - - if(instance->bmfmt.bit == LSBFirst) { - BitOrderInvert((unsigned char*)(tgp->bits), ht*bpr); - } - - if(instance->bmfmt.byte != instance->bmfmt.bit) { - switch(instance->bmfmt.scan) { - case 1: - break; - case 2: - TwoByteSwap((unsigned char*)(tgp->bits), ht*bpr); - break; - case 4: - FourByteSwap((unsigned char*)(tgp->bits), ht*bpr); - break; - default: - ; - } - } - - return Successful; -} - -static void -FreeTypeFreeFont(FTFontPtr font) -{ - FreeTypeFreeInstance(font->instance); - if(font->ranges) - free(font->ranges); - if(font->dummy_char.bits) - free(font->dummy_char.bits); - free(font); -} - -/* Free a font. If freeProps is 0, don't free the properties. */ - -static void -FreeTypeFreeXFont(FontPtr pFont, int freeProps) -{ - FTFontPtr tf; - - if(pFont) { - if((tf = (FTFontPtr)pFont->fontPrivate)) { - FreeTypeFreeFont(tf); - } - if(freeProps && pFont->info.nprops>0) { - free(pFont->info.isStringProp); - free(pFont->info.props); - } - DestroyFontRec(pFont); - } -} - - -/* Unload a font */ - -static void -FreeTypeUnloadXFont(FontPtr pFont) -{ - MUMBLE("Unloading\n"); - FreeTypeFreeXFont(pFont, 1); -} - -/* Add the font properties, including the Font name, the XLFD - properties, some strings from the font, and various typographical - data. We only provide data readily available in the tables in the - font for now, altough FIGURE_WIDTH would be a good idea as it is - used by Xaw. */ - -static int -FreeTypeAddProperties(FTFontPtr font, FontScalablePtr vals, FontInfoPtr info, - char *fontname, int rawAverageWidth, Bool font_properties) -{ - int i, j, maxprops; - char *sp, *ep, val[MAXFONTNAMELEN], *vp; - FTFacePtr face; - FTInstancePtr instance; - FTNormalisedTransformationPtr trans; - int upm; - TT_OS2 *os2; - TT_Postscript *post; - PS_FontInfoRec t1info_rec, *t1info; - int xlfdProps = 0; - int ftrc; - - instance = font->instance; - face = instance->face; - trans = &instance->transformation; - upm = face->face->units_per_EM; - if(upm == 0) { - /* Work around FreeType bug */ - upm = WORK_AROUND_UPM; - } - - os2 = FT_Get_Sfnt_Table(face->face, ft_sfnt_os2); - post = FT_Get_Sfnt_Table(face->face, ft_sfnt_post); - ftrc = FT_Get_PS_Font_Info(face->face, &t1info_rec); - if(ftrc == 0) - t1info = &t1info_rec; - else - t1info = NULL; - - if(t1info) { - os2 = NULL; - post = NULL; - } - - info->nprops = 0; /* in case we abort */ - - strcpy(val, fontname); - if(FontParseXLFDName(val, vals, FONT_XLFD_REPLACE_VALUE)) { - xlfdProps = 1; - } else { - MUMBLE("Couldn't parse XLFD\n"); - xlfdProps = 0; - } - - maxprops= - 1 + /* NAME */ - (xlfdProps ? 14 : 0) + /* from XLFD */ - 5 + - ( !face->bitmap ? 3 : 0 ) + /* raw_av,raw_asc,raw_dec */ - ( font_properties ? 2 : 0 ) + /* asc,dec */ - ( (font_properties && os2) ? 6 : 0 ) + - ( (font_properties && (post || t1info)) ? 3 : 0 ) + - 2; /* type */ - - info->props = malloc(maxprops * sizeof(FontPropRec)); - if(info->props == NULL) - return AllocError; - - info->isStringProp = malloc(maxprops); - if(info->isStringProp == NULL) { - free(info->props); - return AllocError; - } - - memset((char *)info->isStringProp, 0, maxprops); - - i = 0; - - info->props[i].name = MakeAtom("FONT", 4, TRUE); - info->props[i].value = MakeAtom(val, strlen(val), TRUE); - info->isStringProp[i] = 1; - i++; - - if(*val && *(sp = val + 1)) { - for (j = 0, sp = val + 1; j < 14; j++) { - if (j == 13) - /* Handle the case of the final field containing a subset - specification. */ - for (ep = sp; *ep && *ep != '['; ep++); - else - for (ep = sp; *ep && *ep != '-'; ep++); - - info->props[i].name = - MakeAtom(xlfd_props[j], strlen(xlfd_props[j]), TRUE); - - switch(j) { - case 6: /* pixel size */ - info->props[i].value = - (int)(fabs(vals->pixel_matrix[3]) + 0.5); - i++; - break; - case 7: /* point size */ - info->props[i].value = - (int)(fabs(vals->point_matrix[3])*10.0 + 0.5); - i++; - break; - case 8: /* resolution x */ - info->props[i].value = vals->x; - i++; - break; - case 9: /* resolution y */ - info->props[i].value = vals->y; - i++; - break; - case 11: /* average width */ - info->props[i].value = vals->width; - i++; - break; - default: /* a string */ - info->props[i].value = MakeAtom(sp, ep - sp, TRUE); - info->isStringProp[i] = 1; - i++; - } - sp = ++ep; - } - } - - info->props[i].name = MakeAtom("RAW_PIXEL_SIZE", 14, TRUE); - info->props[i].value = 1000; - i++; - - info->props[i].name = MakeAtom("RAW_POINT_SIZE", 14, TRUE); - info->props[i].value = (long)(72270.0 / (double)vals->y + .5); - i++; - - if(!face->bitmap) { - info->props[i].name = MakeAtom("RAW_AVERAGE_WIDTH", 17, TRUE); - info->props[i].value = rawAverageWidth; - i++; - } - - if ( font_properties ) { - info->props[i].name = MakeAtom("FONT_ASCENT", 11, TRUE); - info->props[i].value = info->fontAscent; - i++; - } - - if(!face->bitmap) { - info->props[i].name = MakeAtom("RAW_ASCENT", 10, TRUE); - info->props[i].value = - ((double)face->face->ascender/(double)upm*1000.0); - i++; - } - - if ( font_properties ) { - info->props[i].name = MakeAtom("FONT_DESCENT", 12, TRUE); - info->props[i].value = info->fontDescent; - i++; - } - - if(!face->bitmap) { - info->props[i].name = MakeAtom("RAW_DESCENT", 11, TRUE); - info->props[i].value = - -((double)face->face->descender/(double)upm*1000.0); - i++; - } - - j = FTGetEnglishName(face->face, TT_NAME_ID_COPYRIGHT, - val, MAXFONTNAMELEN); - vp = val; - if (j < 0) { - if(t1info && t1info->notice) { - vp = t1info->notice; - j = strlen(vp); - } - } - if(j > 0) { - info->props[i].name = MakeAtom("COPYRIGHT", 9, TRUE); - info->props[i].value = MakeAtom(vp, j, TRUE); - info->isStringProp[i] = 1; - i++; - } - - j = FTGetEnglishName(face->face, TT_NAME_ID_FULL_NAME, - val, MAXFONTNAMELEN); - vp = val; - if (j < 0) { - if(t1info && t1info->full_name) { - vp = t1info->full_name; - j = strlen(vp); - } - } - if(j > 0) { - info->props[i].name = MakeAtom("FACE_NAME", 9, TRUE); - info->props[i].value = MakeAtom(vp, j, TRUE); - info->isStringProp[i] = 1; - i++; - } - - vp = (char *)FT_Get_Postscript_Name(face->face); - if (vp) { - j = strlen(vp); - } else { - j = -1; - } - if (j < 0) { - j = FTGetEnglishName(face->face, TT_NAME_ID_PS_NAME, - val, MAXFONTNAMELEN); - vp = val; - } - if (j < 0) { - if(t1info && t1info->full_name) { - vp = t1info->full_name; - j = strlen(vp); - } - } - if(j > 0) { - info->props[i].name = MakeAtom("_ADOBE_POSTSCRIPT_FONTNAME", 26, TRUE); - info->props[i].value = MakeAtom(vp, j, TRUE); - info->isStringProp[i] = 1; - i++; - } - - /* These macros handle the case of a diagonal matrix. They convert - FUnits into pixels. */ -#define TRANSFORM_FUNITS_X(xval) \ - ((int) \ - floor( ((double)(xval)/(double)upm) * (double)vals->pixel_matrix[0] + 0.5 ) ) - -#define TRANSFORM_FUNITS_Y(yval) \ - ((int) \ - floor( ((double)(yval)/(double)upm) * (double)vals->pixel_matrix[3] + 0.5 ) ) - - /* In what follows, we assume the matrix is diagonal. In the rare - case when it is not, the values will be somewhat wrong. */ - - if( font_properties && os2 ) { - info->props[i].name = MakeAtom("SUBSCRIPT_SIZE",14,TRUE); - info->props[i].value = - TRANSFORM_FUNITS_Y(os2->ySubscriptYSize); - i++; - info->props[i].name = MakeAtom("SUBSCRIPT_X",11,TRUE); - info->props[i].value = - TRANSFORM_FUNITS_X(os2->ySubscriptXOffset); - i++; - info->props[i].name = MakeAtom("SUBSCRIPT_Y",11,TRUE); - info->props[i].value = - TRANSFORM_FUNITS_Y(os2->ySubscriptYOffset); - i++; - info->props[i].name = MakeAtom("SUPERSCRIPT_SIZE",16,TRUE); - info->props[i].value = - TRANSFORM_FUNITS_Y(os2->ySuperscriptYSize); - i++; - info->props[i].name = MakeAtom("SUPERSCRIPT_X",13,TRUE); - info->props[i].value = - TRANSFORM_FUNITS_X(os2->ySuperscriptXOffset); - i++; - info->props[i].name = MakeAtom("SUPERSCRIPT_Y",13,TRUE); - info->props[i].value = - TRANSFORM_FUNITS_Y(os2->ySuperscriptYOffset); - i++; - } - - if( font_properties && (post || t1info) ) { - int underlinePosition, underlineThickness; - - /* Raw underlineposition counts upwards, - but UNDERLINE_POSITION counts downwards. */ - if(post) { - underlinePosition = TRANSFORM_FUNITS_Y(-post->underlinePosition); - underlineThickness = TRANSFORM_FUNITS_Y(post->underlineThickness); - } else { - underlinePosition = - TRANSFORM_FUNITS_Y(-t1info->underline_position); - underlineThickness = - TRANSFORM_FUNITS_Y(t1info->underline_thickness); - } - if(underlineThickness <= 0) - underlineThickness = 1; - - info->props[i].name = MakeAtom("UNDERLINE_THICKNESS",19,TRUE); - info->props[i].value = underlineThickness; - i++; - - info->props[i].name = MakeAtom("UNDERLINE_POSITION",18,TRUE); - - info->props[i].value = underlinePosition; - - i++; - - /* The italic angle is often unreliable for Type 1 fonts */ - if(post && trans->matrix.xx == trans->matrix.yy) { - info->props[i].name = MakeAtom("ITALIC_ANGLE",12,TRUE); - info->props[i].value = - /* Convert from TT_Fixed to - 64th of a degree counterclockwise from 3 o'clock */ - 90*64+(post->italicAngle >> 10); - i++; - } -#undef TRANSFORM_FUNITS_X -#undef TRANSFORM_FUNITS_Y - } - - info->props[i].name = MakeAtom("FONT_TYPE", 9, TRUE); - vp = (char *)FT_Get_X11_Font_Format(face->face); - info->props[i].value = MakeAtom(vp, strlen(vp), TRUE); - info->isStringProp[i] = 1; - i++; - - info->props[i].name = MakeAtom("RASTERIZER_NAME", 15, TRUE); - info->props[i].value = MakeAtom("FreeType", 10, TRUE); - info->isStringProp[i] = 1; - i++; - - info->nprops = i; - return Successful; -} - -static int -ft_get_index(unsigned code, FTFontPtr font, unsigned *idx) -{ - - /* As a special case, we pass 0 even when it is not in the ranges; - this will allow for the default glyph, which should exist in any - TrueType font. */ - - /* This is not required... - if(code > 0 && font->nranges) { - int i; - for(i = 0; i < font->nranges; i++) - if((code >= - font->ranges[i].min_char_low+ - (font->ranges[i].min_char_high<<8)) && - (code <= - font->ranges[i].max_char_low + - (font->ranges[i].max_char_high<<8))) - break; - if(i == font->nranges) { - *idx = font->zero_idx; - return -1; - } - } - */ - if( font->info ) { - if( !( font->info->firstCol <= (code & 0x000ff) && - (code & 0x000ff) <= font->info->lastCol && - font->info->firstRow <= (code >> 8) && - (code >> 8) <= font->info->lastRow ) ) { - *idx = font->zero_idx; - /* Error: The code has not been parsed in ft_compute_bounds()! - We should not return any metrics. */ - return -1; - } - } - - *idx = FTRemap(font->instance->face->face, &font->mapping, code); - - return 0; -} - -static int -FreeTypeFontGetGlyph(unsigned code, int flags, CharInfoPtr *g, FTFontPtr font) -{ - unsigned idx = 0; - int xrc; - -#ifdef X_ACCEPTS_NO_SUCH_CHAR - if( ft_get_index(code,font,&idx) || idx == 0 || idx == font->zero_idx ) { - *g = NULL; - flags &= ~FT_FORCE_CONSTANT_SPACING; - /* if( font->instance->spacing != FT_CHARCELL ) */ - return Successful; - } -#else - if( ft_get_index(code,font,&idx) ) { - /* The code has not been parsed! */ - *g = NULL; - flags &= ~FT_FORCE_CONSTANT_SPACING; - } -#endif - - xrc = FreeTypeInstanceGetGlyph(idx, flags, g, font->instance); - if( xrc == Successful && *g != NULL ) - return Successful; - if( font->zero_idx != idx ) { - xrc = FreeTypeInstanceGetGlyph(font->zero_idx, flags, g, font->instance); - if( xrc == Successful && *g != NULL ) - return Successful; - } - return FreeTypeInstanceGetGlyph(font->zero_idx, flags|FT_GET_DUMMY, g, font->instance); -} - -static int -FreeTypeFontGetGlyphMetrics(unsigned code, int flags, xCharInfo **metrics, FTFontPtr font) -{ - unsigned idx = 0; - int xrc; - -#ifdef X_ACCEPTS_NO_SUCH_CHAR - if ( ft_get_index(code,font,&idx) || idx == 0 || idx == font->zero_idx ) { - *metrics = NULL; - flags &= ~FT_FORCE_CONSTANT_SPACING; - /* if( font->instance->spacing != FT_CHARCELL ) */ - return Successful; - } -#else - if ( ft_get_index(code,font,&idx) || idx == 0 || idx == font->zero_idx ) { - /* The code has not been parsed! */ - *metrics = NULL; - flags &= ~FT_FORCE_CONSTANT_SPACING; - } -#endif - - xrc = FreeTypeInstanceGetGlyphMetrics(idx, flags, metrics, font->instance); - if( xrc == Successful && *metrics != NULL ) - return Successful; - if( font->zero_idx != idx ) { - xrc = FreeTypeInstanceGetGlyphMetrics(font->zero_idx, flags, - metrics, font->instance); - if( xrc == Successful && *metrics != NULL ) - return Successful; - } - return FreeTypeInstanceGetGlyphMetrics(font->zero_idx, flags|FT_GET_DUMMY, metrics, font->instance); -} - -/* - * restrict code range - * - * boolean for the numeric zone: - * results = results & (ranges[0] | ranges[1] | ... ranges[nranges-1]) - */ - -static void -restrict_code_range(unsigned short *refFirstCol, - unsigned short *refFirstRow, - unsigned short *refLastCol, - unsigned short *refLastRow, - fsRange const *ranges, int nRanges) -{ - if (nRanges) { - int minCol = 256, minRow = 256, maxCol = -1, maxRow = -1; - fsRange const *r = ranges; - int i; - - for (i=0; i<nRanges; i++) { - if (r->min_char_high != r->max_char_high) { - minCol = 0x00; - maxCol = 0xff; - } else { - if (minCol > r->min_char_low) - minCol = r->min_char_low; - if (maxCol < r->max_char_low) - maxCol = r->max_char_low; - } - if (minRow > r->min_char_high) - minRow = r->min_char_high; - if (maxRow < r->max_char_high) - maxRow = r->max_char_high; - r++; - } - - if (minCol > *refLastCol) - *refFirstCol = *refLastCol; - else if (minCol > *refFirstCol) - *refFirstCol = minCol; - - if (maxCol < *refFirstCol) - *refLastCol = *refFirstCol; - else if (maxCol < *refLastCol) - *refLastCol = maxCol; - - if (minRow > *refLastRow) { - *refFirstRow = *refLastRow; - *refFirstCol = *refLastCol; - } else if (minRow > *refFirstRow) - *refFirstRow = minRow; - - if (maxRow < *refFirstRow) { - *refLastRow = *refFirstRow; - *refLastCol = *refFirstCol; - } else if (maxRow < *refLastRow) - *refLastRow = maxRow; - } -} - - -static int -restrict_code_range_by_str(int count,unsigned short *refFirstCol, - unsigned short *refFirstRow, - unsigned short *refLastCol, - unsigned short *refLastRow, - char const *str) -{ - int nRanges = 0; - int result = 0; - fsRange *ranges = NULL; - char const *p, *q; - - p = q = str; - for (;;) { - int minpoint=0, maxpoint=65535; - long val; - - /* skip comma and/or space */ - while (',' == *p || isspace(*p)) - p++; - - /* begin point */ - if ('-' != *p) { - val = strtol(p, (char **)&q, 0); - if (p == q) - /* end or illegal */ - break; - if (val<0 || val>65535) { - /* out of zone */ - break; - } - minpoint = val; - p=q; - } - - /* skip space */ - while (isspace(*p)) - p++; - - if (',' != *p && '\0' != *p) { - /* contiune */ - if ('-' == *p) - /* hyphon */ - p++; - else - /* end or illegal */ - break; - - /* skip space */ - while (isspace(*p)) - p++; - - val = strtol(p, (char **)&q, 0); - if (p != q) { - if (val<0 || val>65535) - break; - maxpoint = val; - } else if (',' != *p && '\0' != *p) - /* end or illegal */ - break; - p=q; - } else - /* comma - single code */ - maxpoint = minpoint; - - if ( count <= 0 && minpoint>maxpoint ) { - int tmp; - tmp = minpoint; - minpoint = maxpoint; - maxpoint = tmp; - } - - /* add range */ -#if 0 - fprintf(stderr, "zone: 0x%04X - 0x%04X\n", minpoint, maxpoint); - fflush(stderr); -#endif - nRanges++; - ranges = realloc(ranges, nRanges*sizeof(*ranges)); - if (NULL == ranges) - break; - { - fsRange *r = ranges+nRanges-1; - - r->min_char_low = minpoint & 0xff; - r->max_char_low = maxpoint & 0xff; - r->min_char_high = (minpoint>>8) & 0xff; - r->max_char_high = (maxpoint>>8) & 0xff; - } - } - - if (ranges) { - if ( count <= 0 ) { - restrict_code_range(refFirstCol, refFirstRow, refLastCol, refLastRow, - ranges, nRanges); - } - else { - int i; - fsRange *r; - for ( i=0 ; i<nRanges ; i++ ) { - if ( count <= i ) break; - r = ranges+i; - refFirstCol[i] = r->min_char_low; - refLastCol[i] = r->max_char_low; - refFirstRow[i] = r->min_char_high; - refLastRow[i] = r->max_char_high; - } - result=i; - } - free(ranges); - } - return result; -} - -/* *face_number and *spacing are initialized but *load_flags is NOT. */ -static int -FreeTypeSetUpTTCap( char *fileName, FontScalablePtr vals, - char **dynStrRealFileName, char **dynStrFTFileName, - struct TTCapInfo *ret, int *face_number, FT_Int32 *load_flags, - int *spacing, Bool *font_properties, char **dynStrTTCapCodeRange ) -{ - int result = Successful; - SDynPropRecValList listPropRecVal; - SPropRecValContainer contRecValue; - Bool hinting=True; - Bool isEmbeddedBitmap = True; - Bool alwaysEmbeddedBitmap = False; - int pixel = vals->pixel; - - *font_properties=True; - *dynStrRealFileName=NULL; - *dynStrFTFileName=NULL; - *dynStrTTCapCodeRange=NULL; - - if (SPropRecValList_new(&listPropRecVal)) { - return AllocError; - } - - { - int len = strlen(fileName); - char *capHead = NULL; - { - /* font cap */ - char *p1=NULL, *p2=NULL; - - p1=strrchr(fileName, '/'); - if ( p1 == NULL ) p1 = fileName; - else p1++; - if (NULL != (p2=strrchr(p1, ':'))) { - /* colon exist in the right side of slash. */ - int dirLen = p1-fileName; - int baseLen = fileName+len - p2 -1; - - *dynStrRealFileName = malloc(dirLen+baseLen+1); - if( *dynStrRealFileName == NULL ) { - result = AllocError; - goto quit; - } - if ( 0 < dirLen ) - memcpy(*dynStrRealFileName, fileName, dirLen); - strcpy(*dynStrRealFileName+dirLen, p2+1); - capHead = p1; - } else { - *dynStrRealFileName = xstrdup(fileName); - if( *dynStrRealFileName == NULL ) { - result = AllocError; - goto quit; - } - } - } - - /* font cap */ - if (capHead) { - if (SPropRecValList_add_by_font_cap(&listPropRecVal, - capHead)) { - result = BadFontPath; - goto quit; - } - } - } - - *face_number=0; - *spacing=0; - ret->autoItalic=0.0; - ret->scaleWidth=1.0; - ret->scaleBBoxWidth = 1.0; - ret->scaleBBoxHeight = 1.0; - ret->doubleStrikeShift = 1; - ret->adjustBBoxWidthByPixel = 0; - ret->adjustLeftSideBearingByPixel = 0; - ret->adjustRightSideBearingByPixel = 0; - ret->flags = 0; - ret->scaleBitmap = 0.0; - ret->forceConstantSpacingBegin = -1; - ret->forceConstantSpacingEnd = -1; - ret->force_c_representative_metrics_char_code = -2; - ret->force_c_scale_b_box_width = 1.0; - ret->force_c_scale_b_box_height = 1.0; - ret->force_c_adjust_width_by_pixel = 0; - ret->force_c_adjust_lsb_by_pixel = 0; - ret->force_c_adjust_rsb_by_pixel = 0; - ret->force_c_scale_lsb = 0.0; - ret->force_c_scale_rsb = 1.0; - /* */ - ret->vl_slant=0; - ret->lsbShiftOfBitmapAutoItalic=0; - ret->rsbShiftOfBitmapAutoItalic=0; - /* face number */ - { - char *beginptr=NULL,*endptr; - if ( SPropRecValList_search_record(&listPropRecVal, - &contRecValue, - "FaceNumber")) { - int lv; - beginptr = SPropContainer_value_str(contRecValue); - lv=strtol(beginptr, &endptr, 10); - if ( *beginptr != '\0' && *endptr == '\0' ) { - if ( 0 < lv ) *face_number = lv; - } - } - if( beginptr && 0 < *face_number ) { - char *slash; - *dynStrFTFileName = /* add -> ':'+strlen0+':'+strlen1+'\0' */ - malloc(1+strlen(beginptr)+1+strlen(*dynStrRealFileName)+1); - if( *dynStrFTFileName == NULL ){ - result = AllocError; - goto quit; - } - **dynStrFTFileName = '\0'; - slash = strrchr(*dynStrRealFileName,'/'); - if( slash ) { - char *p; - strcat(*dynStrFTFileName,*dynStrRealFileName); - p = strrchr(*dynStrFTFileName,'/'); - p[1] = '\0'; - strcat(*dynStrFTFileName,":"); - strcat(*dynStrFTFileName,beginptr); - strcat(*dynStrFTFileName,":"); - strcat(*dynStrFTFileName,slash+1); - } - else{ - strcat(*dynStrFTFileName,":"); - strcat(*dynStrFTFileName,beginptr); - strcat(*dynStrFTFileName,":"); - strcat(*dynStrFTFileName,*dynStrRealFileName); - } - } - else{ - *dynStrFTFileName = malloc(strlen(*dynStrRealFileName)+1); - if( *dynStrFTFileName == NULL ){ - result = AllocError; - goto quit; - } - **dynStrFTFileName = '\0'; - strcat(*dynStrFTFileName,*dynStrRealFileName); - } - } - /* - fprintf(stderr,"[Filename:%s]\n",fileName); - fprintf(stderr,"[RealFilename:%s]\n",*dynStrRealFileName); - fprintf(stderr,"[FTFilename:%s]\n",*dynStrFTFileName); - */ - /* slant control */ - if (SPropRecValList_search_record(&listPropRecVal, - &contRecValue, - "AutoItalic")) - ret->autoItalic = SPropContainer_value_dbl(contRecValue); - /* hinting control */ - if (SPropRecValList_search_record(&listPropRecVal, - &contRecValue, - "Hinting")) - hinting = SPropContainer_value_bool(contRecValue); - /* scaling */ - if (SPropRecValList_search_record(&listPropRecVal, - &contRecValue, - "ScaleWidth")) { - ret->scaleWidth = SPropContainer_value_dbl(contRecValue); - if (ret->scaleWidth<=0.0) { - fprintf(stderr, "ScaleWitdh needs plus.\n"); - result = BadFontName; - goto quit; - } - } - /* bbox adjustment */ - if (SPropRecValList_search_record(&listPropRecVal, - &contRecValue, - "ScaleBBoxWidth")) { - /* Scaling to Bounding Box Width */ - int lv; - char *endptr,*beginptr; - double v,scaleBBoxWidth=1.0,scaleBBoxHeight=1.0; - beginptr = SPropContainer_value_str(contRecValue); - do { - if ( strlen(beginptr) < 1 ) break; - v=strtod(beginptr, &endptr); - if ( endptr!=beginptr ) { - scaleBBoxWidth = v; - } - if ( *endptr != ';' && *endptr != ',' ) break; - if ( *endptr == ',' ) { - beginptr=endptr+1; - v=strtod(beginptr, &endptr); - if ( endptr!=beginptr ) { - scaleBBoxHeight = v; - } - } - if ( *endptr != ';' && *endptr != ',' ) break; - beginptr=endptr+1; - lv=strtol(beginptr, &endptr, 10); - if ( endptr!=beginptr ) { - ret->adjustBBoxWidthByPixel = lv; - } - if ( *endptr != ',' ) break; - beginptr=endptr+1; - lv=strtol(beginptr, &endptr, 10); - if ( endptr!=beginptr ) { - ret->adjustLeftSideBearingByPixel = lv; - } - if ( *endptr != ',' ) break; - beginptr=endptr+1; - lv=strtol(beginptr, &endptr, 10); - if ( endptr!=beginptr ) { - ret->adjustRightSideBearingByPixel = lv; - } - } while ( 0 ); - if (scaleBBoxWidth<=0.0) { - fprintf(stderr, "ScaleBBoxWitdh needs plus.\n"); - result = BadFontName; - goto quit; - } - if (scaleBBoxHeight<=0.0) { - fprintf(stderr, "ScaleBBoxHeight needs plus.\n"); - result = BadFontName; - goto quit; - } - ret->scaleBBoxWidth = scaleBBoxWidth; - ret->scaleBBoxHeight = scaleBBoxHeight; - } - /* spacing */ - if (SPropRecValList_search_record(&listPropRecVal, - &contRecValue, - "ForceSpacing")) { - char *strSpace = SPropContainer_value_str(contRecValue); - Bool err = False; - if (1 != strlen(strSpace)) - err = True; - else - switch (strSpace[0]) { - case 'M': - ret->flags |= TTCAP_MONO_CENTER; - *spacing = 'm'; - break; - case 'm': - case 'p': - case 'c': - *spacing = strSpace[0]; - break; - default: - err = True; - } - if (err) { - result = BadFontName; - goto quit; - } - } - /* doube striking */ - if (SPropRecValList_search_record(&listPropRecVal, - &contRecValue, - "DoubleStrike")) { - /* Set or Reset Auto Bold Flag */ - char *strDoubleStrike = SPropContainer_value_str(contRecValue); - Bool err = False; - if ( 0 < strlen(strDoubleStrike) ) { - switch (strDoubleStrike[0]) { - case 'm': - case 'M': - case 'l': - case 'L': - ret->flags |= TTCAP_DOUBLE_STRIKE; - ret->flags |= TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT; - break; - case 'y': - case 'Y': - ret->flags |= TTCAP_DOUBLE_STRIKE; - break; - case 'n': - case 'N': - ret->flags &= ~TTCAP_DOUBLE_STRIKE; - ret->flags &= ~TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT; - ret->flags &= ~TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH; - break; - default: - err = True; - } - if ( err != True ) { - if ( strDoubleStrike[1] ) { - switch (strDoubleStrike[1]) { - case 'b': - case 'B': - case 'p': - case 'P': - case 'y': - case 'Y': - ret->flags |= TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH; - break; - default: - break; - } - } - do { - char *comma_ptr=strchr(strDoubleStrike,';'); - if ( !comma_ptr ) comma_ptr=strchr(strDoubleStrike,','); - if ( !comma_ptr ) break; - if ( comma_ptr[1] ) { - char *endptr; - int mkboldMaxPixel; - mkboldMaxPixel=strtol(comma_ptr+1, &endptr, 10); - if ( endptr != comma_ptr+1 && mkboldMaxPixel <= pixel ) { - ret->flags &= ~TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT; - } - } - comma_ptr=strchr(comma_ptr+1,','); - if ( !comma_ptr ) break; - if ( comma_ptr[1] ) { - char *endptr; - int max_pixel; - max_pixel=strtol(comma_ptr+1, &endptr, 10); - if ( endptr != comma_ptr+1 && max_pixel <= pixel ) { - if( ret->flags & TTCAP_DOUBLE_STRIKE ) - ret->doubleStrikeShift += pixel / max_pixel; - } - } - } while(0); - } - } - else - err = True; - if (err) { - result = BadFontName; - goto quit; - } - } - /* very lazy metrics */ - if (SPropRecValList_search_record(&listPropRecVal, - &contRecValue, - "VeryLazyMetrics")){ - Bool isVeryLazy = SPropContainer_value_bool(contRecValue); - ret->flags |= TTCAP_DISABLE_DEFAULT_VERY_LAZY; - if( isVeryLazy == True ) - ret->flags |= TTCAP_IS_VERY_LAZY; - else - ret->flags &= ~TTCAP_IS_VERY_LAZY; - } - /* embedded bitmap */ - if (SPropRecValList_search_record(&listPropRecVal, - &contRecValue, - "EmbeddedBitmap")) { - char *strEmbeddedBitmap = SPropContainer_value_str(contRecValue); - Bool err = False; - if ( 1 == strlen(strEmbeddedBitmap) ) { - switch (strEmbeddedBitmap[0]) { - case 'y': - case 'Y': - isEmbeddedBitmap = True; - alwaysEmbeddedBitmap = True; - break; - case 'u': - case 'U': - isEmbeddedBitmap = True; - alwaysEmbeddedBitmap = False; - break; - case 'n': - case 'N': - isEmbeddedBitmap = False; - break; - default: - err = True; - } - } - else - err = True; - if (err) { - result = BadFontName; - goto quit; - } - } - /* scale bitmap */ - if((ret->flags & TTCAP_IS_VERY_LAZY) && - SPropRecValList_search_record(&listPropRecVal, - &contRecValue, - "VeryLazyBitmapWidthScale")) { - /* Scaling to Bitmap Bounding Box Width */ - double scaleBitmapWidth = SPropContainer_value_dbl(contRecValue); - - fprintf(stderr, "Warning: `bs' option is not required in X-TT version 2.\n"); -#if 0 - if (scaleBitmapWidth<=0.0) { - fprintf(stderr, "ScaleBitmapWitdh needs plus.\n"); - result = BadFontName; - goto quit; - } -#endif - ret->scaleBitmap = scaleBitmapWidth; - } - /* restriction of the code range */ - if (SPropRecValList_search_record(&listPropRecVal, - &contRecValue, - "CodeRange")) { - *dynStrTTCapCodeRange = xstrdup(SPropContainer_value_str(contRecValue)); - if( *dynStrTTCapCodeRange == NULL ) { - result = AllocError; - goto quit; - } - } - /* forceConstantSpacing{Begin,End} */ - if ( 1 /* ft->spacing == 'p' */ ){ - unsigned short first_col=0,last_col=0x00ff; - unsigned short first_row=0,last_row=0x00ff; - if (SPropRecValList_search_record(&listPropRecVal, - &contRecValue, - "ForceConstantSpacingCodeRange")) { - if ( restrict_code_range_by_str(1,&first_col, &first_row, - &last_col, &last_row, - SPropContainer_value_str(contRecValue)) == 1 ) { - ret->forceConstantSpacingBegin = (int)( first_row<<8 | first_col ); - ret->forceConstantSpacingEnd = (int)( last_row<<8 | last_col ); - if ( ret->forceConstantSpacingBegin <= ret->forceConstantSpacingEnd ) - ret->flags &= ~TTCAP_FORCE_C_OUTSIDE; - else ret->flags |= TTCAP_FORCE_C_OUTSIDE; - } - } - } - /* */ - if ( 1 ){ - unsigned short first_col=0, last_col=0x0ff; - unsigned short first_row=0, last_row=0x0ff; - if ( SPropRecValList_search_record(&listPropRecVal, - &contRecValue, - "ForceConstantSpacingMetrics")) { - char *strMetrics; - strMetrics = SPropContainer_value_str(contRecValue); - if ( strMetrics ) { - char *comma_ptr,*period_ptr,*semic_ptr; - semic_ptr=strchr(strMetrics,';'); - comma_ptr=strchr(strMetrics,','); - period_ptr=strchr(strMetrics,'.'); - if ( semic_ptr && comma_ptr ) - if ( semic_ptr < comma_ptr ) comma_ptr=NULL; - if ( semic_ptr && period_ptr ) - if ( semic_ptr < period_ptr ) period_ptr=NULL; - if ( !comma_ptr && !period_ptr && strMetrics != semic_ptr ) { - if ( restrict_code_range_by_str(1,&first_col, &first_row, - &last_col, &last_row, - SPropContainer_value_str(contRecValue)) == 1 ) { - ret->force_c_representative_metrics_char_code = - (int)( first_row<<8 | first_col ); - } - } - else { - double v; - char *endptr,*beginptr=strMetrics; - do { - v=strtod(beginptr, &endptr); - if ( endptr!=beginptr ) { - ret->force_c_scale_b_box_width = v; - } - if ( *endptr != ',' ) break; - beginptr=endptr+1; - v=strtod(beginptr, &endptr); - if ( endptr!=beginptr ) { - ret->force_c_scale_lsb = v; - ret->flags |= TTCAP_FORCE_C_LSB_FLAG; - } - if ( *endptr != ',' ) break; - beginptr=endptr+1; - v=strtod(beginptr, &endptr); - if ( endptr!=beginptr ) { - ret->force_c_scale_rsb = v; - ret->flags |= TTCAP_FORCE_C_RSB_FLAG; - } - if ( *endptr != ',' ) break; - beginptr=endptr+1; - v=strtod(beginptr, &endptr); - if ( endptr!=beginptr ) { - ret->force_c_scale_b_box_height = v; - } - } while (0); - } - if ( semic_ptr ) { - int lv; - char *endptr,*beginptr=semic_ptr+1; - do { - lv=strtol(beginptr, &endptr, 10); - if ( endptr!=beginptr ) { - ret->force_c_adjust_width_by_pixel=lv; - } - if ( *endptr != ',' ) break; - beginptr=endptr+1; - lv=strtol(beginptr, &endptr, 10); - if ( endptr!=beginptr ) { - ret->force_c_adjust_lsb_by_pixel=lv; - } - if ( *endptr != ',' ) break; - beginptr=endptr+1; - lv=strtol(beginptr, &endptr, 10); - if ( endptr!=beginptr ) { - ret->force_c_adjust_rsb_by_pixel=lv; - } - } while (0); - } - } - } - } - - if (SPropRecValList_search_record(&listPropRecVal, - &contRecValue, - "FontProperties")) { - /* Set or Reset the Flag of FontProperties */ - *font_properties=SPropContainer_value_bool(contRecValue); - } - - ret->force_c_scale_b_box_width *= ret->scaleBBoxWidth; - ret->force_c_scale_b_box_height *= ret->scaleBBoxHeight; - - ret->force_c_scale_b_box_width *= ret->scaleWidth; - ret->scaleBBoxWidth *= ret->scaleWidth; - - ret->force_c_adjust_rsb_by_pixel += ret->adjustRightSideBearingByPixel; - ret->force_c_adjust_lsb_by_pixel += ret->adjustLeftSideBearingByPixel; - - /* scaleWidth, scaleBBoxWidth, force_c_scale_b_box_width, force_c_scale_b_box_width */ - - /* by TTCap */ - if( hinting == False ) *load_flags |= FT_LOAD_NO_HINTING; - if( isEmbeddedBitmap == False ) *load_flags |= FT_LOAD_NO_BITMAP; - if( ret->autoItalic != 0 && alwaysEmbeddedBitmap == False ) - *load_flags |= FT_LOAD_NO_BITMAP; - - quit: - return result; -} - -static int -ft_get_trans_from_vals( FontScalablePtr vals, FTNormalisedTransformationPtr trans ) -{ - /* Compute the transformation matrix. We use floating-point - arithmetic for simplicity */ - - trans->xres = vals->x; - trans->yres = vals->y; - - /* This value cannot be 0. */ - trans->scale = hypot(vals->point_matrix[2], vals->point_matrix[3]); - trans->nonIdentity = 0; - - /* Try to round stuff. We want approximate zeros to be exact zeros, - and if the elements on the diagonal are approximately equal, we - want them equal. We do this to avoid breaking hinting. */ - if(DIFFER(vals->point_matrix[0], vals->point_matrix[3])) { - trans->nonIdentity = 1; - trans->matrix.xx = - (int)((vals->point_matrix[0]*(double)TWO_SIXTEENTH)/trans->scale); - trans->matrix.yy = - (int)((vals->point_matrix[3]*(double)TWO_SIXTEENTH)/trans->scale); - } else { - trans->matrix.xx = trans->matrix.yy = - ((vals->point_matrix[0] + vals->point_matrix[3])/2* - (double)TWO_SIXTEENTH)/trans->scale; - } - - if(DIFFER0(vals->point_matrix[1], trans->scale)) { - trans->matrix.yx = - (int)((vals->point_matrix[1]*(double)TWO_SIXTEENTH)/trans->scale); - trans->nonIdentity = 1; - } else - trans->matrix.yx = 0; - - if(DIFFER0(vals->point_matrix[2], trans->scale)) { - trans->matrix.xy = - (int)((vals->point_matrix[2]*(double)TWO_SIXTEENTH)/trans->scale); - trans->nonIdentity = 1; - } else - trans->matrix.xy=0; - return 0; -} - - -static int -is_fixed_width(FT_Face face) -{ - PS_FontInfoRec t1info_rec; - int ftrc; - - if(FT_IS_FIXED_WIDTH(face)) { - return 1; - } - - ftrc = FT_Get_PS_Font_Info(face, &t1info_rec); - if(ftrc == 0 && t1info_rec.is_fixed_pitch) { - return 1; - } - - return 0; -} - -static int -FreeTypeLoadFont(FTFontPtr font, FontInfoPtr info, FTFacePtr face, - char *FTFileName, FontScalablePtr vals, FontEntryPtr entry, - FontBitmapFormatPtr bmfmt, FT_Int32 load_flags, - struct TTCapInfo *tmp_ttcap, char *dynStrTTCapCodeRange, - int ttcap_spacing ) -{ - int xrc; - FTNormalisedTransformationRec trans; - int spacing, actual_spacing, zero_code; - long lastCode, firstCode; - TT_Postscript *post; - - ft_get_trans_from_vals(vals,&trans); - - /* Check for charcell in XLFD */ - spacing = FT_PROPORTIONAL; - if(entry->name.ndashes == 14) { - char *p; - int dashes = 0; - for(p = entry->name.name; - p <= entry->name.name + entry->name.length - 2; - p++) { - if(*p == '-') { - dashes++; - if(dashes == 11) { - if(p[1]=='c' && p[2]=='-') - spacing=FT_CHARCELL; - else if(p[1]=='m' && p[2]=='-') - spacing=FT_MONOSPACED; - break; - } - } - } - } - /* by TTCap */ - if( ttcap_spacing != 0 ) { - if( ttcap_spacing == 'c' ) spacing=FT_CHARCELL; - else if( ttcap_spacing == 'm' ) spacing=FT_MONOSPACED; - else spacing=FT_PROPORTIONAL; - } - - actual_spacing = spacing; - if( spacing == FT_PROPORTIONAL ) { - if( is_fixed_width(face->face) ) - actual_spacing = FT_MONOSPACED; - } - - if(entry->name.ndashes == 14) { - xrc = FTPickMapping(entry->name.name, entry->name.length, FTFileName, - face->face, &font->mapping); - if (xrc != Successful) - return xrc; - } else { - xrc = FTPickMapping(0, 0, FTFileName, - face->face, &font->mapping); - if (xrc != Successful) - return xrc; - } - - font->nranges = vals->nranges; - font->ranges = 0; - if(font->nranges) { - font->ranges = malloc(vals->nranges*sizeof(fsRange)); - if(font->ranges == NULL) - return AllocError; - memcpy((char*)font->ranges, (char*)vals->ranges, - vals->nranges*sizeof(fsRange)); - } - - zero_code=-1; - if(info) { - firstCode = 0; - lastCode = 0xFFFFL; - if(!font->mapping.mapping || - font->mapping.mapping->encoding->row_size == 0) { - /* linear indexing */ - lastCode=MIN(lastCode, - font->mapping.mapping ? - font->mapping.mapping->encoding->size-1 : - 0xFF); - if(font->mapping.mapping && font->mapping.mapping->encoding->first) - firstCode = font->mapping.mapping->encoding->first; - info->firstRow = firstCode/0x100; - info->lastRow = lastCode/0x100; - info->firstCol = - (info->firstRow || info->lastRow) ? 0 : (firstCode & 0xFF); - info->lastCol = info->lastRow ? 0xFF : (lastCode & 0xFF); - if ( firstCode == 0 ) zero_code=0; - } else { - /* matrix indexing */ - info->firstRow = font->mapping.mapping->encoding->first; - info->lastRow = MIN(font->mapping.mapping->encoding->size-1, - lastCode/0x100); - info->firstCol = font->mapping.mapping->encoding->first_col; - info->lastCol = MIN(font->mapping.mapping->encoding->row_size-1, - lastCode<0x100?lastCode:0xFF); - if( info->firstRow == 0 && info->firstCol == 0 ) zero_code=0; - } - - /* firstCode and lastCode are not valid in case of a matrix - encoding */ - - if( dynStrTTCapCodeRange ) { - restrict_code_range_by_str(0,&info->firstCol, &info->firstRow, - &info->lastCol, &info->lastRow, - dynStrTTCapCodeRange); - } - restrict_code_range(&info->firstCol, &info->firstRow, - &info->lastCol, &info->lastRow, - font->ranges, font->nranges); - } - font->info = info; - - /* zero code is frequently used. */ - if ( zero_code < 0 ) { - /* The fontenc should have the information of DefaultCh. - But we do not have such a information. - So we cannot but set 0. */ - font->zero_idx = 0; - } - else - font->zero_idx = FTRemap(face->face, - &font->mapping, zero_code); - - post = FT_Get_Sfnt_Table(face->face, ft_sfnt_post); - -#ifdef DEFAULT_VERY_LAZY - if( !( tmp_ttcap->flags & TTCAP_DISABLE_DEFAULT_VERY_LAZY ) ) - if( DEFAULT_VERY_LAZY <= 1 + info->lastRow - info->firstRow ) { - if( post ){ - tmp_ttcap->flags |= TTCAP_IS_VERY_LAZY; - } - } -#endif - /* We should always reset. */ - tmp_ttcap->flags &= ~TTCAP_DISABLE_DEFAULT_VERY_LAZY; - - if ( face->bitmap || actual_spacing == FT_CHARCELL ) - tmp_ttcap->flags &= ~TTCAP_IS_VERY_LAZY; - /* "vl=y" is available when TrueType or OpenType only */ - if ( !face->bitmap && !(FT_IS_SFNT( face->face )) ) - tmp_ttcap->flags &= ~TTCAP_IS_VERY_LAZY; - - if( post ) { - if( post->italicAngle != 0 ) - tmp_ttcap->vl_slant = -sin( (post->italicAngle/1024./5760.)*1.57079632679489661923 ); - /* fprintf(stderr,"angle=%g(%g)\n",tmp_ttcap->vl_slant,(post->italicAngle/1024./5760.)*90); */ - } - - xrc = FreeTypeOpenInstance(&font->instance, face, - FTFileName, &trans, actual_spacing, bmfmt, - tmp_ttcap, load_flags ); - return xrc; -} - -static void -adjust_min_max(xCharInfo *minc, xCharInfo *maxc, xCharInfo *tmp) -{ -#define MINMAX(field,ci) \ - if (minc->field > (ci)->field) \ - minc->field = (ci)->field; \ - if (maxc->field < (ci)->field) \ - maxc->field = (ci)->field; - - MINMAX(ascent, tmp); - MINMAX(descent, tmp); - MINMAX(leftSideBearing, tmp); - MINMAX(rightSideBearing, tmp); - MINMAX(characterWidth, tmp); - - if ((INT16)minc->attributes > (INT16)tmp->attributes) - minc->attributes = tmp->attributes; - if ((INT16)maxc->attributes < (INT16)tmp->attributes) - maxc->attributes = tmp->attributes; -#undef MINMAX -} - -static void -ft_compute_bounds(FTFontPtr font, FontInfoPtr pinfo, FontScalablePtr vals ) -{ - FTInstancePtr instance; - int row, col; - unsigned int c; - xCharInfo minchar, maxchar, *tmpchar = NULL; - int overlap, maxOverlap; - long swidth = 0; - long total_width = 0; - int num_cols, num_chars = 0; - int flags, skip_ok = 0; - int force_c_outside ; - - instance = font->instance; - force_c_outside = instance->ttcap.flags & TTCAP_FORCE_C_OUTSIDE; - - minchar.ascent = minchar.descent = - minchar.leftSideBearing = minchar.rightSideBearing = - minchar.characterWidth = minchar.attributes = 32767; - maxchar.ascent = maxchar.descent = - maxchar.leftSideBearing = maxchar.rightSideBearing = - maxchar.characterWidth = maxchar.attributes = -32767; - maxOverlap = -32767; - - /* Parse all glyphs */ - num_cols = 1 + pinfo->lastCol - pinfo->firstCol; - for (row = pinfo->firstRow; row <= pinfo->lastRow; row++) { - if ( skip_ok && tmpchar ) { - if ( !force_c_outside ) { - if ( instance->ttcap.forceConstantSpacingBegin < row<<8 - && row<<8 < (instance->ttcap.forceConstantSpacingEnd & 0x0ff00) ) { - if (tmpchar->characterWidth) { - num_chars += num_cols; - swidth += ABS(tmpchar->characterWidth)*num_cols; - total_width += tmpchar->characterWidth*num_cols; - continue; - } - } - else skip_ok=0; - } - else { /* for GB18030 proportional */ - if ( instance->ttcap.forceConstantSpacingBegin < row<<8 - || row<<8 < (instance->ttcap.forceConstantSpacingEnd & 0x0ff00) ) { - if (tmpchar->characterWidth) { - num_chars += num_cols; - swidth += ABS(tmpchar->characterWidth)*num_cols; - total_width += tmpchar->characterWidth*num_cols; - continue; - } - } - else skip_ok=0; - } - } - for (col = pinfo->firstCol; col <= pinfo->lastCol; col++) { - c = row<<8|col; - flags=0; - if ( !force_c_outside ) { - if ( c <= instance->ttcap.forceConstantSpacingEnd - && instance->ttcap.forceConstantSpacingBegin <= c ) - flags|=FT_FORCE_CONSTANT_SPACING; - } - else { /* for GB18030 proportional */ - if ( c <= instance->ttcap.forceConstantSpacingEnd - || instance->ttcap.forceConstantSpacingBegin <= c ) - flags|=FT_FORCE_CONSTANT_SPACING; - } -#if 0 - fprintf(stderr, "comp_bounds: %x ->", c); -#endif - if ( skip_ok == 0 || flags == 0 ){ - tmpchar=NULL; -#if 0 - fprintf(stderr, "%x\n", c); -#endif - if( FreeTypeFontGetGlyphMetrics(c, flags, &tmpchar, font) != Successful ) - continue; - } - if ( !tmpchar ) continue; - adjust_min_max(&minchar, &maxchar, tmpchar); - overlap = tmpchar->rightSideBearing - tmpchar->characterWidth; - if (maxOverlap < overlap) - maxOverlap = overlap; - - if (!tmpchar->characterWidth) - continue; - num_chars++; - swidth += ABS(tmpchar->characterWidth); - total_width += tmpchar->characterWidth; - - if ( flags & FT_FORCE_CONSTANT_SPACING ) skip_ok=1; - } - } - -#ifndef X_ACCEPTS_NO_SUCH_CHAR - /* Check code 0 */ - if( FreeTypeInstanceGetGlyphMetrics(font->zero_idx, 0, &tmpchar, font->instance) != Successful || tmpchar == NULL) - if( FreeTypeInstanceGetGlyphMetrics(font->zero_idx, FT_GET_DUMMY, &tmpchar, font->instance) != Successful ) - tmpchar = NULL; - if ( tmpchar ) { - adjust_min_max(&minchar, &maxchar, tmpchar); - overlap = tmpchar->rightSideBearing - tmpchar->characterWidth; - if (maxOverlap < overlap) - maxOverlap = overlap; - } -#endif - - /* AVERAGE_WIDTH ... 1/10 pixel unit */ - if (num_chars > 0) { - swidth = (swidth * 10.0 + num_chars / 2.0) / num_chars; - if (total_width < 0) - swidth = -swidth; - vals->width = swidth; - } else - vals->width = 0; - - /* - if (char_width.pixel) { - maxchar.characterWidth = char_width.pixel; - minchar.characterWidth = char_width.pixel; - } - */ - - pinfo->maxbounds = maxchar; - pinfo->minbounds = minchar; - pinfo->ink_maxbounds = maxchar; - pinfo->ink_minbounds = minchar; - pinfo->maxOverlap = maxOverlap; -} - -static int -compute_new_extents( FontScalablePtr vals, double scale, double lsb, double rsb, double desc, double asc, - int *lsb_result, int *rsb_result, int *desc_result, int *asc_result ) -{ -#define TRANSFORM_POINT(matrix, x, y, dest) \ - ((dest)[0] = (matrix)[0] * (x) + (matrix)[2] * (y), \ - (dest)[1] = (matrix)[1] * (x) + (matrix)[3] * (y)) - -#define CHECK_EXTENT(lsb, rsb, desc, asc, data) \ - ((lsb) > (data)[0] ? (lsb) = (data)[0] : 0 , \ - (rsb) < (data)[0] ? (rsb) = (data)[0] : 0, \ - (-desc) > (data)[1] ? (desc) = -(data)[1] : 0 , \ - (asc) < (data)[1] ? (asc) = (data)[1] : 0) - double newlsb, newrsb, newdesc, newasc; - double point[2]; - - /* Compute new extents for this glyph */ - TRANSFORM_POINT(vals->pixel_matrix, lsb, -desc, point); - newlsb = point[0]; - newrsb = newlsb; - newdesc = -point[1]; - newasc = -newdesc; - TRANSFORM_POINT(vals->pixel_matrix, lsb, asc, point); - CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); - TRANSFORM_POINT(vals->pixel_matrix, rsb, -desc, point); - CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); - TRANSFORM_POINT(vals->pixel_matrix, rsb, asc, point); - CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); - - /* ???: lsb = (int)floor(newlsb * scale); */ - *lsb_result = (int)floor(newlsb * scale + 0.5); - *rsb_result = (int)floor(newrsb * scale + 0.5); - *desc_result = (int)ceil(newdesc * scale - 0.5); - *asc_result = (int)floor(newasc * scale + 0.5); - - return 0; -#undef CHECK_EXTENT -#undef TRANSFORM_POINT -} - -static int -is_matrix_unit(FontScalablePtr vals) -{ - double base_size; - FT_Matrix m; - - base_size = hypot(vals->point_matrix[2], vals->point_matrix[3]); - - m.xx = vals->point_matrix[0] / base_size * 65536; - m.xy = vals->point_matrix[2] / base_size * 65536; - m.yx = vals->point_matrix[1] / base_size * 65536; - m.yy = vals->point_matrix[3] / base_size * 65536; - - return (m.xx == 65536) && (m.yx == 0) && - (m.xy == 0) && (m.yy == 65536); -} - -/* Do all the real work for OpenFont or FontInfo */ -/* xf->info is only accessed through info, and xf might be null */ - -static int -FreeTypeLoadXFont(char *fileName, - FontScalablePtr vals, FontPtr xf, FontInfoPtr info, - FontBitmapFormatPtr bmfmt, FontEntryPtr entry) -{ - FTFontPtr font = NULL; - FTFacePtr face = NULL; - FTInstancePtr instance; - FT_Size_Metrics *smetrics; - int xrc=Successful; - int charcell; - long rawWidth = 0, rawAverageWidth = 0; - int upm, minLsb, maxRsb, ascent, descent, width, averageWidth; - double scale, base_width, base_height; - Bool orig_is_matrix_unit, font_properties; - int face_number, ttcap_spacing; - struct TTCapInfo tmp_ttcap; - struct TTCapInfo *ins_ttcap; - FT_Int32 load_flags = FT_LOAD_DEFAULT; /* orig: FT_LOAD_RENDER | FT_LOAD_MONOCHROME */ - char *dynStrRealFileName = NULL; /* foo.ttc */ - char *dynStrFTFileName = NULL; /* :1:foo.ttc */ - char *dynStrTTCapCodeRange = NULL; - - font = calloc(1, sizeof(FTFontRec)); - if(font == NULL) { - xrc = AllocError; - goto quit; - } - - xrc = FreeTypeSetUpTTCap(fileName, vals, - &dynStrRealFileName, &dynStrFTFileName, - &tmp_ttcap, &face_number, - &load_flags, &ttcap_spacing, - &font_properties, &dynStrTTCapCodeRange); - if ( xrc != Successful ) { - goto quit; - } - - xrc = FreeTypeOpenFace(&face, dynStrFTFileName, dynStrRealFileName, face_number); - if(xrc != Successful) { - goto quit; - } - - if( is_matrix_unit(vals) ) - orig_is_matrix_unit = True; - else { - orig_is_matrix_unit = False; - /* Turn off EmbeddedBitmap when original matrix is not diagonal. */ - load_flags |= FT_LOAD_NO_BITMAP; - } - - if( face->bitmap ) load_flags &= ~FT_LOAD_NO_BITMAP; - - /* Slant control by TTCap */ - if(!face->bitmap) { - vals->pixel_matrix[2] += - vals->pixel_matrix[0] * tmp_ttcap.autoItalic; - vals->point_matrix[2] += - vals->point_matrix[0] * tmp_ttcap.autoItalic; - vals->pixel_matrix[3] += - vals->pixel_matrix[1] * tmp_ttcap.autoItalic; - vals->point_matrix[3] += - vals->point_matrix[1] * tmp_ttcap.autoItalic; - } - - base_width=hypot(vals->pixel_matrix[0], vals->pixel_matrix[1]); - base_height=hypot(vals->pixel_matrix[2], vals->pixel_matrix[3]); - if(MAX(base_width, base_height) < 1.0 ) { - xrc = BadFontName; - goto quit; - } - - xrc = FreeTypeLoadFont(font, info, face, dynStrFTFileName, vals, entry, bmfmt, - load_flags, &tmp_ttcap, dynStrTTCapCodeRange, - ttcap_spacing ); - if(xrc != Successful) { - goto quit; - } - - instance = font->instance; - smetrics = &instance->size->metrics; - ins_ttcap = &instance->ttcap; - - upm = face->face->units_per_EM; - if(upm == 0) { - /* Work around FreeType bug */ - upm = WORK_AROUND_UPM; - } - scale = 1.0 / upm; - - charcell = (instance->spacing == FT_CHARCELL); - - if( instance->charcellMetrics == NULL ) { - - /* New instance */ - - long force_c_rawWidth = 0; - int force_c_lsb,force_c_rsb,force_c_width; - double unit_x=0,unit_y=0,advance; - CharInfoPtr tmpglyph; - - /* - * CALCULATE HEADER'S METRICS - */ - - /* for OUTLINE fonts */ - if(!face->bitmap) { - int new_width; - double ratio,force_c_ratio; - double width_x=0,width_y=0; - double force_c_width_x, force_c_rsb_x, force_c_lsb_x; - double tmp_rsb,tmp_lsb,tmp_asc,tmp_des; - double max_advance_height; - tmp_asc = face->face->bbox.yMax; - tmp_des = -(face->face->bbox.yMin); - if ( tmp_asc < face->face->ascender ) tmp_asc = face->face->ascender; - if ( tmp_des < -(face->face->descender) ) tmp_des = -(face->face->descender); - tmp_lsb = face->face->bbox.xMin; - tmp_rsb = face->face->bbox.xMax; - if ( tmp_rsb < face->face->max_advance_width ) tmp_rsb = face->face->max_advance_width; - /* apply scaleBBoxWidth */ - /* we should not ...??? */ - tmp_lsb *= ins_ttcap->scaleBBoxWidth; - tmp_rsb *= ins_ttcap->scaleBBoxWidth; - /* transform and rescale */ - compute_new_extents( vals, scale, tmp_lsb, tmp_rsb, tmp_des, tmp_asc, - &minLsb, &maxRsb, &descent, &ascent ); - /* */ - /* Consider vertical layouts */ - if( 0 < face->face->max_advance_height ) - max_advance_height = face->face->max_advance_height; - else - max_advance_height = tmp_asc + tmp_des; - if( vals->pixel_matrix[1] == 0 ){ - unit_x = fabs(vals->pixel_matrix[0]); - unit_y = 0; - width_x = face->face->max_advance_width * ins_ttcap->scaleBBoxWidth * unit_x; - } - else if( vals->pixel_matrix[3] == 0 ){ - unit_y = fabs(vals->pixel_matrix[2]); - unit_x = 0; - width_x = max_advance_height * ins_ttcap->scaleBBoxHeight * unit_y; - } - else{ - unit_x = fabs(vals->pixel_matrix[0] - - vals->pixel_matrix[1]*vals->pixel_matrix[2]/vals->pixel_matrix[3]); - unit_y = fabs(vals->pixel_matrix[2] - - vals->pixel_matrix[3]*vals->pixel_matrix[0]/vals->pixel_matrix[1]); - width_x = face->face->max_advance_width * ins_ttcap->scaleBBoxWidth * unit_x; - width_y = max_advance_height * ins_ttcap->scaleBBoxHeight * unit_y; - if( width_y < width_x ){ - width_x = width_y; - unit_x = 0; - } - else{ - unit_y = 0; - } - } - /* calculate correction ratio */ - width = (int)floor( (advance = width_x * scale) + 0.5); - new_width = width; - if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH ) - new_width += ins_ttcap->doubleStrikeShift; - new_width += ins_ttcap->adjustBBoxWidthByPixel; - ratio = (double)new_width/width; - width = new_width; - /* force constant */ - if( unit_x != 0 ) { - force_c_width_x = face->face->max_advance_width - * ins_ttcap->force_c_scale_b_box_width * unit_x; - force_c_lsb_x = face->face->max_advance_width - * ins_ttcap->force_c_scale_lsb * unit_x; - force_c_rsb_x = face->face->max_advance_width - * ins_ttcap->force_c_scale_rsb * unit_x; - } - else { - force_c_width_x = max_advance_height - * ins_ttcap->force_c_scale_b_box_height * unit_y; - force_c_lsb_x = max_advance_height - * ins_ttcap->force_c_scale_lsb * unit_y; - force_c_rsb_x = max_advance_height - * ins_ttcap->force_c_scale_rsb * unit_y; - } - /* calculate correction ratio */ - force_c_width = (int)floor(force_c_width_x * scale + 0.5); - new_width = force_c_width; - if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH ) - force_c_width += ins_ttcap->doubleStrikeShift; - new_width += ins_ttcap->force_c_adjust_width_by_pixel; - force_c_ratio = (double)new_width/force_c_width; - force_c_width = new_width; - /* force_c_lsb, force_c_rsb */ - if( ins_ttcap->flags & TTCAP_FORCE_C_LSB_FLAG ) - force_c_lsb = (int)floor( force_c_lsb_x * scale + 0.5 ); - else - force_c_lsb = minLsb; - if( ins_ttcap->flags & TTCAP_FORCE_C_RSB_FLAG ) - force_c_rsb = (int)floor( force_c_rsb_x * scale + 0.5 ); - else - force_c_rsb = maxRsb; - /* calculate shift of BitmapAutoItalic - (when diagonal matrix only) */ - if( orig_is_matrix_unit == True ) { - if( ins_ttcap->autoItalic != 0 ) { - double ai; - int ai_lsb,ai_rsb,ai_total; - if( 0 < ins_ttcap->autoItalic ) ai=ins_ttcap->autoItalic; - else ai = -ins_ttcap->autoItalic; - ai_total = (int)( (ascent+descent) * ai + 0.5); - ai_rsb = (int)((double)ai_total * ascent / ( ascent + descent ) + 0.5 ); - ai_lsb = -(ai_total - ai_rsb); - if( 0 < ins_ttcap->autoItalic ) { - ins_ttcap->lsbShiftOfBitmapAutoItalic = ai_lsb; - ins_ttcap->rsbShiftOfBitmapAutoItalic = ai_rsb; - } - else { - ins_ttcap->lsbShiftOfBitmapAutoItalic = -ai_rsb; - ins_ttcap->rsbShiftOfBitmapAutoItalic = -ai_lsb; - } - } - } - /* integer adjustment by TTCap */ - if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE ) - maxRsb += ins_ttcap->doubleStrikeShift; - maxRsb += ins_ttcap->adjustRightSideBearingByPixel; - minLsb += ins_ttcap->adjustLeftSideBearingByPixel; - /* */ - if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE ) - force_c_rsb += ins_ttcap->doubleStrikeShift; - force_c_rsb += ins_ttcap->force_c_adjust_rsb_by_pixel; - force_c_lsb += ins_ttcap->force_c_adjust_lsb_by_pixel; - /* apply to rawWidth */ - averageWidth = (int)floor(10 * width_x * scale - * ratio + 0.5); - rawWidth = floor(width_x * scale - * ratio * 1000. / base_height + 0.5); - rawAverageWidth = floor(width_x * scale * ratio * 10. - * 1000. / base_height + 0.5); - force_c_rawWidth = floor(force_c_width_x * scale - * force_c_ratio * 1000. / base_height + 0.5); - /* */ - } - /* for BITMAP fonts [if(face->bitmap)] */ - else { - /* These values differ from actual when outline, - so we must use them ONLY FOR BITMAP. */ - width = (int)floor(smetrics->max_advance * ins_ttcap->scaleBBoxWidth / 64.0 + .5); - descent = -smetrics->descender / 64; - ascent = smetrics->ascender / 64; - /* force constant */ - force_c_width = (int)floor(smetrics->max_advance - * ins_ttcap->force_c_scale_b_box_width / 64.0 + .5); - /* Preserve average width for bitmap fonts */ - if(vals->width != 0) - averageWidth = (int)floor(vals->width * ins_ttcap->scaleBBoxWidth +.5); - else - averageWidth = (int)floor(10.0 * smetrics->max_advance - * ins_ttcap->scaleBBoxWidth / 64.0 + .5); - rawWidth = 0; - rawAverageWidth = 0; - force_c_rawWidth = 0; - /* We don't consider vertical layouts */ - advance = (int)floor(smetrics->max_advance / 64.0 +.5); - unit_x = vals->pixel_matrix[0]; - unit_y = 0; - /* We can use 'width' only when bitmap. - This should not be set when outline. */ - minLsb = 0; - maxRsb = width; - /* force constant */ - if( ins_ttcap->flags & TTCAP_FORCE_C_LSB_FLAG ) - force_c_lsb = (int)floor(smetrics->max_advance - * ins_ttcap->force_c_scale_lsb / 64.0 + .5); - else - force_c_lsb = minLsb; - if( ins_ttcap->flags & TTCAP_FORCE_C_RSB_FLAG ) - force_c_rsb = (int)floor(smetrics->max_advance - * ins_ttcap->force_c_scale_rsb / 64.0 + .5); - else - force_c_rsb = maxRsb; - /* calculate shift of BitmapAutoItalic */ - if( ins_ttcap->autoItalic != 0 ) { - double ai; - int ai_lsb,ai_rsb,ai_total; - if( 0 < ins_ttcap->autoItalic ) ai=ins_ttcap->autoItalic; - else ai = -ins_ttcap->autoItalic; - ai_total = (int)( (ascent+descent) * ai + 0.5); - ai_rsb = (int)((double)ai_total * ascent / ( ascent + descent ) + 0.5 ); - ai_lsb = -(ai_total - ai_rsb); - if( 0 < ins_ttcap->autoItalic ) { - ins_ttcap->lsbShiftOfBitmapAutoItalic = ai_lsb; - ins_ttcap->rsbShiftOfBitmapAutoItalic = ai_rsb; - } - else { - ins_ttcap->lsbShiftOfBitmapAutoItalic = -ai_rsb; - ins_ttcap->rsbShiftOfBitmapAutoItalic = -ai_lsb; - } - } - /* integer adjustment by TTCap */ - if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH ) - width += ins_ttcap->doubleStrikeShift; - if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE ) - maxRsb += ins_ttcap->doubleStrikeShift; - maxRsb += ins_ttcap->adjustRightSideBearingByPixel; - minLsb += ins_ttcap->adjustLeftSideBearingByPixel; - /* We have not carried out matrix calculation, so this is done. */ - maxRsb += ins_ttcap->rsbShiftOfBitmapAutoItalic; - minLsb += ins_ttcap->lsbShiftOfBitmapAutoItalic; - /* force constant */ - if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE ) - force_c_rsb += ins_ttcap->doubleStrikeShift; - force_c_rsb += ins_ttcap->force_c_adjust_rsb_by_pixel; - force_c_lsb += ins_ttcap->force_c_adjust_lsb_by_pixel; - force_c_rsb += ins_ttcap->rsbShiftOfBitmapAutoItalic; - force_c_lsb += ins_ttcap->lsbShiftOfBitmapAutoItalic; - } - - /* SET CALCULATED VALUES TO INSTANCE */ - - /* Set actual height and cosine */ - instance->pixel_size = base_height; - instance->advance = advance; - if ( unit_x != 0 ){ - instance->pixel_width_unit_x = unit_x/base_height; - instance->pixel_width_unit_y = 0; - } - else{ - instance->pixel_width_unit_x = 0; - instance->pixel_width_unit_y = unit_y/base_height; - } - - /* header's metrics */ - instance->charcellMetrics = malloc(sizeof(xCharInfo)); - if(instance->charcellMetrics == NULL) { - xrc = AllocError; - goto quit; - } - instance->charcellMetrics->ascent = ascent; - instance->charcellMetrics->descent = descent; - instance->charcellMetrics->attributes = rawWidth; - instance->charcellMetrics->rightSideBearing = maxRsb; - instance->charcellMetrics->leftSideBearing = minLsb; - instance->charcellMetrics->characterWidth = width; - instance->averageWidth = averageWidth; - instance->rawAverageWidth = rawAverageWidth; - - /* Check code 0 */ - if( FreeTypeInstanceGetGlyph(font->zero_idx, 0, &tmpglyph, font->instance) != Successful - || tmpglyph == NULL) - if( FreeTypeInstanceGetGlyph(font->zero_idx, FT_GET_DUMMY, &tmpglyph, font->instance) - != Successful ) - tmpglyph = NULL; - if ( !tmpglyph ) { - xrc = AllocError; - goto quit; - } - - /* FORCE CONSTANT METRICS */ - if( 0 <= ins_ttcap->forceConstantSpacingEnd ) { - xCharInfo *tmpchar = NULL; - int c = ins_ttcap->force_c_representative_metrics_char_code; - /* header's metrics */ - if( instance->forceConstantMetrics == NULL ){ - instance->forceConstantMetrics = malloc(sizeof(xCharInfo)); - if(instance->forceConstantMetrics == NULL) { - xrc = AllocError; - goto quit; - } - } - /* Get Representative Metrics */ - if ( 0 <= c ) { - if( FreeTypeFontGetGlyphMetrics(c, 0, &tmpchar, font) != Successful ) - tmpchar = NULL; - } - if ( tmpchar && 0 < tmpchar->characterWidth ) { - instance->forceConstantMetrics->leftSideBearing = tmpchar->leftSideBearing; - instance->forceConstantMetrics->rightSideBearing = tmpchar->rightSideBearing; - instance->forceConstantMetrics->characterWidth = tmpchar->characterWidth; - instance->forceConstantMetrics->ascent = tmpchar->ascent; - instance->forceConstantMetrics->descent = tmpchar->descent; - instance->forceConstantMetrics->attributes = tmpchar->attributes; - } - else { - instance->forceConstantMetrics->leftSideBearing = force_c_lsb; - instance->forceConstantMetrics->rightSideBearing = force_c_rsb; - instance->forceConstantMetrics->characterWidth = force_c_width; - instance->forceConstantMetrics->ascent = ascent; - instance->forceConstantMetrics->descent = descent; - instance->forceConstantMetrics->attributes = force_c_rawWidth; - } - /* Check code 0 */ - if( FreeTypeInstanceGetGlyph(font->zero_idx, FT_FORCE_CONSTANT_SPACING, - &tmpglyph, font->instance) != Successful - || tmpglyph == NULL) - if( FreeTypeInstanceGetGlyph(font->zero_idx, FT_FORCE_CONSTANT_SPACING | FT_GET_DUMMY, - &tmpglyph, font->instance) - != Successful ) - tmpglyph = NULL; - if ( !tmpglyph ) { - xrc = AllocError; - goto quit; - } - } - } - else{ - - /* - * CACHED VALUES - */ - - width = instance->charcellMetrics->characterWidth; - ascent = instance->charcellMetrics->ascent; - descent = instance->charcellMetrics->descent; - rawWidth = instance->charcellMetrics->attributes; - maxRsb = instance->charcellMetrics->rightSideBearing; - minLsb = instance->charcellMetrics->leftSideBearing; - averageWidth = instance->averageWidth; - rawAverageWidth = instance->rawAverageWidth; - - } - - /* - * SET maxbounds, minbounds ... - */ - - if( !charcell ) { /* NOT CHARCELL */ - if( info ){ - /* - Calculate all glyphs' metrics. - maxbounds.ascent and maxbounds.descent are quite important values - for XAA. If ascent/descent of each glyph exceeds - maxbounds.ascent/maxbounds.descent, XAA causes SERVER CRASH. - Therefore, THIS MUST BE DONE. - */ - ft_compute_bounds(font,info,vals); - } - } - else{ /* CHARCELL */ - - /* - * SET CALCULATED OR CACHED VARIABLES - */ - - vals->width = averageWidth; - - if( info ){ - - info->maxbounds.leftSideBearing = minLsb; - info->maxbounds.rightSideBearing = maxRsb; - info->maxbounds.characterWidth = width; - info->maxbounds.ascent = ascent; - info->maxbounds.descent = descent; - info->maxbounds.attributes = - (unsigned short)(short)rawWidth; - - info->minbounds = info->maxbounds; - } - } - - /* set info */ - - if( info ){ - /* - info->fontAscent = ascent; - info->fontDescent = descent; - */ - info->fontAscent = info->maxbounds.ascent; - info->fontDescent = info->maxbounds.descent; - /* Glyph metrics are accurate */ - info->inkMetrics=1; - - memcpy((char *)&info->ink_maxbounds, - (char *)&info->maxbounds, sizeof(xCharInfo)); - memcpy((char *)&info->ink_minbounds, - (char *)&info->minbounds, sizeof(xCharInfo)); - - /* XXX - hack */ - info->defaultCh=0; - - /* Set the pInfo flags */ - /* Properties set by FontComputeInfoAccelerators: - pInfo->noOverlap; - pInfo->terminalFont; - pInfo->constantMetrics; - pInfo->constantWidth; - pInfo->inkInside; - */ - /* from lib/font/util/fontaccel.c */ - FontComputeInfoAccelerators(info); - } - - if(xf) - xf->fontPrivate = (void*)font; - - if(info) { - xrc = FreeTypeAddProperties(font, vals, info, entry->name.name, - rawAverageWidth, font_properties); - if (xrc != Successful) { - goto quit; - } - } - - quit: - if ( dynStrTTCapCodeRange ) free(dynStrTTCapCodeRange); - if ( dynStrFTFileName ) free(dynStrFTFileName); - if ( dynStrRealFileName ) free(dynStrRealFileName); - if ( xrc != Successful ) { - if( font ){ - if( face && font->instance == NULL ) FreeTypeFreeFace(face); - FreeTypeFreeFont(font); - } - } - return xrc; -} - -/* Routines used by X11 to get info and glyphs from the font. */ - -static int -FreeTypeGetMetrics(FontPtr pFont, unsigned long count, unsigned char *chars, - FontEncoding charEncoding, unsigned long *metricCount, - xCharInfo **metrics) -{ - unsigned int code = 0; - int flags = 0; - FTFontPtr tf; - struct TTCapInfo *ttcap; - xCharInfo **mp, *m; - - /* MUMBLE("Get metrics for %ld characters\n", count);*/ - - tf = (FTFontPtr)pFont->fontPrivate; - ttcap = &tf->instance->ttcap; - mp = metrics; - - while (count-- > 0) { - switch (charEncoding) { - case Linear8Bit: - case TwoD8Bit: - code = *chars++; - break; - case Linear16Bit: - case TwoD16Bit: - code = (*chars++ << 8); - code |= *chars++; - /* */ - if ( !(ttcap->flags & TTCAP_FORCE_C_OUTSIDE) ) { - if ( (int)code <= ttcap->forceConstantSpacingEnd - && ttcap->forceConstantSpacingBegin <= (int)code ) - flags|=FT_FORCE_CONSTANT_SPACING; - else flags=0; - } - else { /* for GB18030 proportional */ - if ( (int)code <= ttcap->forceConstantSpacingEnd - || ttcap->forceConstantSpacingBegin <= (int)code ) - flags|=FT_FORCE_CONSTANT_SPACING; - else flags=0; - } - break; - } - - if(FreeTypeFontGetGlyphMetrics(code, flags, &m, tf) == Successful && m!=NULL) { - *mp++ = m; - } -#ifdef X_ACCEPTS_NO_SUCH_CHAR - else *mp++ = &noSuchChar.metrics; -#endif - } - - *metricCount = mp - metrics; - return Successful; -} - -static int -FreeTypeGetGlyphs(FontPtr pFont, unsigned long count, unsigned char *chars, - FontEncoding charEncoding, unsigned long *glyphCount, - CharInfoPtr *glyphs) -{ - unsigned int code = 0; - int flags = 0; - FTFontPtr tf; - CharInfoPtr *gp; - CharInfoPtr g; - struct TTCapInfo *ttcap; - - tf = (FTFontPtr)pFont->fontPrivate; - ttcap = &tf->instance->ttcap; - gp = glyphs; - - while (count-- > 0) { - switch (charEncoding) { - case Linear8Bit: case TwoD8Bit: - code = *chars++; - break; - case Linear16Bit: case TwoD16Bit: - code = *chars++ << 8; - code |= *chars++; - /* */ - if ( !(ttcap->flags & TTCAP_FORCE_C_OUTSIDE) ) { - if ( (int)code <= ttcap->forceConstantSpacingEnd - && ttcap->forceConstantSpacingBegin <= (int)code ) - flags|=FT_FORCE_CONSTANT_SPACING; - else flags=0; - } - else { /* for GB18030 proportional */ - if ( (int)code <= ttcap->forceConstantSpacingEnd - || ttcap->forceConstantSpacingBegin <= (int)code ) - flags|=FT_FORCE_CONSTANT_SPACING; - else flags=0; - } - break; - } - - if(FreeTypeFontGetGlyph(code, flags, &g, tf) == Successful && g!=NULL) { - *gp++ = g; - } -#ifdef X_ACCEPTS_NO_SUCH_CHAR - else { -#ifdef XAA_ACCEPTS_NULL_BITS - *gp++ = &noSuchChar; -#else - if ( tf->dummy_char.bits ) { - *gp++ = &tf->dummy_char; - } - else { - char *raster = NULL; - int wd_actual, ht_actual, wd, ht, bpr; - wd_actual = tf->info->maxbounds.rightSideBearing - tf->info->maxbounds.leftSideBearing; - ht_actual = tf->info->maxbounds.ascent + tf->info->maxbounds.descent; - if(wd_actual <= 0) wd = 1; - else wd=wd_actual; - if(ht_actual <= 0) ht = 1; - else ht=ht_actual; - bpr = (((wd + (tf->instance->bmfmt.glyph<<3) - 1) >> 3) & - -tf->instance->bmfmt.glyph); - raster = calloc(1, ht * bpr); - if(raster) { - tf->dummy_char.bits = raster; - *gp++ = &tf->dummy_char; - } - } -#endif - } -#endif - } - - *glyphCount = gp - glyphs; - return Successful; -} - -static int -FreeTypeSetUpFont(FontPathElementPtr fpe, FontPtr xf, FontInfoPtr info, - fsBitmapFormat format, fsBitmapFormatMask fmask, - FontBitmapFormatPtr bmfmt) -{ - int xrc; - int image; - - /* Get the default bitmap format information for this X installation. - Also update it for the client if running in the font server. */ - FontDefaultFormat(&bmfmt->bit, &bmfmt->byte, &bmfmt->glyph, &bmfmt->scan); - if ((xrc = CheckFSFormat(format, fmask, &bmfmt->bit, &bmfmt->byte, - &bmfmt->scan, &bmfmt->glyph, - &image)) != Successful) { - MUMBLE("Aborting after checking FS format: %d\n", xrc); - return xrc; - } - - if(xf) { - xf->refcnt = 0; - xf->bit = bmfmt->bit; - xf->byte = bmfmt->byte; - xf->glyph = bmfmt->glyph; - xf->scan = bmfmt->scan; - xf->format = format; - xf->get_glyphs = FreeTypeGetGlyphs; - xf->get_metrics = FreeTypeGetMetrics; - xf->unload_font = FreeTypeUnloadXFont; - xf->unload_glyphs = 0; - xf->fpe = fpe; - xf->svrPrivate = 0; - xf->fontPrivate = 0; /* we'll set it later */ - xf->fpePrivate = 0; - } - - info->defaultCh = 0; - info->noOverlap = 0; /* not updated */ - info->terminalFont = 0; /* not updated */ - info->constantMetrics = 0; /* we'll set it later */ - info->constantWidth = 0; /* we'll set it later */ - info->inkInside = 1; - info->inkMetrics = 1; - info->allExist=0; /* not updated */ - info->drawDirection = LeftToRight; /* we'll set it later */ - info->cachable = 1; /* we don't do licensing */ - info->anamorphic = 0; /* can hinting lead to anamorphic scaling? */ - info->maxOverlap = 0; /* we'll set it later. */ - info->pad = 0; /* ??? */ - return Successful; -} - -/* Functions exported by the backend */ - -static int -FreeTypeOpenScalable(FontPathElementPtr fpe, FontPtr *ppFont, int flags, - FontEntryPtr entry, char *fileName, FontScalablePtr vals, - fsBitmapFormat format, fsBitmapFormatMask fmask, - FontPtr non_cachable_font) -{ - int xrc; - FontPtr xf; - FontBitmapFormatRec bmfmt; - - MUMBLE("Open Scalable %s, XLFD=%s\n",fileName, entry->name.length ? entry->name.name : ""); - - xf = CreateFontRec(); - if (xf == NULL) - return AllocError; - - xrc = FreeTypeSetUpFont(fpe, xf, &xf->info, format, fmask, &bmfmt); - if(xrc != Successful) { - DestroyFontRec(xf); - return xrc; - } - xrc = FreeTypeLoadXFont(fileName, vals, xf, &xf->info, &bmfmt, entry); - if(xrc != Successful) { - MUMBLE("Error during load: %d\n",xrc); - DestroyFontRec(xf); - return xrc; - } - - *ppFont = xf; - - return xrc; -} - -/* Routine to get requested font info. */ - -static int -FreeTypeGetInfoScalable(FontPathElementPtr fpe, FontInfoPtr info, - FontEntryPtr entry, FontNamePtr fontName, - char *fileName, FontScalablePtr vals) -{ - int xrc; - FontBitmapFormatRec bmfmt; - - MUMBLE("Get info, XLFD=%s\n", entry->name.length ? entry->name.name : ""); - - xrc = FreeTypeSetUpFont(fpe, 0, info, 0, 0, &bmfmt); - if(xrc != Successful) { - return xrc; - } - - bmfmt.glyph <<= 3; - - xrc = FreeTypeLoadXFont(fileName, vals, 0, info, &bmfmt, entry); - if(xrc != Successful) { - MUMBLE("Error during load: %d\n", xrc); - return xrc; - } - - return Successful; -} - -/* Renderer registration. */ - -/* Set the capabilities of this renderer. */ -#define CAPABILITIES (CAP_CHARSUBSETTING | CAP_MATRIX) - -/* Set it up so file names with either upper or lower case can be - loaded. We don't support compressed fonts. */ -static FontRendererRec renderers[] = { - {".ttf", 4, 0, FreeTypeOpenScalable, 0, - FreeTypeGetInfoScalable, 0, CAPABILITIES}, - {".ttc", 4, 0, FreeTypeOpenScalable, 0, - FreeTypeGetInfoScalable, 0, CAPABILITIES}, - {".otf", 4, 0, FreeTypeOpenScalable, 0, - FreeTypeGetInfoScalable, 0, CAPABILITIES}, - {".otc", 4, 0, FreeTypeOpenScalable, 0, - FreeTypeGetInfoScalable, 0, CAPABILITIES}, - {".pfa", 4, 0, FreeTypeOpenScalable, 0, - FreeTypeGetInfoScalable, 0, CAPABILITIES}, - {".pfb", 4, 0, FreeTypeOpenScalable, 0, - FreeTypeGetInfoScalable, 0, CAPABILITIES}, -}; -static int num_renderers = sizeof(renderers) / sizeof(renderers[0]); - -static FontRendererRec alt_renderers[] = { - {".bdf", 4, 0, FreeTypeOpenScalable, 0, - FreeTypeGetInfoScalable, 0, CAPABILITIES}, - {".pcf", 4, 0, FreeTypeOpenScalable, 0, - FreeTypeGetInfoScalable, 0, CAPABILITIES}, -}; - -static int num_alt_renderers = -sizeof(alt_renderers) / sizeof(alt_renderers[0]); - - -void -FreeTypeRegisterFontFileFunctions(void) -{ - int i; - - for (i = 0; i < num_renderers; i++) - FontFileRegisterRenderer(&renderers[i]); - - for (i = 0; i < num_alt_renderers; i++) - FontFilePriorityRegisterRenderer(&alt_renderers[i], -10); -} +/*
+Copyright (c) 1997 by Mark Leisher
+Copyright (c) 1998-2003 by Juliusz Chroboczek
+Copyright (c) 1998 Go Watanabe, All rights reserved.
+Copyright (c) 1998 Kazushi (Jam) Marukawa, All rights reserved.
+Copyright (c) 1998 Takuya SHIOZAKI, All rights reserved.
+Copyright (c) 1998 X-TrueType Server Project, All rights reserved.
+Copyright (c) 2003-2004 After X-TT Project, All rights reserved.
+
+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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fontmisc.h>
+
+#include <string.h>
+#include <math.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#include <X11/fonts/fntfilst.h>
+#include <X11/fonts/fontutil.h>
+#include <X11/fonts/FSproto.h>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_SIZES_H
+#include FT_TRUETYPE_IDS_H
+#include FT_TRUETYPE_TABLES_H
+#include FT_TYPE1_TABLES_H
+#include FT_XFREE86_H
+#include FT_BBOX_H
+#include FT_TRUETYPE_TAGS_H
+/*
+ * If you want to use FT_Outline_Get_CBox instead of
+ * FT_Outline_Get_BBox, define here.
+ */
+/* #define USE_GET_CBOX */
+#ifdef USE_GET_CBOX
+#include FT_OUTLINE_H
+#endif
+
+#include <X11/fonts/fontenc.h>
+#include "ft.h"
+#include "ftfuncs.h"
+#include "xttcap.h"
+
+/* Work around FreeType bug */
+#define WORK_AROUND_UPM 2048
+
+#ifndef True
+#define True (-1)
+#endif /* True */
+#ifndef False
+#define False (0)
+#endif /* False */
+
+#define FLOOR64(x) ((x) & -64)
+#define CEIL64(x) (((x) + 64 - 1) & -64)
+
+/*
+ * If you want very lazy method(vl=y) AS DEFAULT when
+ * handling large charset, define here.
+ */
+/* #define DEFAULT_VERY_LAZY 1 */ /* Always */
+#define DEFAULT_VERY_LAZY 2 /* Multi-byte only */
+/* #define DEFAULT_VERY_LAZY 256 */ /* Unicode only */
+
+/* Does the X accept noSuchChar? */
+#define X_ACCEPTS_NO_SUCH_CHAR
+/* Does the XAA accept NULL noSuchChar.bits?(dangerous) */
+/* #define XAA_ACCEPTS_NULL_BITS */
+
+#ifdef X_ACCEPTS_NO_SUCH_CHAR
+static CharInfoRec noSuchChar = { /* metrics */{0,0,0,0,0,0},
+ /* bits */ NULL };
+#endif
+
+/* The propery names for all the XLFD properties. */
+
+static char *xlfd_props[] = {
+ "FOUNDRY",
+ "FAMILY_NAME",
+ "WEIGHT_NAME",
+ "SLANT",
+ "SETWIDTH_NAME",
+ "ADD_STYLE_NAME",
+ "PIXEL_SIZE",
+ "POINT_SIZE",
+ "RESOLUTION_X",
+ "RESOLUTION_Y",
+ "SPACING",
+ "AVERAGE_WIDTH",
+ "CHARSET_REGISTRY",
+ "CHARSET_ENCODING",
+};
+
+
+/* read 2-byte value from a SFNT table */
+static FT_UShort
+sfnt_get_ushort( FT_Face face,
+ FT_ULong table_tag,
+ FT_ULong table_offset )
+{
+ FT_Byte buff[2];
+ FT_ULong len = sizeof(buff);
+ FT_UShort result = 0;
+
+ if ( !FT_Load_Sfnt_Table( face, table_tag, table_offset, buff, &len ) );
+ result = (FT_UShort)( (buff[0] << 8) | buff[1] );
+
+ return result;
+}
+
+#define sfnt_get_short(f,t,o) ((FT_Short)sfnt_get_ushort((f),(t),(o)))
+
+#ifdef _MSC_VER
+#define hypot _hypot
+#endif
+
+static int ftypeInitP = 0; /* is the engine initialised? */
+FT_Library ftypeLibrary;
+
+static FTFacePtr faceTable[NUMFACEBUCKETS];
+
+static unsigned
+hash(char *string)
+{
+ int i;
+ unsigned u = 0;
+ for(i = 0; string[i] != '\0'; i++)
+ u = (u<<5) + (u >> (NUMFACEBUCKETS - 5)) + (unsigned char)string[i];
+ return u;
+}
+
+static int
+ifloor(int x, int y)
+{
+ if(x >= 0)
+ return x/y;
+ else
+ return x/y - 1;
+}
+
+static int
+iceil(int x, int y)
+{
+ return ifloor(x + y - 1, y);
+}
+
+static int
+FreeTypeOpenFace(FTFacePtr *facep, char *FTFileName, char *realFileName, int faceNumber)
+{
+ FT_Error ftrc;
+ int bucket;
+ FTFacePtr face, otherFace;
+
+ if (!ftypeInitP) {
+ ftrc = FT_Init_FreeType(&ftypeLibrary);
+ if (ftrc != 0) {
+ ErrorF("FreeType: error initializing ftypeEngine: %d\n", ftrc);
+ return AllocError;
+ }
+ ftypeInitP = 1;
+ }
+
+ /* Try to find a matching face in the hashtable */
+ bucket = hash(FTFileName)%NUMFACEBUCKETS;
+ otherFace = faceTable[bucket];
+ while(otherFace) {
+ if( strcmp(otherFace->filename, FTFileName) == 0 ) break;
+ otherFace = otherFace->next;
+ }
+ if(otherFace) {
+ MUMBLE("Returning cached face: %s\n", otherFace->filename);
+ *facep = otherFace;
+ return Successful;
+ }
+
+ /* No cached match; need to make a new one */
+ face = calloc(1, sizeof(FTFaceRec));
+ if (face == NULL) {
+ return AllocError;
+ }
+
+ face->filename = strdup(FTFileName);
+ if (face->filename == NULL) {
+ free(face);
+ return AllocError;
+ }
+
+ ftrc = FT_New_Face(ftypeLibrary, realFileName, faceNumber, &face->face);
+ if(ftrc != 0) {
+ ErrorF("FreeType: couldn't open face %s: %d\n", FTFileName, ftrc);
+ free(face->filename);
+ free(face);
+ return BadFontName;
+ }
+
+ face->bitmap = ((face->face->face_flags & FT_FACE_FLAG_SCALABLE) == 0);
+ if(!face->bitmap) {
+ TT_MaxProfile *maxp;
+ maxp = FT_Get_Sfnt_Table(face->face, ft_sfnt_maxp);
+ if(maxp && maxp->maxContours == 0)
+ face->bitmap = 1;
+ }
+
+ face->num_hmetrics = (FT_UInt) sfnt_get_ushort( face->face,
+ TTAG_hhea, 34 );
+
+ /* Insert face in hashtable and return it */
+ face->next = faceTable[bucket];
+ faceTable[bucket] = face;
+ *facep = face;
+ return Successful;
+}
+
+static void
+FreeTypeFreeFace(FTFacePtr face)
+{
+ int bucket;
+ FTFacePtr otherFace;
+
+ if(!face->instances) {
+ bucket = hash(face->filename) % NUMFACEBUCKETS;
+ if(faceTable[bucket] == face)
+ faceTable[bucket] = face->next;
+ else {
+ otherFace = faceTable[bucket];
+ while(otherFace) {
+ if(otherFace->next == face)
+ break;
+ otherFace = otherFace->next;
+ }
+ if(otherFace && otherFace->next)
+ otherFace->next = otherFace->next->next;
+ else
+ ErrorF("FreeType: freeing unknown face\n");
+ }
+ MUMBLE("Closing face: %s\n", face->filename);
+ FT_Done_Face(face->face);
+ free(face->filename);
+ free(face);
+ }
+}
+
+static int
+TransEqual(FTNormalisedTransformationPtr t1, FTNormalisedTransformationPtr t2)
+{
+ if(t1->scale != t2->scale)
+ return 0;
+ else if(t1->xres != t2->xres || t1->yres != t2->yres)
+ return 0;
+ else if(t1->nonIdentity != t2->nonIdentity)
+ return 0;
+ else if(t1->nonIdentity && t2->nonIdentity) {
+ return
+ t1->matrix.xx == t2->matrix.xx &&
+ t1->matrix.yx == t2->matrix.yx &&
+ t1->matrix.yy == t2->matrix.yy &&
+ t1->matrix.xy == t2->matrix.xy;
+ } else
+ return 1;
+}
+
+static int
+BitmapFormatEqual(FontBitmapFormatPtr f1, FontBitmapFormatPtr f2)
+{
+ return
+ f1->bit == f2->bit &&
+ f1->byte == f2->byte &&
+ f1->glyph == f2->glyph;
+}
+
+static int
+TTCapEqual(struct TTCapInfo *t1, struct TTCapInfo *t2)
+{
+ return
+ t1->autoItalic == t2->autoItalic &&
+ t1->scaleWidth == t2->scaleWidth &&
+ t1->scaleBBoxWidth == t2->scaleBBoxWidth &&
+ t1->scaleBBoxHeight == t2->scaleBBoxHeight &&
+ t1->doubleStrikeShift == t2->doubleStrikeShift &&
+ t1->adjustBBoxWidthByPixel == t2->adjustBBoxWidthByPixel &&
+ t1->adjustLeftSideBearingByPixel == t2->adjustLeftSideBearingByPixel &&
+ t1->adjustRightSideBearingByPixel == t2->adjustRightSideBearingByPixel &&
+ t1->flags == t2->flags &&
+ t1->scaleBitmap == t2->scaleBitmap &&
+ /*
+ If we use forceConstantSpacing,
+ we *MUST* allocate new instance.
+ */
+ t1->forceConstantSpacingEnd < 0 &&
+ t2->forceConstantSpacingEnd < 0;
+}
+
+static int
+FTInstanceMatch(FTInstancePtr instance,
+ char *FTFileName, FTNormalisedTransformationPtr trans,
+ int spacing, FontBitmapFormatPtr bmfmt,
+ struct TTCapInfo *tmp_ttcap, FT_Int32 load_flags)
+{
+ if(strcmp(instance->face->filename, FTFileName) != 0) {
+ return 0;
+ } else if(!TransEqual(&instance->transformation, trans)) {
+ return 0;
+ } else if( spacing != instance->spacing ) {
+ return 0;
+ } else if( load_flags != instance->load_flags ) {
+ return 0;
+ } else if(!BitmapFormatEqual(&instance->bmfmt, bmfmt)) {
+ return 0;
+ } else if(!TTCapEqual(&instance->ttcap, tmp_ttcap)) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+static int
+FreeTypeActivateInstance(FTInstancePtr instance)
+{
+ FT_Error ftrc;
+ if(instance->face->active_instance == instance)
+ return Successful;
+
+ ftrc = FT_Activate_Size(instance->size);
+ if(ftrc != 0) {
+ instance->face->active_instance = NULL;
+ ErrorF("FreeType: couldn't activate instance: %d\n", ftrc);
+ return FTtoXReturnCode(ftrc);
+ }
+ FT_Set_Transform(instance->face->face,
+ instance->transformation.nonIdentity ?
+ &instance->transformation.matrix : 0,
+ 0);
+
+ instance->face->active_instance = instance;
+ return Successful;
+}
+
+static int
+FTFindSize(FT_Face face, FTNormalisedTransformationPtr trans,
+ int *x_return, int *y_return)
+{
+ int tx, ty, x, y;
+ int i, j;
+ int d, dd;
+
+ if(trans->nonIdentity)
+ return BadFontName;
+
+ tx = (int)(trans->scale * trans->xres / 72.0 + 0.5);
+ ty = (int)(trans->scale * trans->yres / 72.0 + 0.5);
+
+ d = 100;
+ j = -1;
+ for(i = 0; i < face->num_fixed_sizes; i++) {
+ x = face->available_sizes[i].width;
+ y = face->available_sizes[i].height;
+ if(ABS(x - tx) <= 1 && ABS(y - ty) <= 1) {
+ dd = ABS(x - tx) * ABS(x - tx) + ABS(y - ty) * ABS(y - ty);
+ if(dd < d) {
+ j = i;
+ d = dd;
+ }
+ }
+ }
+ if(j < 0)
+ return BadFontName;
+
+ *x_return = face->available_sizes[j].width;
+ *y_return = face->available_sizes[j].height;
+ return Successful;
+}
+
+static int
+FreeTypeOpenInstance(FTInstancePtr *instance_return, FTFacePtr face,
+ char *FTFileName, FTNormalisedTransformationPtr trans,
+ int spacing, FontBitmapFormatPtr bmfmt,
+ struct TTCapInfo *tmp_ttcap, FT_Int32 load_flags)
+{
+ FT_Error ftrc;
+ int xrc;
+ FTInstancePtr instance, otherInstance;
+
+ /* Search for a matching instance */
+ for(otherInstance = face->instances;
+ otherInstance;
+ otherInstance = otherInstance->next) {
+ if(FTInstanceMatch(otherInstance, FTFileName, trans, spacing, bmfmt,
+ tmp_ttcap, load_flags)) break;
+ }
+ if(otherInstance) {
+ MUMBLE("Returning cached instance\n");
+ otherInstance->refcount++;
+ *instance_return = otherInstance;
+ return Successful;
+ }
+
+ /* None matching found */
+ instance = malloc(sizeof(FTInstanceRec));
+ if(instance == NULL) {
+ return AllocError;
+ }
+
+ instance->refcount = 1;
+ instance->face = face;
+
+ instance->load_flags = load_flags;
+ instance->spacing = spacing; /* Actual spacing */
+ instance->pixel_size =0;
+ instance->pixel_width_unit_x =0;
+ instance->pixel_width_unit_y =0;
+ instance->charcellMetrics = NULL;
+ instance->averageWidth = 0;
+ instance->rawAverageWidth = 0;
+ instance->forceConstantMetrics = NULL;
+
+ instance->transformation = *trans;
+ instance->bmfmt = *bmfmt;
+ instance->glyphs = NULL;
+ instance->available = NULL;
+
+ if( 0 <= tmp_ttcap->forceConstantSpacingEnd )
+ instance->nglyphs = 2 * instance->face->face->num_glyphs;
+ else
+ instance->nglyphs = instance->face->face->num_glyphs;
+
+ /* Store the TTCap info. */
+ memcpy((char*)&instance->ttcap, (char*)tmp_ttcap,
+ sizeof(struct TTCapInfo));
+
+ ftrc = FT_New_Size(instance->face->face, &instance->size);
+ if(ftrc != 0) {
+ ErrorF("FreeType: couldn't create size object: %d\n", ftrc);
+ free(instance);
+ return FTtoXReturnCode(ftrc);
+ }
+ FreeTypeActivateInstance(instance);
+ if(!face->bitmap) {
+ ftrc = FT_Set_Char_Size(instance->face->face,
+ (int)(trans->scale*(1<<6) + 0.5),
+ (int)(trans->scale*(1<<6) + 0.5),
+ trans->xres, trans->yres);
+ } else {
+ int xsize, ysize;
+ xrc = FTFindSize(face->face, trans, &xsize, &ysize);
+ if(xrc != Successful) {
+ free(instance);
+ return xrc;
+ }
+ ftrc = FT_Set_Pixel_Sizes(instance->face->face, xsize, ysize);
+ }
+ if(ftrc != 0) {
+ FT_Done_Size(instance->size);
+ free(instance);
+ return FTtoXReturnCode(ftrc);
+ }
+
+ if( FT_IS_SFNT( face->face ) ) {
+#if 1
+ FT_F26Dot6 tt_char_width, tt_char_height, tt_dim_x, tt_dim_y;
+ FT_UInt nn;
+
+ instance->strike_index=0xFFFFU;
+
+ tt_char_width = (FT_F26Dot6)(trans->scale*(1<<6) + 0.5);
+ tt_char_height = (FT_F26Dot6)(trans->scale*(1<<6) + 0.5);
+
+ tt_dim_x = FLOOR64( ( tt_char_width * trans->xres + 36 ) / 72 + 32 );
+ tt_dim_y = FLOOR64( ( tt_char_height * trans->yres + 36 ) / 72 + 32 );
+
+ if ( tt_dim_x && !tt_dim_y )
+ tt_dim_y = tt_dim_x;
+ else if ( !tt_dim_x && tt_dim_y )
+ tt_dim_x = tt_dim_y;
+
+ for ( nn = 0; nn < face->face->num_fixed_sizes; nn++ )
+ {
+ FT_Bitmap_Size* sz = &face->face->available_sizes[nn];
+
+ if ( tt_dim_x == FLOOR64(sz->x_ppem + 32) && tt_dim_y == FLOOR64(sz->y_ppem + 32) )
+ {
+ instance->strike_index = nn;
+ break;
+ }
+ }
+#else
+ /* See Set_Char_Sizes() in ttdriver.c */
+ FT_Error err;
+ TT_Face tt_face;
+ FT_Long tt_dim_x, tt_dim_y;
+ FT_UShort tt_x_ppem, tt_y_ppem;
+ FT_F26Dot6 tt_char_width, tt_char_height;
+ SFNT_Service sfnt;
+ tt_face=(TT_Face)face->face;
+ tt_char_width = (int)(trans->scale*(1<<6) + 0.5);
+ tt_char_height = (int)(trans->scale*(1<<6) + 0.5);
+ if ( ( tt_face->header.Flags & 8 ) != 0 ) {
+ tt_dim_x = ( ( tt_char_width * trans->xres + (36+32*72) ) / 72 ) & -64;
+ tt_dim_y = ( ( tt_char_height * trans->yres + (36+32*72) ) / 72 ) & -64;
+ }
+ else{
+ tt_dim_x = ( ( tt_char_width * trans->xres + 36 ) / 72 );
+ tt_dim_y = ( ( tt_char_height * trans->yres + 36 ) / 72 );
+ }
+ tt_x_ppem = (FT_UShort)( tt_dim_x >> 6 );
+ tt_y_ppem = (FT_UShort)( tt_dim_y >> 6 );
+ /* See Reset_SBit_Size() in ttobjs.c */
+ sfnt = (SFNT_Service)tt_face->sfnt;
+ err = sfnt->set_sbit_strike(tt_face,tt_x_ppem,tt_y_ppem,&instance->strike_index);
+ if ( err ) instance->strike_index=0xFFFFU;
+#endif
+ }
+
+ /* maintain a linked list of instances */
+ instance->next = instance->face->instances;
+ instance->face->instances = instance;
+
+ *instance_return = instance;
+ return Successful;
+}
+
+static void
+FreeTypeFreeInstance(FTInstancePtr instance)
+{
+ FTInstancePtr otherInstance;
+
+ if( instance == NULL ) return;
+
+ if(instance->face->active_instance == instance)
+ instance->face->active_instance = NULL;
+ instance->refcount--;
+ if(instance->refcount <= 0) {
+ int i,j;
+
+ if(instance->face->instances == instance)
+ instance->face->instances = instance->next;
+ else {
+ for(otherInstance = instance->face->instances;
+ otherInstance;
+ otherInstance = otherInstance->next)
+ if(otherInstance->next == instance) {
+ otherInstance->next = instance->next;
+ break;
+ }
+ }
+
+ FT_Done_Size(instance->size);
+ FreeTypeFreeFace(instance->face);
+
+ if(instance->charcellMetrics) {
+ free(instance->charcellMetrics);
+ }
+ if(instance->forceConstantMetrics) {
+ free(instance->forceConstantMetrics);
+ }
+ if(instance->glyphs) {
+ for(i = 0; i < iceil(instance->nglyphs, FONTSEGMENTSIZE); i++) {
+ if(instance->glyphs[i]) {
+ for(j = 0; j < FONTSEGMENTSIZE; j++) {
+ if(instance->available[i][j] ==
+ FT_AVAILABLE_RASTERISED)
+ free(instance->glyphs[i][j].bits);
+ }
+ free(instance->glyphs[i]);
+ }
+ }
+ free(instance->glyphs);
+ }
+ if(instance->available) {
+ for(i = 0; i < iceil(instance->nglyphs, FONTSEGMENTSIZE); i++) {
+ if(instance->available[i])
+ free(instance->available[i]);
+ }
+ free(instance->available);
+ }
+ free(instance);
+ }
+}
+
+static int
+FreeTypeInstanceFindGlyph(unsigned idx_in, int flags, FTInstancePtr instance,
+ CharInfoPtr **glyphs, int ***available,
+ int *found, int *segmentP, int *offsetP)
+{
+ int segment, offset;
+ unsigned idx = idx_in;
+
+ if( 0 <= instance->ttcap.forceConstantSpacingEnd ){
+ if( (flags & FT_FORCE_CONSTANT_SPACING) )
+ idx += instance->nglyphs / 2 ;
+ }
+
+ if(idx > instance->nglyphs) {
+ *found = 0;
+ return Successful;
+ }
+
+ if(*available == NULL) {
+ *available = calloc(iceil(instance->nglyphs, FONTSEGMENTSIZE),
+ sizeof(int *));
+ if(*available == NULL)
+ return AllocError;
+ }
+
+ segment = ifloor(idx, FONTSEGMENTSIZE);
+ offset = idx - segment * FONTSEGMENTSIZE;
+
+ if((*available)[segment] == NULL) {
+ (*available)[segment] = calloc(FONTSEGMENTSIZE, sizeof(int *));
+ if((*available)[segment] == NULL)
+ return AllocError;
+ }
+
+ if(*glyphs == NULL) {
+ *glyphs = calloc(iceil(instance->nglyphs, FONTSEGMENTSIZE),
+ sizeof(CharInfoPtr));
+ if(*glyphs == NULL)
+ return AllocError;
+ }
+
+ if((*glyphs)[segment] == NULL) {
+ (*glyphs)[segment] = malloc(sizeof(CharInfoRec) * FONTSEGMENTSIZE);
+ if((*glyphs)[segment] == NULL)
+ return AllocError;
+ }
+
+ *found = 1;
+ *segmentP = segment;
+ *offsetP = offset;
+ return Successful;
+}
+
+static int
+FreeTypeInstanceGetGlyph(unsigned idx, int flags, CharInfoPtr *g, FTInstancePtr instance)
+{
+ int found, segment, offset;
+ int xrc;
+ int ***available;
+ CharInfoPtr **glyphs;
+
+ available = &instance->available;
+ glyphs = &instance->glyphs;
+
+ xrc = FreeTypeInstanceFindGlyph(idx, flags, instance, glyphs, available,
+ &found, &segment, &offset);
+ if(xrc != Successful)
+ return xrc;
+
+ if(!found || (*available)[segment][offset] == FT_AVAILABLE_NO) {
+ *g = NULL;
+ return Successful;
+ }
+
+ if((*available)[segment][offset] == FT_AVAILABLE_RASTERISED) {
+ *g = &(*glyphs)[segment][offset];
+ return Successful;
+ }
+
+ flags |= FT_GET_GLYPH_BOTH;
+
+ xrc = FreeTypeRasteriseGlyph(idx, flags,
+ &(*glyphs)[segment][offset], instance,
+ (*available)[segment][offset] >= FT_AVAILABLE_METRICS);
+ if(xrc != Successful && (*available)[segment][offset] >= FT_AVAILABLE_METRICS) {
+ ErrorF("Warning: FreeTypeRasteriseGlyph() returns an error,\n");
+ ErrorF("\tso the backend tries to set a white space.\n");
+ xrc = FreeTypeRasteriseGlyph(idx, flags | FT_GET_DUMMY,
+ &(*glyphs)[segment][offset], instance,
+ (*available)[segment][offset] >= FT_AVAILABLE_METRICS);
+ }
+ if(xrc == Successful) {
+ (*available)[segment][offset] = FT_AVAILABLE_RASTERISED;
+ /* return the glyph */
+ *g = &(*glyphs)[segment][offset];
+ }
+ return xrc;
+}
+
+static int
+FreeTypeInstanceGetGlyphMetrics(unsigned idx, int flags,
+ xCharInfo **metrics, FTInstancePtr instance )
+{
+ int xrc;
+ int found, segment, offset;
+
+ /* Char cell */
+ if(instance->spacing == FT_CHARCELL) {
+ *metrics = instance->charcellMetrics;
+ return Successful;
+ }
+ /* Force constant metrics */
+ if( flags & FT_FORCE_CONSTANT_SPACING) {
+ *metrics = instance->forceConstantMetrics;
+ return Successful;
+ }
+
+ /* Not char cell */
+
+ xrc = FreeTypeInstanceFindGlyph(idx, flags, instance,
+ &instance->glyphs, &instance->available,
+ &found, &segment, &offset);
+ if(xrc != Successful)
+ return xrc;
+ if(!found) {
+ *metrics = NULL;
+ return Successful;
+ }
+ if( instance->available[segment][offset] == FT_AVAILABLE_NO ) {
+ *metrics = NULL;
+ return Successful;
+ }
+
+ if( instance->available[segment][offset] >= FT_AVAILABLE_METRICS ) {
+ *metrics = &instance->glyphs[segment][offset].metrics;
+ return Successful;
+ }
+
+ flags |= FT_GET_GLYPH_METRICS_ONLY;
+
+ xrc = FreeTypeRasteriseGlyph(idx, flags,
+ &instance->glyphs[segment][offset],
+ instance, 0);
+ if(xrc == Successful) {
+ instance->available[segment][offset] = FT_AVAILABLE_METRICS;
+ *metrics = &instance->glyphs[segment][offset].metrics;
+ }
+ return xrc;
+}
+
+/*
+ * Pseudo enbolding similar as Microsoft Windows.
+ * It is useful but poor.
+ */
+static void
+ft_make_up_bold_bitmap( char *raster, int bpr, int ht, int ds_mode)
+{
+ int x, y;
+ unsigned char *p = (unsigned char *)raster;
+ if ( ds_mode & TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT ) {
+ for (y=0; y<ht; y++) {
+ unsigned char rev_pat=0;
+ unsigned char lsb = 0;
+ for (x=0; x<bpr; x++) {
+ unsigned char tmp = *p<<7;
+ if ( (rev_pat & 0x01) && (*p & 0x80) ) p[-1] &= 0xfe;
+ rev_pat = ~(*p);
+ *p |= (*p>>1) | lsb;
+ *p &= ~(rev_pat & (*p << 1));
+ lsb = tmp;
+ p++;
+ }
+ }
+ }
+ else {
+ for (y=0; y<ht; y++) {
+ unsigned char lsb = 0;
+ for (x=0; x<bpr; x++) {
+ unsigned char tmp = *p<<7;
+ *p |= (*p>>1) | lsb;
+ lsb = tmp;
+ p++;
+ }
+ }
+ }
+}
+
+static void
+ft_make_up_italic_bitmap( char *raster, int bpr, int ht, int shift,
+ int h_total, int h_offset, double a_italic)
+{
+ int x, y;
+ unsigned char *p = (unsigned char *)raster;
+ if ( a_italic < 0 ) shift = -shift;
+ for (y=0; y<ht; y++) {
+ unsigned char *tmp_p = p + y*bpr;
+ int tmp_shift = shift * (h_total -1 -(y+h_offset)) / h_total;
+ int tmp_byte_shift;
+ if ( 0 <= tmp_shift ) {
+ tmp_byte_shift = tmp_shift/8;
+ tmp_shift %= 8;
+ if ( tmp_shift ) {
+ for (x=bpr-1;0<=x;x--) {
+ if ( x != bpr-1 )
+ tmp_p[x+1] |= tmp_p[x]<<(8-tmp_shift);
+ tmp_p[x]>>=tmp_shift;
+ }
+ }
+ if ( tmp_byte_shift ) {
+ for (x=bpr-1;0<x;x--) {
+ tmp_p[x] = tmp_p[x-1];
+ }
+ tmp_p[x]=0;
+ }
+ }
+ else {
+ tmp_shift = -tmp_shift;
+ tmp_byte_shift = tmp_shift/8;
+ tmp_shift %= 8;
+ if ( tmp_shift ) {
+ for (x=0;x<bpr;x++) {
+ if ( x != 0 )
+ tmp_p[x-1] |= tmp_p[x]>>(8-tmp_shift);
+ tmp_p[x]<<=tmp_shift;
+ }
+ }
+ if ( tmp_byte_shift ) {
+ for (x=0;x<bpr-1;x++) {
+ tmp_p[x] = tmp_p[x+1];
+ }
+ tmp_p[x]=0;
+ }
+ }
+ }
+}
+
+/*
+ * The very lazy method,
+ * parse the htmx field in TrueType font.
+ */
+
+static void
+tt_get_metrics( FT_Face face,
+ FT_UInt idx,
+ FT_UInt num_hmetrics,
+ FT_Short* bearing,
+ FT_UShort* advance )
+{
+ /* read the metrics directly from the horizontal header, we
+ * parse the SFNT table directly through the standard FreeType API.
+ * this works with any version of the library and doesn't need to
+ * peek at its internals. Maybe a bit less
+ */
+ FT_UInt count = num_hmetrics;
+ FT_ULong length = 0;
+ FT_ULong offset = 0;
+ FT_Error error;
+
+ error = FT_Load_Sfnt_Table( face, TTAG_hmtx, 0, NULL, &length );
+
+ if ( count == 0 || error )
+ {
+ *advance = 0;
+ *bearing = 0;
+ }
+ else if ( idx < count )
+ {
+ offset = idx * 4L;
+ if ( offset + 4 > length )
+ {
+ *advance = 0;
+ *bearing = 0;
+ }
+ else
+ {
+ *advance = sfnt_get_ushort( face, TTAG_hmtx, offset );
+ *bearing = sfnt_get_short ( face, TTAG_hmtx, offset+2 );
+ }
+ }
+ else
+ {
+ offset = 4L * (count - 1);
+ if ( offset + 4 > length )
+ {
+ *advance = 0;
+ *bearing = 0;
+ }
+ else
+ {
+ *advance = sfnt_get_ushort ( face, TTAG_hmtx, offset );
+ offset += 4 + 2 * ( idx - count );
+ if ( offset + 2 > length)
+ *bearing = 0;
+ else
+ *bearing = sfnt_get_short ( face, TTAG_hmtx, offset );
+ }
+ }
+}
+
+static int
+ft_get_very_lazy_bbox( FT_UInt index,
+ FT_Face face,
+ FT_Size size,
+ FT_UInt num_hmetrics,
+ double slant,
+ FT_Matrix *matrix,
+ FT_BBox *bbox,
+ FT_Long *horiAdvance,
+ FT_Long *vertAdvance)
+{
+ if ( FT_IS_SFNT( face ) ) {
+ FT_Size_Metrics *smetrics = &size->metrics;
+ FT_Short leftBearing = 0;
+ FT_UShort advance = 0;
+ FT_Vector p0, p1, p2, p3;
+
+ /* horizontal */
+ tt_get_metrics( face, index, num_hmetrics,
+ &leftBearing, &advance );
+
+#if 0
+ fprintf(stderr,"x_scale=%f y_scale=%f\n",
+ (double)smetrics->x_scale,(double)smetrics->y_scale);
+#endif
+ bbox->xMax = *horiAdvance =
+ FT_MulFix( advance, smetrics->x_scale );
+ bbox->xMin =
+ FT_MulFix( leftBearing, smetrics->x_scale );
+ /* vertical */
+ bbox->yMin = FT_MulFix( face->bbox.yMin,
+ smetrics->y_scale );
+ bbox->yMax = FT_MulFix( face->bbox.yMax,
+ smetrics->y_scale );
+ /* slant */
+ if( 0 < slant ) {
+ bbox->xMax += slant * bbox->yMax;
+ bbox->xMin += slant * bbox->yMin;
+ }
+ else if( slant < 0 ) {
+ bbox->xMax += slant * bbox->yMin;
+ bbox->xMin += slant * bbox->yMax;
+ }
+
+ *vertAdvance = -1; /* We don't support */
+
+ p0.x = p2.x = bbox->xMin;
+ p1.x = p3.x = bbox->xMax;
+ p0.y = p1.y = bbox->yMin;
+ p2.y = p3.y = bbox->yMax;
+
+ FT_Vector_Transform(&p0, matrix);
+ FT_Vector_Transform(&p1, matrix);
+ FT_Vector_Transform(&p2, matrix);
+ FT_Vector_Transform(&p3, matrix);
+
+#if 0
+ fprintf(stderr,
+ "->(%.1f %.1f) (%.1f %.1f)"
+ " (%.1f %.1f) (%.1f %.1f)\n",
+ p0.x / 64.0, p0.y / 64.0,
+ p1.x / 64.0, p1.y / 64.0,
+ p2.x / 64.0, p2.y / 64.0,
+ p3.x / 64.0, p3.y / 64.0);
+#endif
+ bbox->xMin = MIN(p0.x, MIN(p1.x, MIN(p2.x, p3.x)));
+ bbox->xMax = MAX(p0.x, MAX(p1.x, MAX(p2.x, p3.x)));
+ bbox->yMin = MIN(p0.y, MIN(p1.y, MIN(p2.y, p3.y)));
+ bbox->yMax = MAX(p0.y, MAX(p1.y, MAX(p2.y, p3.y)));
+ return 0; /* Successful */
+ }
+ return -1;
+}
+
+static FT_Error
+FT_Do_SBit_Metrics( FT_Face ft_face, FT_Size ft_size, FT_ULong strike_index,
+ FT_UShort glyph_index, FT_Glyph_Metrics *metrics_return,
+ int *sbitchk_incomplete_but_exist )
+{
+#if 1
+ if ( strike_index != 0xFFFFU && ft_face->available_sizes != NULL )
+ {
+ FT_Error error;
+ FT_Bitmap_Size* sz = &ft_face->available_sizes[strike_index];
+
+ error = FT_Set_Pixel_Sizes( ft_face, sz->x_ppem/64, sz->y_ppem/64 );
+ if ( !error )
+ {
+ error = FT_Load_Glyph( ft_face, glyph_index, FT_LOAD_SBITS_ONLY );
+ if ( !error )
+ {
+ if ( metrics_return != NULL )
+ *metrics_return = ft_face->glyph->metrics;
+
+ return 0;
+ }
+ }
+ }
+ return -1;
+#elif (FREETYPE_VERSION >= 2001008)
+ SFNT_Service sfnt;
+ TT_Face face;
+ FT_Error error;
+ FT_Stream stream;
+ TT_SBit_Strike strike;
+ TT_SBit_Range range;
+ TT_SBit_MetricsRec elem_metrics;
+ FT_ULong ebdt_pos;
+ FT_ULong glyph_offset;
+ ;
+
+ if ( ! FT_IS_SFNT( ft_face ) )
+ {
+ error=-1;
+ goto Exit;
+ }
+
+ face = (TT_Face)ft_face;
+ sfnt = (SFNT_Service)face->sfnt;
+
+ if (strike_index != 0xFFFFU && sfnt && sfnt->find_sbit_image &&
+ sfnt->load_sbits) {
+ /* Check whether there is a glyph sbit for the current index */
+ error = sfnt->find_sbit_image( face, glyph_index, strike_index,
+ &range, &strike, &glyph_offset );
+ }
+ else error=-1;
+ if ( error ) goto Exit;
+
+ if ( metrics_return == NULL ) goto Exit;
+
+ stream = face->root.stream;
+
+ /* now, find the location of the `EBDT' table in */
+ /* the font file */
+ error = face->goto_table( face, TTAG_EBDT, stream, 0 );
+ if ( error )
+ error = face->goto_table( face, TTAG_bdat, stream, 0 );
+ if (error)
+ goto Exit;
+
+ ebdt_pos = FT_STREAM_POS();
+
+ /* place stream at beginning of glyph data and read metrics */
+ if ( FT_STREAM_SEEK( ebdt_pos + glyph_offset ) )
+ goto Exit;
+
+ error = sfnt->load_sbit_metrics( stream, range, &elem_metrics );
+ if ( error )
+ goto Exit;
+
+ metrics_return->width = (FT_Pos)elem_metrics.width << 6;
+ metrics_return->height = (FT_Pos)elem_metrics.height << 6;
+
+ metrics_return->horiBearingX = (FT_Pos)elem_metrics.horiBearingX << 6;
+ metrics_return->horiBearingY = (FT_Pos)elem_metrics.horiBearingY << 6;
+ metrics_return->horiAdvance = (FT_Pos)elem_metrics.horiAdvance << 6;
+
+ metrics_return->vertBearingX = (FT_Pos)elem_metrics.vertBearingX << 6;
+ metrics_return->vertBearingY = (FT_Pos)elem_metrics.vertBearingY << 6;
+ metrics_return->vertAdvance = (FT_Pos)elem_metrics.vertAdvance << 6;
+
+ Exit:
+ return error;
+#else /* if (FREETYPE_VERSION < 2001008) */
+ TT_Face face;
+ SFNT_Service sfnt;
+ if ( ! FT_IS_SFNT( ft_face ) ) return -1;
+ face = (TT_Face)ft_face;
+ sfnt = (SFNT_Service)face->sfnt;
+ if ( strike_index != 0xFFFFU && sfnt->load_sbits ) {
+ if ( sbitchk_incomplete_but_exist ) *sbitchk_incomplete_but_exist=1;
+ }
+ return -1;
+#endif
+}
+
+int
+FreeTypeRasteriseGlyph(unsigned idx, int flags, CharInfoPtr tgp,
+ FTInstancePtr instance, int hasMetrics)
+{
+ FTFacePtr face;
+ FT_BBox bbox;
+ FT_Long outline_hori_advance, outline_vert_advance;
+ FT_Glyph_Metrics sbit_metrics;
+ FT_Glyph_Metrics *bitmap_metrics=NULL, *metrics = NULL;
+ char *raster;
+ int wd, ht, bpr; /* width, height, bytes per row */
+ int wd_actual, ht_actual;
+ int ftrc, is_outline, correct, b_shift=0;
+ int dx, dy;
+ int leftSideBearing, rightSideBearing, characterWidth, rawCharacterWidth,
+ ascent, descent;
+ int sbitchk_incomplete_but_exist;
+ double bbox_center_raw;
+
+ face = instance->face;
+
+ FreeTypeActivateInstance(instance);
+
+ if(!tgp) return AllocError;
+
+ /*
+ * PREPARE METRICS
+ */
+
+ if(!hasMetrics) {
+ if( instance->spacing == FT_CHARCELL || flags & FT_GET_DUMMY ){
+ memcpy((char*)&tgp->metrics,
+ (char*)instance->charcellMetrics,
+ sizeof(xCharInfo));
+ }
+ else if( flags & FT_FORCE_CONSTANT_SPACING ) {
+ memcpy((char*)&tgp->metrics,
+ (char*)instance->forceConstantMetrics,
+ sizeof(xCharInfo));
+ }
+ /* mono or prop. */
+ else{
+ int new_width;
+ double ratio;
+
+ sbitchk_incomplete_but_exist=0;
+ if( ! (instance->load_flags & FT_LOAD_NO_BITMAP) ) {
+ if( FT_Do_SBit_Metrics(face->face,instance->size,instance->strike_index,
+ idx,&sbit_metrics,&sbitchk_incomplete_but_exist)==0 ) {
+ bitmap_metrics = &sbit_metrics;
+ }
+ }
+ if( bitmap_metrics == NULL ) {
+ if ( sbitchk_incomplete_but_exist==0 && (instance->ttcap.flags & TTCAP_IS_VERY_LAZY) ) {
+ if( ft_get_very_lazy_bbox( idx, face->face, instance->size,
+ face->num_hmetrics,
+ instance->ttcap.vl_slant,
+ &instance->transformation.matrix,
+ &bbox, &outline_hori_advance,
+ &outline_vert_advance ) == 0 ) {
+ goto bbox_ok; /* skip exact calculation */
+ }
+ }
+ ftrc = FT_Load_Glyph(instance->face->face, idx,
+ instance->load_flags);
+ if(ftrc != 0) return FTtoXReturnCode(ftrc);
+ metrics = &face->face->glyph->metrics;
+ if( face->face->glyph->format == FT_GLYPH_FORMAT_BITMAP ) {
+ bitmap_metrics = metrics;
+ }
+ }
+
+ if( bitmap_metrics ) {
+ FT_Pos factor;
+
+ leftSideBearing = bitmap_metrics->horiBearingX / 64;
+ rightSideBearing = (bitmap_metrics->width + bitmap_metrics->horiBearingX) / 64;
+ bbox_center_raw = (2.0 * bitmap_metrics->horiBearingX + bitmap_metrics->width)/2.0/64.0;
+ characterWidth = (int)floor(bitmap_metrics->horiAdvance
+ * instance->ttcap.scaleBBoxWidth / 64.0 + .5);
+ ascent = bitmap_metrics->horiBearingY / 64;
+ descent = (bitmap_metrics->height - bitmap_metrics->horiBearingY) / 64 ;
+ /* */
+ new_width = characterWidth;
+ if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH )
+ new_width += instance->ttcap.doubleStrikeShift;
+ new_width += instance->ttcap.adjustBBoxWidthByPixel;
+ ratio = (double)new_width/characterWidth;
+ characterWidth = new_width;
+ /* adjustment by pixel unit */
+ if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE )
+ rightSideBearing += instance->ttcap.doubleStrikeShift;
+ rightSideBearing += instance->ttcap.adjustRightSideBearingByPixel;
+ leftSideBearing += instance->ttcap.adjustLeftSideBearingByPixel;
+ rightSideBearing += instance->ttcap.rsbShiftOfBitmapAutoItalic;
+ leftSideBearing += instance->ttcap.lsbShiftOfBitmapAutoItalic;
+ /* */
+ factor = bitmap_metrics->horiAdvance;
+ rawCharacterWidth = (unsigned short)(short)(floor(1000 * factor
+ * instance->ttcap.scaleBBoxWidth * ratio / 64.
+ / instance->pixel_size));
+ }
+ else {
+ /* Outline */
+#ifdef USE_GET_CBOX
+ /* Very fast?? */
+ FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox);
+ ftrc=0; /* FT_Outline_Get_CBox returns nothing. */
+#else
+ /* Calculate exact metrics */
+ ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox);
+#endif
+ if( ftrc != 0 ) return FTtoXReturnCode(ftrc);
+ outline_hori_advance = metrics->horiAdvance;
+ outline_vert_advance = metrics->vertAdvance;
+ bbox_ok:
+ descent = CEIL64(-bbox.yMin - 32) / 64;
+ leftSideBearing = FLOOR64(bbox.xMin + 32) / 64;
+ ascent = FLOOR64(bbox.yMax + 32) / 64;
+ rightSideBearing = FLOOR64(bbox.xMax + 32) / 64;
+ bbox_center_raw = (double)(bbox.xMax + bbox.xMin)/2.0/64.;
+ if ( instance->pixel_width_unit_x != 0 )
+ characterWidth =
+ (int)floor( outline_hori_advance
+ * instance->ttcap.scaleBBoxWidth
+ * instance->pixel_width_unit_x / 64. + .5);
+ else {
+ characterWidth =
+ (int)floor( outline_vert_advance
+ * instance->ttcap.scaleBBoxHeight
+ * instance->pixel_width_unit_y / 64. + .5);
+ if(characterWidth <= 0)
+ characterWidth = instance->charcellMetrics->characterWidth;
+ }
+ /* */
+ new_width = characterWidth;
+ if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH )
+ new_width += instance->ttcap.doubleStrikeShift;
+ new_width += instance->ttcap.adjustBBoxWidthByPixel;
+ ratio = (double)new_width/characterWidth;
+ characterWidth = new_width;
+ if ( instance->pixel_width_unit_x != 0 )
+ rawCharacterWidth =
+ (unsigned short)(short)(floor(1000 * outline_hori_advance
+ * instance->ttcap.scaleBBoxWidth * ratio
+ * instance->pixel_width_unit_x / 64.));
+ else {
+ rawCharacterWidth =
+ (unsigned short)(short)(floor(1000 * outline_vert_advance
+ * instance->ttcap.scaleBBoxHeight * ratio
+ * instance->pixel_width_unit_y / 64.));
+ if(rawCharacterWidth <= 0)
+ rawCharacterWidth = instance->charcellMetrics->attributes;
+ }
+ /* adjustment by pixel unit */
+ if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE )
+ rightSideBearing += instance->ttcap.doubleStrikeShift;
+ rightSideBearing += instance->ttcap.adjustRightSideBearingByPixel;
+ leftSideBearing += instance->ttcap.adjustLeftSideBearingByPixel;
+ }
+
+ /* Set the glyph metrics. */
+ tgp->metrics.attributes = (unsigned short)((short)rawCharacterWidth);
+ tgp->metrics.leftSideBearing = leftSideBearing;
+ tgp->metrics.rightSideBearing = rightSideBearing;
+ tgp->metrics.characterWidth = characterWidth;
+ tgp->metrics.ascent = ascent;
+ tgp->metrics.descent = descent;
+ /* Update the width to match the width of the font */
+ if( instance->spacing != FT_PROPORTIONAL )
+ tgp->metrics.characterWidth = instance->charcellMetrics->characterWidth;
+ if(instance->ttcap.flags & TTCAP_MONO_CENTER){
+ b_shift = (int)floor((instance->advance/2.0-bbox_center_raw) + .5);
+ tgp->metrics.leftSideBearing += b_shift;
+ tgp->metrics.rightSideBearing += b_shift;
+ }
+ }
+ }
+
+ if( flags & FT_GET_GLYPH_METRICS_ONLY ) return Successful;
+
+ /*
+ * CHECK THE NECESSITY OF BITMAP POSITION'S CORRECTION
+ */
+
+ correct=0;
+ if( instance->spacing == FT_CHARCELL ) correct=1;
+ else if( flags & FT_FORCE_CONSTANT_SPACING ) correct=1;
+ else{
+ int sbit_available=0;
+ sbitchk_incomplete_but_exist=0;
+ if( !(instance->load_flags & FT_LOAD_NO_BITMAP) ) {
+ if( FT_Do_SBit_Metrics(face->face,instance->size,
+ instance->strike_index,idx,NULL,
+ &sbitchk_incomplete_but_exist)==0 ) {
+ sbit_available=1;
+ }
+ }
+ if( sbit_available == 0 ) {
+ if ( sbitchk_incomplete_but_exist==0 && (instance->ttcap.flags & TTCAP_IS_VERY_LAZY) ) {
+ if( FT_IS_SFNT(face->face) ) correct=1;
+ }
+ }
+ }
+
+ /*
+ * RENDER AND ALLOCATE BUFFER
+ */
+
+ if( flags & FT_GET_DUMMY ) is_outline = -1;
+ else {
+ if( !metrics ) {
+ ftrc = FT_Load_Glyph(instance->face->face, idx,
+ instance->load_flags);
+ metrics = &face->face->glyph->metrics;
+
+ if(ftrc != 0) return FTtoXReturnCode(ftrc);
+ }
+
+ if( face->face->glyph->format != FT_GLYPH_FORMAT_BITMAP ) {
+#ifdef USE_GET_CBOX
+ FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox);
+ ftrc = 0;
+#else
+ ftrc = FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox);
+#endif
+ if( ftrc != 0 ) return FTtoXReturnCode(ftrc);
+ bbox.yMin = FLOOR64( bbox.yMin );
+ bbox.yMax = CEIL64 ( bbox.yMax );
+ ht_actual = ( bbox.yMax - bbox.yMin ) >> 6;
+ /* FreeType think a glyph with 0 height control box is invalid.
+ * So just let X to create a empty bitmap instead. */
+ if ( ht_actual == 0 )
+ is_outline = -1;
+ else
+ {
+ ftrc = FT_Render_Glyph(face->face->glyph,FT_RENDER_MODE_MONO);
+ if( ftrc != 0 ) return FTtoXReturnCode(ftrc);
+ is_outline = 1;
+ }
+ }
+ else{
+ is_outline=0;
+ }
+ }
+
+ /* Spacial case */
+ if( (instance->ttcap.flags & TTCAP_MONO_CENTER) && hasMetrics ) {
+ if( is_outline == 1 ){
+ if( correct ){
+ if( ft_get_very_lazy_bbox( idx, face->face, instance->size,
+ face->num_hmetrics,
+ instance->ttcap.vl_slant,
+ &instance->transformation.matrix,
+ &bbox, &outline_hori_advance,
+ &outline_vert_advance ) != 0 ){
+ is_outline = -1; /* <- error */
+ }
+ }
+ else {
+#ifdef USE_GET_CBOX
+ FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox);
+ ftrc=0;
+#else
+ ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox);
+#endif
+ if( ftrc != 0 ) return FTtoXReturnCode(ftrc);
+ }
+ bbox_center_raw = (double)(bbox.xMax + bbox.xMin)/2.0/64.;
+ }
+ else if( is_outline == 0 )
+ bbox_center_raw = (2.0 * metrics->horiBearingX + metrics->width)/2.0/64.0;
+ else
+ bbox_center_raw = 0;
+ b_shift = (int)floor((instance->advance/2.0-bbox_center_raw) + .5);
+ }
+
+ wd_actual = tgp->metrics.rightSideBearing - tgp->metrics.leftSideBearing;
+ ht_actual = tgp->metrics.ascent + tgp->metrics.descent;
+
+ /* The X convention is to consider a character with an empty
+ * bounding box as undefined. This convention is broken. */
+
+ if(wd_actual <= 0) wd = 1;
+ else wd=wd_actual;
+ if(ht_actual <= 0) ht = 1;
+ else ht=ht_actual;
+
+ bpr = (((wd + (instance->bmfmt.glyph<<3) - 1) >> 3) &
+ -instance->bmfmt.glyph);
+ raster = calloc(1, ht * bpr);
+ if(raster == NULL)
+ return AllocError;
+
+ tgp->bits = raster;
+
+ /* If FT_GET_DUMMY is set, we return white space. */
+ if ( is_outline == -1 ) return Successful;
+
+ if ( wd_actual <= 0 || ht_actual <= 0 ) return Successful;
+
+ /*
+ * CALCULATE OFFSET, dx AND dy.
+ */
+
+ dx = face->face->glyph->bitmap_left - tgp->metrics.leftSideBearing;
+ dy = tgp->metrics.ascent - face->face->glyph->bitmap_top;
+
+ if(instance->ttcap.flags & TTCAP_MONO_CENTER)
+ dx += b_shift;
+
+ /* To prevent chipped bitmap, we correct dx and dy if needed. */
+ if( correct && is_outline==1 ){
+ int lsb, rsb, asc, des;
+ int chip_left,chip_right,chip_top,chip_bot;
+#ifdef USE_GET_CBOX
+ FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox);
+ ftrc=0;
+#else
+ ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox);
+#endif
+ if( ftrc != 0 ) return FTtoXReturnCode(ftrc);
+ des = CEIL64(-bbox.yMin - 32) / 64;
+ lsb = FLOOR64(bbox.xMin + 32) / 64;
+ asc = FLOOR64(bbox.yMax + 32) / 64;
+ rsb = FLOOR64(bbox.xMax + 32) / 64;
+ rightSideBearing = tgp->metrics.rightSideBearing;
+ leftSideBearing = tgp->metrics.leftSideBearing;
+ if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE )
+ rightSideBearing -= instance->ttcap.doubleStrikeShift;
+ /* special case */
+ if(instance->ttcap.flags & TTCAP_MONO_CENTER){
+ leftSideBearing -= b_shift;
+ rightSideBearing -= b_shift;
+ }
+ chip_left = lsb - leftSideBearing;
+ chip_right = rightSideBearing - rsb;
+ if( flags & FT_FORCE_CONSTANT_SPACING ){
+ if( instance->ttcap.force_c_adjust_lsb_by_pixel != 0 ||
+ instance->ttcap.force_c_adjust_rsb_by_pixel != 0 ){
+ chip_left=0;
+ chip_right=0;
+ }
+ }
+ else{
+ if( instance->ttcap.adjustRightSideBearingByPixel != 0 ||
+ instance->ttcap.adjustLeftSideBearingByPixel != 0 ){
+ chip_left=0;
+ chip_right=0;
+ }
+ }
+ chip_top = tgp->metrics.ascent - asc;
+ chip_bot = tgp->metrics.descent - des;
+ if( chip_left < 0 && 0 < chip_right ) dx++;
+ else if( chip_right < 0 && 0 < chip_left ) dx--;
+ if( chip_top < 0 && 0 < chip_bot ) dy++;
+ else if( chip_bot < 0 && 0 < chip_top ) dy--;
+ }
+
+ /*
+ * COPY RASTER
+ */
+
+ {
+ FT_Bitmap *bitmap;
+ int i, j;
+ unsigned char *current_raster;
+ unsigned char *current_buffer;
+ int mod_dx0,mod_dx1;
+ int div_dx;
+ bitmap = &face->face->glyph->bitmap;
+ if( 0 <= dx ){
+ div_dx = dx / 8;
+ mod_dx0 = dx % 8;
+ mod_dx1 = 8-mod_dx0;
+ }
+ else{
+ div_dx = dx / 8 -1;
+ mod_dx1 = -dx % 8;
+ mod_dx0 = 8-mod_dx1;
+ }
+ for( i = MAX(0, dy) ; i<ht ; i++ ){
+ int prev_jj,jj;
+ if( bitmap->rows <= i-dy ) break;
+ current_buffer=(unsigned char *)(bitmap->buffer+bitmap->pitch*(i-dy));
+ current_raster=(unsigned char *)(raster+i*bpr);
+ j = MAX(0,div_dx);
+ jj = j-div_dx;
+ prev_jj = jj-1;
+ if( j<bpr ){
+ if( 0 <= prev_jj && prev_jj < bitmap->pitch )
+ current_raster[j]|=current_buffer[prev_jj]<<mod_dx1;
+ if( 0 <= jj && jj < bitmap->pitch ){
+ current_raster[j]|=current_buffer[jj]>>mod_dx0;
+ j++; prev_jj++; jj++;
+ for( ; j<bpr ; j++,prev_jj++,jj++ ){
+ current_raster[j]|=current_buffer[prev_jj]<<mod_dx1;
+ if( bitmap->pitch <= jj ) break;
+ current_raster[j]|=current_buffer[jj]>>mod_dx0;
+ }
+ }
+ }
+ }
+ }
+
+ /* by TTCap */
+ if ( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE ) {
+ int i;
+ for( i=0 ; i < instance->ttcap.doubleStrikeShift ; i++ )
+ ft_make_up_bold_bitmap( raster, bpr, ht, instance->ttcap.flags);
+ }
+ if ( is_outline == 0 &&
+ ( instance->ttcap.lsbShiftOfBitmapAutoItalic != 0 ||
+ instance->ttcap.rsbShiftOfBitmapAutoItalic != 0 ) ) {
+ ft_make_up_italic_bitmap( raster, bpr, ht,
+ - instance->ttcap.lsbShiftOfBitmapAutoItalic
+ + instance->ttcap.rsbShiftOfBitmapAutoItalic,
+ instance->charcellMetrics->ascent
+ + instance->charcellMetrics->descent,
+ instance->charcellMetrics->ascent
+ - tgp->metrics.ascent,
+ instance->ttcap.autoItalic);
+ }
+
+ if(instance->bmfmt.bit == LSBFirst) {
+ BitOrderInvert((unsigned char*)(tgp->bits), ht*bpr);
+ }
+
+ if(instance->bmfmt.byte != instance->bmfmt.bit) {
+ switch(instance->bmfmt.scan) {
+ case 1:
+ break;
+ case 2:
+ TwoByteSwap((unsigned char*)(tgp->bits), ht*bpr);
+ break;
+ case 4:
+ FourByteSwap((unsigned char*)(tgp->bits), ht*bpr);
+ break;
+ default:
+ ;
+ }
+ }
+
+ return Successful;
+}
+
+static void
+FreeTypeFreeFont(FTFontPtr font)
+{
+ FreeTypeFreeInstance(font->instance);
+ if(font->ranges)
+ free(font->ranges);
+ if(font->dummy_char.bits)
+ free(font->dummy_char.bits);
+ free(font);
+}
+
+/* Free a font. If freeProps is 0, don't free the properties. */
+
+static void
+FreeTypeFreeXFont(FontPtr pFont, int freeProps)
+{
+ FTFontPtr tf;
+
+ if(pFont) {
+ if((tf = (FTFontPtr)pFont->fontPrivate)) {
+ FreeTypeFreeFont(tf);
+ }
+ if(freeProps && pFont->info.nprops>0) {
+ free(pFont->info.isStringProp);
+ free(pFont->info.props);
+ }
+ DestroyFontRec(pFont);
+ }
+}
+
+
+/* Unload a font */
+
+static void
+FreeTypeUnloadXFont(FontPtr pFont)
+{
+ MUMBLE("Unloading\n");
+ FreeTypeFreeXFont(pFont, 1);
+}
+
+/* Add the font properties, including the Font name, the XLFD
+ properties, some strings from the font, and various typographical
+ data. We only provide data readily available in the tables in the
+ font for now, altough FIGURE_WIDTH would be a good idea as it is
+ used by Xaw. */
+
+static int
+FreeTypeAddProperties(FTFontPtr font, FontScalablePtr vals, FontInfoPtr info,
+ char *fontname, int rawAverageWidth, Bool font_properties)
+{
+ int i, j, maxprops;
+ char *sp, *ep, val[MAXFONTNAMELEN], *vp;
+ FTFacePtr face;
+ FTInstancePtr instance;
+ FTNormalisedTransformationPtr trans;
+ int upm;
+ TT_OS2 *os2;
+ TT_Postscript *post;
+ PS_FontInfoRec t1info_rec, *t1info;
+ int xlfdProps = 0;
+ int ftrc;
+
+ instance = font->instance;
+ face = instance->face;
+ trans = &instance->transformation;
+ upm = face->face->units_per_EM;
+ if(upm == 0) {
+ /* Work around FreeType bug */
+ upm = WORK_AROUND_UPM;
+ }
+
+ os2 = FT_Get_Sfnt_Table(face->face, ft_sfnt_os2);
+ post = FT_Get_Sfnt_Table(face->face, ft_sfnt_post);
+ ftrc = FT_Get_PS_Font_Info(face->face, &t1info_rec);
+ if(ftrc == 0)
+ t1info = &t1info_rec;
+ else
+ t1info = NULL;
+
+ if(t1info) {
+ os2 = NULL;
+ post = NULL;
+ }
+
+ info->nprops = 0; /* in case we abort */
+
+ strcpy(val, fontname);
+ if(FontParseXLFDName(val, vals, FONT_XLFD_REPLACE_VALUE)) {
+ xlfdProps = 1;
+ } else {
+ MUMBLE("Couldn't parse XLFD\n");
+ xlfdProps = 0;
+ }
+
+ maxprops=
+ 1 + /* NAME */
+ (xlfdProps ? 14 : 0) + /* from XLFD */
+ 5 +
+ ( !face->bitmap ? 3 : 0 ) + /* raw_av,raw_asc,raw_dec */
+ ( font_properties ? 2 : 0 ) + /* asc,dec */
+ ( (font_properties && os2) ? 6 : 0 ) +
+ ( (font_properties && (post || t1info)) ? 3 : 0 ) +
+ 2; /* type */
+
+ info->props = malloc(maxprops * sizeof(FontPropRec));
+ if(info->props == NULL)
+ return AllocError;
+
+ info->isStringProp = malloc(maxprops);
+ if(info->isStringProp == NULL) {
+ free(info->props);
+ return AllocError;
+ }
+
+ memset((char *)info->isStringProp, 0, maxprops);
+
+ i = 0;
+
+ info->props[i].name = MakeAtom("FONT", 4, TRUE);
+ info->props[i].value = MakeAtom(val, strlen(val), TRUE);
+ info->isStringProp[i] = 1;
+ i++;
+
+ if(*val && *(sp = val + 1)) {
+ for (j = 0, sp = val + 1; j < 14; j++) {
+ if (j == 13)
+ /* Handle the case of the final field containing a subset
+ specification. */
+ for (ep = sp; *ep && *ep != '['; ep++);
+ else
+ for (ep = sp; *ep && *ep != '-'; ep++);
+
+ info->props[i].name =
+ MakeAtom(xlfd_props[j], strlen(xlfd_props[j]), TRUE);
+
+ switch(j) {
+ case 6: /* pixel size */
+ info->props[i].value =
+ (int)(fabs(vals->pixel_matrix[3]) + 0.5);
+ i++;
+ break;
+ case 7: /* point size */
+ info->props[i].value =
+ (int)(fabs(vals->point_matrix[3])*10.0 + 0.5);
+ i++;
+ break;
+ case 8: /* resolution x */
+ info->props[i].value = vals->x;
+ i++;
+ break;
+ case 9: /* resolution y */
+ info->props[i].value = vals->y;
+ i++;
+ break;
+ case 11: /* average width */
+ info->props[i].value = vals->width;
+ i++;
+ break;
+ default: /* a string */
+ info->props[i].value = MakeAtom(sp, ep - sp, TRUE);
+ info->isStringProp[i] = 1;
+ i++;
+ }
+ sp = ++ep;
+ }
+ }
+
+ info->props[i].name = MakeAtom("RAW_PIXEL_SIZE", 14, TRUE);
+ info->props[i].value = 1000;
+ i++;
+
+ info->props[i].name = MakeAtom("RAW_POINT_SIZE", 14, TRUE);
+ info->props[i].value = (long)(72270.0 / (double)vals->y + .5);
+ i++;
+
+ if(!face->bitmap) {
+ info->props[i].name = MakeAtom("RAW_AVERAGE_WIDTH", 17, TRUE);
+ info->props[i].value = rawAverageWidth;
+ i++;
+ }
+
+ if ( font_properties ) {
+ info->props[i].name = MakeAtom("FONT_ASCENT", 11, TRUE);
+ info->props[i].value = info->fontAscent;
+ i++;
+ }
+
+ if(!face->bitmap) {
+ info->props[i].name = MakeAtom("RAW_ASCENT", 10, TRUE);
+ info->props[i].value =
+ ((double)face->face->ascender/(double)upm*1000.0);
+ i++;
+ }
+
+ if ( font_properties ) {
+ info->props[i].name = MakeAtom("FONT_DESCENT", 12, TRUE);
+ info->props[i].value = info->fontDescent;
+ i++;
+ }
+
+ if(!face->bitmap) {
+ info->props[i].name = MakeAtom("RAW_DESCENT", 11, TRUE);
+ info->props[i].value =
+ -((double)face->face->descender/(double)upm*1000.0);
+ i++;
+ }
+
+ j = FTGetEnglishName(face->face, TT_NAME_ID_COPYRIGHT,
+ val, MAXFONTNAMELEN);
+ vp = val;
+ if (j < 0) {
+ if(t1info && t1info->notice) {
+ vp = t1info->notice;
+ j = strlen(vp);
+ }
+ }
+ if(j > 0) {
+ info->props[i].name = MakeAtom("COPYRIGHT", 9, TRUE);
+ info->props[i].value = MakeAtom(vp, j, TRUE);
+ info->isStringProp[i] = 1;
+ i++;
+ }
+
+ j = FTGetEnglishName(face->face, TT_NAME_ID_FULL_NAME,
+ val, MAXFONTNAMELEN);
+ vp = val;
+ if (j < 0) {
+ if(t1info && t1info->full_name) {
+ vp = t1info->full_name;
+ j = strlen(vp);
+ }
+ }
+ if(j > 0) {
+ info->props[i].name = MakeAtom("FACE_NAME", 9, TRUE);
+ info->props[i].value = MakeAtom(vp, j, TRUE);
+ info->isStringProp[i] = 1;
+ i++;
+ }
+
+ vp = (char *)FT_Get_Postscript_Name(face->face);
+ if (vp) {
+ j = strlen(vp);
+ } else {
+ j = -1;
+ }
+ if (j < 0) {
+ j = FTGetEnglishName(face->face, TT_NAME_ID_PS_NAME,
+ val, MAXFONTNAMELEN);
+ vp = val;
+ }
+ if (j < 0) {
+ if(t1info && t1info->full_name) {
+ vp = t1info->full_name;
+ j = strlen(vp);
+ }
+ }
+ if(j > 0) {
+ info->props[i].name = MakeAtom("_ADOBE_POSTSCRIPT_FONTNAME", 26, TRUE);
+ info->props[i].value = MakeAtom(vp, j, TRUE);
+ info->isStringProp[i] = 1;
+ i++;
+ }
+
+ /* These macros handle the case of a diagonal matrix. They convert
+ FUnits into pixels. */
+#define TRANSFORM_FUNITS_X(xval) \
+ ((int) \
+ floor( ((double)(xval)/(double)upm) * (double)vals->pixel_matrix[0] + 0.5 ) )
+
+#define TRANSFORM_FUNITS_Y(yval) \
+ ((int) \
+ floor( ((double)(yval)/(double)upm) * (double)vals->pixel_matrix[3] + 0.5 ) )
+
+ /* In what follows, we assume the matrix is diagonal. In the rare
+ case when it is not, the values will be somewhat wrong. */
+
+ if( font_properties && os2 ) {
+ info->props[i].name = MakeAtom("SUBSCRIPT_SIZE",14,TRUE);
+ info->props[i].value =
+ TRANSFORM_FUNITS_Y(os2->ySubscriptYSize);
+ i++;
+ info->props[i].name = MakeAtom("SUBSCRIPT_X",11,TRUE);
+ info->props[i].value =
+ TRANSFORM_FUNITS_X(os2->ySubscriptXOffset);
+ i++;
+ info->props[i].name = MakeAtom("SUBSCRIPT_Y",11,TRUE);
+ info->props[i].value =
+ TRANSFORM_FUNITS_Y(os2->ySubscriptYOffset);
+ i++;
+ info->props[i].name = MakeAtom("SUPERSCRIPT_SIZE",16,TRUE);
+ info->props[i].value =
+ TRANSFORM_FUNITS_Y(os2->ySuperscriptYSize);
+ i++;
+ info->props[i].name = MakeAtom("SUPERSCRIPT_X",13,TRUE);
+ info->props[i].value =
+ TRANSFORM_FUNITS_X(os2->ySuperscriptXOffset);
+ i++;
+ info->props[i].name = MakeAtom("SUPERSCRIPT_Y",13,TRUE);
+ info->props[i].value =
+ TRANSFORM_FUNITS_Y(os2->ySuperscriptYOffset);
+ i++;
+ }
+
+ if( font_properties && (post || t1info) ) {
+ int underlinePosition, underlineThickness;
+
+ /* Raw underlineposition counts upwards,
+ but UNDERLINE_POSITION counts downwards. */
+ if(post) {
+ underlinePosition = TRANSFORM_FUNITS_Y(-post->underlinePosition);
+ underlineThickness = TRANSFORM_FUNITS_Y(post->underlineThickness);
+ } else {
+ underlinePosition =
+ TRANSFORM_FUNITS_Y(-t1info->underline_position);
+ underlineThickness =
+ TRANSFORM_FUNITS_Y(t1info->underline_thickness);
+ }
+ if(underlineThickness <= 0)
+ underlineThickness = 1;
+
+ info->props[i].name = MakeAtom("UNDERLINE_THICKNESS",19,TRUE);
+ info->props[i].value = underlineThickness;
+ i++;
+
+ info->props[i].name = MakeAtom("UNDERLINE_POSITION",18,TRUE);
+
+ info->props[i].value = underlinePosition;
+
+ i++;
+
+ /* The italic angle is often unreliable for Type 1 fonts */
+ if(post && trans->matrix.xx == trans->matrix.yy) {
+ info->props[i].name = MakeAtom("ITALIC_ANGLE",12,TRUE);
+ info->props[i].value =
+ /* Convert from TT_Fixed to
+ 64th of a degree counterclockwise from 3 o'clock */
+ 90*64+(post->italicAngle >> 10);
+ i++;
+ }
+#undef TRANSFORM_FUNITS_X
+#undef TRANSFORM_FUNITS_Y
+ }
+
+ info->props[i].name = MakeAtom("FONT_TYPE", 9, TRUE);
+ vp = (char *)FT_Get_X11_Font_Format(face->face);
+ info->props[i].value = MakeAtom(vp, strlen(vp), TRUE);
+ info->isStringProp[i] = 1;
+ i++;
+
+ info->props[i].name = MakeAtom("RASTERIZER_NAME", 15, TRUE);
+ info->props[i].value = MakeAtom("FreeType", 10, TRUE);
+ info->isStringProp[i] = 1;
+ i++;
+
+ info->nprops = i;
+ return Successful;
+}
+
+static int
+ft_get_index(unsigned code, FTFontPtr font, unsigned *idx)
+{
+
+ /* As a special case, we pass 0 even when it is not in the ranges;
+ this will allow for the default glyph, which should exist in any
+ TrueType font. */
+
+ /* This is not required...
+ if(code > 0 && font->nranges) {
+ int i;
+ for(i = 0; i < font->nranges; i++)
+ if((code >=
+ font->ranges[i].min_char_low+
+ (font->ranges[i].min_char_high<<8)) &&
+ (code <=
+ font->ranges[i].max_char_low +
+ (font->ranges[i].max_char_high<<8)))
+ break;
+ if(i == font->nranges) {
+ *idx = font->zero_idx;
+ return -1;
+ }
+ }
+ */
+ if( font->info ) {
+ if( !( font->info->firstCol <= (code & 0x000ff) &&
+ (code & 0x000ff) <= font->info->lastCol &&
+ font->info->firstRow <= (code >> 8) &&
+ (code >> 8) <= font->info->lastRow ) ) {
+ *idx = font->zero_idx;
+ /* Error: The code has not been parsed in ft_compute_bounds()!
+ We should not return any metrics. */
+ return -1;
+ }
+ }
+
+ *idx = FTRemap(font->instance->face->face, &font->mapping, code);
+
+ return 0;
+}
+
+static int
+FreeTypeFontGetGlyph(unsigned code, int flags, CharInfoPtr *g, FTFontPtr font)
+{
+ unsigned idx = 0;
+ int xrc;
+
+#ifdef X_ACCEPTS_NO_SUCH_CHAR
+ if( ft_get_index(code,font,&idx) || idx == 0 || idx == font->zero_idx ) {
+ *g = NULL;
+ flags &= ~FT_FORCE_CONSTANT_SPACING;
+ /* if( font->instance->spacing != FT_CHARCELL ) */
+ return Successful;
+ }
+#else
+ if( ft_get_index(code,font,&idx) ) {
+ /* The code has not been parsed! */
+ *g = NULL;
+ flags &= ~FT_FORCE_CONSTANT_SPACING;
+ }
+#endif
+
+ xrc = FreeTypeInstanceGetGlyph(idx, flags, g, font->instance);
+ if( xrc == Successful && *g != NULL )
+ return Successful;
+ if( font->zero_idx != idx ) {
+ xrc = FreeTypeInstanceGetGlyph(font->zero_idx, flags, g, font->instance);
+ if( xrc == Successful && *g != NULL )
+ return Successful;
+ }
+ return FreeTypeInstanceGetGlyph(font->zero_idx, flags|FT_GET_DUMMY, g, font->instance);
+}
+
+static int
+FreeTypeFontGetGlyphMetrics(unsigned code, int flags, xCharInfo **metrics, FTFontPtr font)
+{
+ unsigned idx = 0;
+ int xrc;
+
+#ifdef X_ACCEPTS_NO_SUCH_CHAR
+ if ( ft_get_index(code,font,&idx) || idx == 0 || idx == font->zero_idx ) {
+ *metrics = NULL;
+ flags &= ~FT_FORCE_CONSTANT_SPACING;
+ /* if( font->instance->spacing != FT_CHARCELL ) */
+ return Successful;
+ }
+#else
+ if ( ft_get_index(code,font,&idx) || idx == 0 || idx == font->zero_idx ) {
+ /* The code has not been parsed! */
+ *metrics = NULL;
+ flags &= ~FT_FORCE_CONSTANT_SPACING;
+ }
+#endif
+
+ xrc = FreeTypeInstanceGetGlyphMetrics(idx, flags, metrics, font->instance);
+ if( xrc == Successful && *metrics != NULL )
+ return Successful;
+ if( font->zero_idx != idx ) {
+ xrc = FreeTypeInstanceGetGlyphMetrics(font->zero_idx, flags,
+ metrics, font->instance);
+ if( xrc == Successful && *metrics != NULL )
+ return Successful;
+ }
+ return FreeTypeInstanceGetGlyphMetrics(font->zero_idx, flags|FT_GET_DUMMY, metrics, font->instance);
+}
+
+/*
+ * restrict code range
+ *
+ * boolean for the numeric zone:
+ * results = results & (ranges[0] | ranges[1] | ... ranges[nranges-1])
+ */
+
+static void
+restrict_code_range(unsigned short *refFirstCol,
+ unsigned short *refFirstRow,
+ unsigned short *refLastCol,
+ unsigned short *refLastRow,
+ fsRange const *ranges, int nRanges)
+{
+ if (nRanges) {
+ int minCol = 256, minRow = 256, maxCol = -1, maxRow = -1;
+ fsRange const *r = ranges;
+ int i;
+
+ for (i=0; i<nRanges; i++) {
+ if (r->min_char_high != r->max_char_high) {
+ minCol = 0x00;
+ maxCol = 0xff;
+ } else {
+ if (minCol > r->min_char_low)
+ minCol = r->min_char_low;
+ if (maxCol < r->max_char_low)
+ maxCol = r->max_char_low;
+ }
+ if (minRow > r->min_char_high)
+ minRow = r->min_char_high;
+ if (maxRow < r->max_char_high)
+ maxRow = r->max_char_high;
+ r++;
+ }
+
+ if (minCol > *refLastCol)
+ *refFirstCol = *refLastCol;
+ else if (minCol > *refFirstCol)
+ *refFirstCol = minCol;
+
+ if (maxCol < *refFirstCol)
+ *refLastCol = *refFirstCol;
+ else if (maxCol < *refLastCol)
+ *refLastCol = maxCol;
+
+ if (minRow > *refLastRow) {
+ *refFirstRow = *refLastRow;
+ *refFirstCol = *refLastCol;
+ } else if (minRow > *refFirstRow)
+ *refFirstRow = minRow;
+
+ if (maxRow < *refFirstRow) {
+ *refLastRow = *refFirstRow;
+ *refLastCol = *refFirstCol;
+ } else if (maxRow < *refLastRow)
+ *refLastRow = maxRow;
+ }
+}
+
+
+static int
+restrict_code_range_by_str(int count,unsigned short *refFirstCol,
+ unsigned short *refFirstRow,
+ unsigned short *refLastCol,
+ unsigned short *refLastRow,
+ char const *str)
+{
+ int nRanges = 0;
+ int result = 0;
+ fsRange *ranges = NULL;
+ char const *p, *q;
+
+ p = q = str;
+ for (;;) {
+ int minpoint=0, maxpoint=65535;
+ long val;
+
+ /* skip comma and/or space */
+ while (',' == *p || isspace(*p))
+ p++;
+
+ /* begin point */
+ if ('-' != *p) {
+ val = strtol(p, (char **)&q, 0);
+ if (p == q)
+ /* end or illegal */
+ break;
+ if (val<0 || val>65535) {
+ /* out of zone */
+ break;
+ }
+ minpoint = val;
+ p=q;
+ }
+
+ /* skip space */
+ while (isspace(*p))
+ p++;
+
+ if (',' != *p && '\0' != *p) {
+ /* contiune */
+ if ('-' == *p)
+ /* hyphon */
+ p++;
+ else
+ /* end or illegal */
+ break;
+
+ /* skip space */
+ while (isspace(*p))
+ p++;
+
+ val = strtol(p, (char **)&q, 0);
+ if (p != q) {
+ if (val<0 || val>65535)
+ break;
+ maxpoint = val;
+ } else if (',' != *p && '\0' != *p)
+ /* end or illegal */
+ break;
+ p=q;
+ } else
+ /* comma - single code */
+ maxpoint = minpoint;
+
+ if ( count <= 0 && minpoint>maxpoint ) {
+ int tmp;
+ tmp = minpoint;
+ minpoint = maxpoint;
+ maxpoint = tmp;
+ }
+
+ /* add range */
+#if 0
+ fprintf(stderr, "zone: 0x%04X - 0x%04X\n", minpoint, maxpoint);
+ fflush(stderr);
+#endif
+ nRanges++;
+ ranges = realloc(ranges, nRanges*sizeof(*ranges));
+ if (NULL == ranges)
+ break;
+ {
+ fsRange *r = ranges+nRanges-1;
+
+ r->min_char_low = minpoint & 0xff;
+ r->max_char_low = maxpoint & 0xff;
+ r->min_char_high = (minpoint>>8) & 0xff;
+ r->max_char_high = (maxpoint>>8) & 0xff;
+ }
+ }
+
+ if (ranges) {
+ if ( count <= 0 ) {
+ restrict_code_range(refFirstCol, refFirstRow, refLastCol, refLastRow,
+ ranges, nRanges);
+ }
+ else {
+ int i;
+ fsRange *r;
+ for ( i=0 ; i<nRanges ; i++ ) {
+ if ( count <= i ) break;
+ r = ranges+i;
+ refFirstCol[i] = r->min_char_low;
+ refLastCol[i] = r->max_char_low;
+ refFirstRow[i] = r->min_char_high;
+ refLastRow[i] = r->max_char_high;
+ }
+ result=i;
+ }
+ free(ranges);
+ }
+ return result;
+}
+
+/* *face_number and *spacing are initialized but *load_flags is NOT. */
+static int
+FreeTypeSetUpTTCap( char *fileName, FontScalablePtr vals,
+ char **dynStrRealFileName, char **dynStrFTFileName,
+ struct TTCapInfo *ret, int *face_number, FT_Int32 *load_flags,
+ int *spacing, Bool *font_properties, char **dynStrTTCapCodeRange )
+{
+ int result = Successful;
+ SDynPropRecValList listPropRecVal;
+ SPropRecValContainer contRecValue;
+ Bool hinting=True;
+ Bool isEmbeddedBitmap = True;
+ Bool alwaysEmbeddedBitmap = False;
+ int pixel = vals->pixel;
+
+ *font_properties=True;
+ *dynStrRealFileName=NULL;
+ *dynStrFTFileName=NULL;
+ *dynStrTTCapCodeRange=NULL;
+
+ if (SPropRecValList_new(&listPropRecVal)) {
+ return AllocError;
+ }
+
+ {
+ int len = strlen(fileName);
+ char *capHead = NULL;
+ {
+ /* font cap */
+ char *p1=NULL, *p2=NULL;
+
+ p1=strrchr(fileName, '/');
+ if ( p1 == NULL ) p1 = fileName;
+ else p1++;
+ if (NULL != (p2=strrchr(p1, ':'))) {
+ /* colon exist in the right side of slash. */
+ int dirLen = p1-fileName;
+ int baseLen = fileName+len - p2 -1;
+
+ *dynStrRealFileName = malloc(dirLen+baseLen+1);
+ if( *dynStrRealFileName == NULL ) {
+ result = AllocError;
+ goto quit;
+ }
+ if ( 0 < dirLen )
+ memcpy(*dynStrRealFileName, fileName, dirLen);
+ strcpy(*dynStrRealFileName+dirLen, p2+1);
+ capHead = p1;
+ } else {
+ *dynStrRealFileName = xstrdup(fileName);
+ if( *dynStrRealFileName == NULL ) {
+ result = AllocError;
+ goto quit;
+ }
+ }
+ }
+
+ /* font cap */
+ if (capHead) {
+ if (SPropRecValList_add_by_font_cap(&listPropRecVal,
+ capHead)) {
+ result = BadFontPath;
+ goto quit;
+ }
+ }
+ }
+
+ *face_number=0;
+ *spacing=0;
+ ret->autoItalic=0.0;
+ ret->scaleWidth=1.0;
+ ret->scaleBBoxWidth = 1.0;
+ ret->scaleBBoxHeight = 1.0;
+ ret->doubleStrikeShift = 1;
+ ret->adjustBBoxWidthByPixel = 0;
+ ret->adjustLeftSideBearingByPixel = 0;
+ ret->adjustRightSideBearingByPixel = 0;
+ ret->flags = 0;
+ ret->scaleBitmap = 0.0;
+ ret->forceConstantSpacingBegin = -1;
+ ret->forceConstantSpacingEnd = -1;
+ ret->force_c_representative_metrics_char_code = -2;
+ ret->force_c_scale_b_box_width = 1.0;
+ ret->force_c_scale_b_box_height = 1.0;
+ ret->force_c_adjust_width_by_pixel = 0;
+ ret->force_c_adjust_lsb_by_pixel = 0;
+ ret->force_c_adjust_rsb_by_pixel = 0;
+ ret->force_c_scale_lsb = 0.0;
+ ret->force_c_scale_rsb = 1.0;
+ /* */
+ ret->vl_slant=0;
+ ret->lsbShiftOfBitmapAutoItalic=0;
+ ret->rsbShiftOfBitmapAutoItalic=0;
+ /* face number */
+ {
+ char *beginptr=NULL,*endptr;
+ if ( SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "FaceNumber")) {
+ int lv;
+ beginptr = SPropContainer_value_str(contRecValue);
+ lv=strtol(beginptr, &endptr, 10);
+ if ( *beginptr != '\0' && *endptr == '\0' ) {
+ if ( 0 < lv ) *face_number = lv;
+ }
+ }
+ if( beginptr && 0 < *face_number ) {
+ char *slash;
+ *dynStrFTFileName = /* add -> ':'+strlen0+':'+strlen1+'\0' */
+ malloc(1+strlen(beginptr)+1+strlen(*dynStrRealFileName)+1);
+ if( *dynStrFTFileName == NULL ){
+ result = AllocError;
+ goto quit;
+ }
+ **dynStrFTFileName = '\0';
+ slash = strrchr(*dynStrRealFileName,'/');
+ if( slash ) {
+ char *p;
+ strcat(*dynStrFTFileName,*dynStrRealFileName);
+ p = strrchr(*dynStrFTFileName,'/');
+ p[1] = '\0';
+ strcat(*dynStrFTFileName,":");
+ strcat(*dynStrFTFileName,beginptr);
+ strcat(*dynStrFTFileName,":");
+ strcat(*dynStrFTFileName,slash+1);
+ }
+ else{
+ strcat(*dynStrFTFileName,":");
+ strcat(*dynStrFTFileName,beginptr);
+ strcat(*dynStrFTFileName,":");
+ strcat(*dynStrFTFileName,*dynStrRealFileName);
+ }
+ }
+ else{
+ *dynStrFTFileName = malloc(strlen(*dynStrRealFileName)+1);
+ if( *dynStrFTFileName == NULL ){
+ result = AllocError;
+ goto quit;
+ }
+ **dynStrFTFileName = '\0';
+ strcat(*dynStrFTFileName,*dynStrRealFileName);
+ }
+ }
+ /*
+ fprintf(stderr,"[Filename:%s]\n",fileName);
+ fprintf(stderr,"[RealFilename:%s]\n",*dynStrRealFileName);
+ fprintf(stderr,"[FTFilename:%s]\n",*dynStrFTFileName);
+ */
+ /* slant control */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "AutoItalic"))
+ ret->autoItalic = SPropContainer_value_dbl(contRecValue);
+ /* hinting control */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "Hinting"))
+ hinting = SPropContainer_value_bool(contRecValue);
+ /* scaling */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "ScaleWidth")) {
+ ret->scaleWidth = SPropContainer_value_dbl(contRecValue);
+ if (ret->scaleWidth<=0.0) {
+ fprintf(stderr, "ScaleWitdh needs plus.\n");
+ result = BadFontName;
+ goto quit;
+ }
+ }
+ /* bbox adjustment */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "ScaleBBoxWidth")) {
+ /* Scaling to Bounding Box Width */
+ int lv;
+ char *endptr,*beginptr;
+ double v,scaleBBoxWidth=1.0,scaleBBoxHeight=1.0;
+ beginptr = SPropContainer_value_str(contRecValue);
+ do {
+ if ( strlen(beginptr) < 1 ) break;
+ v=strtod(beginptr, &endptr);
+ if ( endptr!=beginptr ) {
+ scaleBBoxWidth = v;
+ }
+ if ( *endptr != ';' && *endptr != ',' ) break;
+ if ( *endptr == ',' ) {
+ beginptr=endptr+1;
+ v=strtod(beginptr, &endptr);
+ if ( endptr!=beginptr ) {
+ scaleBBoxHeight = v;
+ }
+ }
+ if ( *endptr != ';' && *endptr != ',' ) break;
+ beginptr=endptr+1;
+ lv=strtol(beginptr, &endptr, 10);
+ if ( endptr!=beginptr ) {
+ ret->adjustBBoxWidthByPixel = lv;
+ }
+ if ( *endptr != ',' ) break;
+ beginptr=endptr+1;
+ lv=strtol(beginptr, &endptr, 10);
+ if ( endptr!=beginptr ) {
+ ret->adjustLeftSideBearingByPixel = lv;
+ }
+ if ( *endptr != ',' ) break;
+ beginptr=endptr+1;
+ lv=strtol(beginptr, &endptr, 10);
+ if ( endptr!=beginptr ) {
+ ret->adjustRightSideBearingByPixel = lv;
+ }
+ } while ( 0 );
+ if (scaleBBoxWidth<=0.0) {
+ fprintf(stderr, "ScaleBBoxWitdh needs plus.\n");
+ result = BadFontName;
+ goto quit;
+ }
+ if (scaleBBoxHeight<=0.0) {
+ fprintf(stderr, "ScaleBBoxHeight needs plus.\n");
+ result = BadFontName;
+ goto quit;
+ }
+ ret->scaleBBoxWidth = scaleBBoxWidth;
+ ret->scaleBBoxHeight = scaleBBoxHeight;
+ }
+ /* spacing */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "ForceSpacing")) {
+ char *strSpace = SPropContainer_value_str(contRecValue);
+ Bool err = False;
+ if (1 != strlen(strSpace))
+ err = True;
+ else
+ switch (strSpace[0]) {
+ case 'M':
+ ret->flags |= TTCAP_MONO_CENTER;
+ *spacing = 'm';
+ break;
+ case 'm':
+ case 'p':
+ case 'c':
+ *spacing = strSpace[0];
+ break;
+ default:
+ err = True;
+ }
+ if (err) {
+ result = BadFontName;
+ goto quit;
+ }
+ }
+ /* doube striking */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "DoubleStrike")) {
+ /* Set or Reset Auto Bold Flag */
+ char *strDoubleStrike = SPropContainer_value_str(contRecValue);
+ Bool err = False;
+ if ( 0 < strlen(strDoubleStrike) ) {
+ switch (strDoubleStrike[0]) {
+ case 'm':
+ case 'M':
+ case 'l':
+ case 'L':
+ ret->flags |= TTCAP_DOUBLE_STRIKE;
+ ret->flags |= TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT;
+ break;
+ case 'y':
+ case 'Y':
+ ret->flags |= TTCAP_DOUBLE_STRIKE;
+ break;
+ case 'n':
+ case 'N':
+ ret->flags &= ~TTCAP_DOUBLE_STRIKE;
+ ret->flags &= ~TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT;
+ ret->flags &= ~TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH;
+ break;
+ default:
+ err = True;
+ }
+ if ( err != True ) {
+ if ( strDoubleStrike[1] ) {
+ switch (strDoubleStrike[1]) {
+ case 'b':
+ case 'B':
+ case 'p':
+ case 'P':
+ case 'y':
+ case 'Y':
+ ret->flags |= TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH;
+ break;
+ default:
+ break;
+ }
+ }
+ do {
+ char *comma_ptr=strchr(strDoubleStrike,';');
+ if ( !comma_ptr ) comma_ptr=strchr(strDoubleStrike,',');
+ if ( !comma_ptr ) break;
+ if ( comma_ptr[1] ) {
+ char *endptr;
+ int mkboldMaxPixel;
+ mkboldMaxPixel=strtol(comma_ptr+1, &endptr, 10);
+ if ( endptr != comma_ptr+1 && mkboldMaxPixel <= pixel ) {
+ ret->flags &= ~TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT;
+ }
+ }
+ comma_ptr=strchr(comma_ptr+1,',');
+ if ( !comma_ptr ) break;
+ if ( comma_ptr[1] ) {
+ char *endptr;
+ int max_pixel;
+ max_pixel=strtol(comma_ptr+1, &endptr, 10);
+ if ( endptr != comma_ptr+1 && max_pixel <= pixel ) {
+ if( ret->flags & TTCAP_DOUBLE_STRIKE )
+ ret->doubleStrikeShift += pixel / max_pixel;
+ }
+ }
+ } while(0);
+ }
+ }
+ else
+ err = True;
+ if (err) {
+ result = BadFontName;
+ goto quit;
+ }
+ }
+ /* very lazy metrics */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "VeryLazyMetrics")){
+ Bool isVeryLazy = SPropContainer_value_bool(contRecValue);
+ ret->flags |= TTCAP_DISABLE_DEFAULT_VERY_LAZY;
+ if( isVeryLazy == True )
+ ret->flags |= TTCAP_IS_VERY_LAZY;
+ else
+ ret->flags &= ~TTCAP_IS_VERY_LAZY;
+ }
+ /* embedded bitmap */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "EmbeddedBitmap")) {
+ char *strEmbeddedBitmap = SPropContainer_value_str(contRecValue);
+ Bool err = False;
+ if ( 1 == strlen(strEmbeddedBitmap) ) {
+ switch (strEmbeddedBitmap[0]) {
+ case 'y':
+ case 'Y':
+ isEmbeddedBitmap = True;
+ alwaysEmbeddedBitmap = True;
+ break;
+ case 'u':
+ case 'U':
+ isEmbeddedBitmap = True;
+ alwaysEmbeddedBitmap = False;
+ break;
+ case 'n':
+ case 'N':
+ isEmbeddedBitmap = False;
+ break;
+ default:
+ err = True;
+ }
+ }
+ else
+ err = True;
+ if (err) {
+ result = BadFontName;
+ goto quit;
+ }
+ }
+ /* scale bitmap */
+ if((ret->flags & TTCAP_IS_VERY_LAZY) &&
+ SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "VeryLazyBitmapWidthScale")) {
+ /* Scaling to Bitmap Bounding Box Width */
+ double scaleBitmapWidth = SPropContainer_value_dbl(contRecValue);
+
+ fprintf(stderr, "Warning: `bs' option is not required in X-TT version 2.\n");
+#if 0
+ if (scaleBitmapWidth<=0.0) {
+ fprintf(stderr, "ScaleBitmapWitdh needs plus.\n");
+ result = BadFontName;
+ goto quit;
+ }
+#endif
+ ret->scaleBitmap = scaleBitmapWidth;
+ }
+ /* restriction of the code range */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "CodeRange")) {
+ *dynStrTTCapCodeRange = xstrdup(SPropContainer_value_str(contRecValue));
+ if( *dynStrTTCapCodeRange == NULL ) {
+ result = AllocError;
+ goto quit;
+ }
+ }
+ /* forceConstantSpacing{Begin,End} */
+ if ( 1 /* ft->spacing == 'p' */ ){
+ unsigned short first_col=0,last_col=0x00ff;
+ unsigned short first_row=0,last_row=0x00ff;
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "ForceConstantSpacingCodeRange")) {
+ if ( restrict_code_range_by_str(1,&first_col, &first_row,
+ &last_col, &last_row,
+ SPropContainer_value_str(contRecValue)) == 1 ) {
+ ret->forceConstantSpacingBegin = (int)( first_row<<8 | first_col );
+ ret->forceConstantSpacingEnd = (int)( last_row<<8 | last_col );
+ if ( ret->forceConstantSpacingBegin <= ret->forceConstantSpacingEnd )
+ ret->flags &= ~TTCAP_FORCE_C_OUTSIDE;
+ else ret->flags |= TTCAP_FORCE_C_OUTSIDE;
+ }
+ }
+ }
+ /* */
+ if ( 1 ){
+ unsigned short first_col=0, last_col=0x0ff;
+ unsigned short first_row=0, last_row=0x0ff;
+ if ( SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "ForceConstantSpacingMetrics")) {
+ char *strMetrics;
+ strMetrics = SPropContainer_value_str(contRecValue);
+ if ( strMetrics ) {
+ char *comma_ptr,*period_ptr,*semic_ptr;
+ semic_ptr=strchr(strMetrics,';');
+ comma_ptr=strchr(strMetrics,',');
+ period_ptr=strchr(strMetrics,'.');
+ if ( semic_ptr && comma_ptr )
+ if ( semic_ptr < comma_ptr ) comma_ptr=NULL;
+ if ( semic_ptr && period_ptr )
+ if ( semic_ptr < period_ptr ) period_ptr=NULL;
+ if ( !comma_ptr && !period_ptr && strMetrics != semic_ptr ) {
+ if ( restrict_code_range_by_str(1,&first_col, &first_row,
+ &last_col, &last_row,
+ SPropContainer_value_str(contRecValue)) == 1 ) {
+ ret->force_c_representative_metrics_char_code =
+ (int)( first_row<<8 | first_col );
+ }
+ }
+ else {
+ double v;
+ char *endptr,*beginptr=strMetrics;
+ do {
+ v=strtod(beginptr, &endptr);
+ if ( endptr!=beginptr ) {
+ ret->force_c_scale_b_box_width = v;
+ }
+ if ( *endptr != ',' ) break;
+ beginptr=endptr+1;
+ v=strtod(beginptr, &endptr);
+ if ( endptr!=beginptr ) {
+ ret->force_c_scale_lsb = v;
+ ret->flags |= TTCAP_FORCE_C_LSB_FLAG;
+ }
+ if ( *endptr != ',' ) break;
+ beginptr=endptr+1;
+ v=strtod(beginptr, &endptr);
+ if ( endptr!=beginptr ) {
+ ret->force_c_scale_rsb = v;
+ ret->flags |= TTCAP_FORCE_C_RSB_FLAG;
+ }
+ if ( *endptr != ',' ) break;
+ beginptr=endptr+1;
+ v=strtod(beginptr, &endptr);
+ if ( endptr!=beginptr ) {
+ ret->force_c_scale_b_box_height = v;
+ }
+ } while (0);
+ }
+ if ( semic_ptr ) {
+ int lv;
+ char *endptr,*beginptr=semic_ptr+1;
+ do {
+ lv=strtol(beginptr, &endptr, 10);
+ if ( endptr!=beginptr ) {
+ ret->force_c_adjust_width_by_pixel=lv;
+ }
+ if ( *endptr != ',' ) break;
+ beginptr=endptr+1;
+ lv=strtol(beginptr, &endptr, 10);
+ if ( endptr!=beginptr ) {
+ ret->force_c_adjust_lsb_by_pixel=lv;
+ }
+ if ( *endptr != ',' ) break;
+ beginptr=endptr+1;
+ lv=strtol(beginptr, &endptr, 10);
+ if ( endptr!=beginptr ) {
+ ret->force_c_adjust_rsb_by_pixel=lv;
+ }
+ } while (0);
+ }
+ }
+ }
+ }
+
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "FontProperties")) {
+ /* Set or Reset the Flag of FontProperties */
+ *font_properties=SPropContainer_value_bool(contRecValue);
+ }
+
+ ret->force_c_scale_b_box_width *= ret->scaleBBoxWidth;
+ ret->force_c_scale_b_box_height *= ret->scaleBBoxHeight;
+
+ ret->force_c_scale_b_box_width *= ret->scaleWidth;
+ ret->scaleBBoxWidth *= ret->scaleWidth;
+
+ ret->force_c_adjust_rsb_by_pixel += ret->adjustRightSideBearingByPixel;
+ ret->force_c_adjust_lsb_by_pixel += ret->adjustLeftSideBearingByPixel;
+
+ /* scaleWidth, scaleBBoxWidth, force_c_scale_b_box_width, force_c_scale_b_box_width */
+
+ /* by TTCap */
+ if( hinting == False ) *load_flags |= FT_LOAD_NO_HINTING;
+ if( isEmbeddedBitmap == False ) *load_flags |= FT_LOAD_NO_BITMAP;
+ if( ret->autoItalic != 0 && alwaysEmbeddedBitmap == False )
+ *load_flags |= FT_LOAD_NO_BITMAP;
+
+ quit:
+ return result;
+}
+
+static int
+ft_get_trans_from_vals( FontScalablePtr vals, FTNormalisedTransformationPtr trans )
+{
+ /* Compute the transformation matrix. We use floating-point
+ arithmetic for simplicity */
+
+ trans->xres = vals->x;
+ trans->yres = vals->y;
+
+ /* This value cannot be 0. */
+ trans->scale = hypot(vals->point_matrix[2], vals->point_matrix[3]);
+ trans->nonIdentity = 0;
+
+ /* Try to round stuff. We want approximate zeros to be exact zeros,
+ and if the elements on the diagonal are approximately equal, we
+ want them equal. We do this to avoid breaking hinting. */
+ if(DIFFER(vals->point_matrix[0], vals->point_matrix[3])) {
+ trans->nonIdentity = 1;
+ trans->matrix.xx =
+ (int)((vals->point_matrix[0]*(double)TWO_SIXTEENTH)/trans->scale);
+ trans->matrix.yy =
+ (int)((vals->point_matrix[3]*(double)TWO_SIXTEENTH)/trans->scale);
+ } else {
+ trans->matrix.xx = trans->matrix.yy =
+ ((vals->point_matrix[0] + vals->point_matrix[3])/2*
+ (double)TWO_SIXTEENTH)/trans->scale;
+ }
+
+ if(DIFFER0(vals->point_matrix[1], trans->scale)) {
+ trans->matrix.yx =
+ (int)((vals->point_matrix[1]*(double)TWO_SIXTEENTH)/trans->scale);
+ trans->nonIdentity = 1;
+ } else
+ trans->matrix.yx = 0;
+
+ if(DIFFER0(vals->point_matrix[2], trans->scale)) {
+ trans->matrix.xy =
+ (int)((vals->point_matrix[2]*(double)TWO_SIXTEENTH)/trans->scale);
+ trans->nonIdentity = 1;
+ } else
+ trans->matrix.xy=0;
+ return 0;
+}
+
+
+static int
+is_fixed_width(FT_Face face)
+{
+ PS_FontInfoRec t1info_rec;
+ int ftrc;
+
+ if(FT_IS_FIXED_WIDTH(face)) {
+ return 1;
+ }
+
+ ftrc = FT_Get_PS_Font_Info(face, &t1info_rec);
+ if(ftrc == 0 && t1info_rec.is_fixed_pitch) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+FreeTypeLoadFont(FTFontPtr font, FontInfoPtr info, FTFacePtr face,
+ char *FTFileName, FontScalablePtr vals, FontEntryPtr entry,
+ FontBitmapFormatPtr bmfmt, FT_Int32 load_flags,
+ struct TTCapInfo *tmp_ttcap, char *dynStrTTCapCodeRange,
+ int ttcap_spacing )
+{
+ int xrc;
+ FTNormalisedTransformationRec trans;
+ int spacing, actual_spacing, zero_code;
+ long lastCode, firstCode;
+ TT_Postscript *post;
+
+ ft_get_trans_from_vals(vals,&trans);
+
+ /* Check for charcell in XLFD */
+ spacing = FT_PROPORTIONAL;
+ if(entry->name.ndashes == 14) {
+ char *p;
+ int dashes = 0;
+ for(p = entry->name.name;
+ p <= entry->name.name + entry->name.length - 2;
+ p++) {
+ if(*p == '-') {
+ dashes++;
+ if(dashes == 11) {
+ if(p[1]=='c' && p[2]=='-')
+ spacing=FT_CHARCELL;
+ else if(p[1]=='m' && p[2]=='-')
+ spacing=FT_MONOSPACED;
+ break;
+ }
+ }
+ }
+ }
+ /* by TTCap */
+ if( ttcap_spacing != 0 ) {
+ if( ttcap_spacing == 'c' ) spacing=FT_CHARCELL;
+ else if( ttcap_spacing == 'm' ) spacing=FT_MONOSPACED;
+ else spacing=FT_PROPORTIONAL;
+ }
+
+ actual_spacing = spacing;
+ if( spacing == FT_PROPORTIONAL ) {
+ if( is_fixed_width(face->face) )
+ actual_spacing = FT_MONOSPACED;
+ }
+
+ if(entry->name.ndashes == 14) {
+ xrc = FTPickMapping(entry->name.name, entry->name.length, FTFileName,
+ face->face, &font->mapping);
+ if (xrc != Successful)
+ return xrc;
+ } else {
+ xrc = FTPickMapping(0, 0, FTFileName,
+ face->face, &font->mapping);
+ if (xrc != Successful)
+ return xrc;
+ }
+
+ font->nranges = vals->nranges;
+ font->ranges = 0;
+ if(font->nranges) {
+ font->ranges = malloc(vals->nranges*sizeof(fsRange));
+ if(font->ranges == NULL)
+ return AllocError;
+ memcpy((char*)font->ranges, (char*)vals->ranges,
+ vals->nranges*sizeof(fsRange));
+ }
+
+ zero_code=-1;
+ if(info) {
+ firstCode = 0;
+ lastCode = 0xFFFFL;
+ if(!font->mapping.mapping ||
+ font->mapping.mapping->encoding->row_size == 0) {
+ /* linear indexing */
+ lastCode=MIN(lastCode,
+ font->mapping.mapping ?
+ font->mapping.mapping->encoding->size-1 :
+ 0xFF);
+ if(font->mapping.mapping && font->mapping.mapping->encoding->first)
+ firstCode = font->mapping.mapping->encoding->first;
+ info->firstRow = firstCode/0x100;
+ info->lastRow = lastCode/0x100;
+ info->firstCol =
+ (info->firstRow || info->lastRow) ? 0 : (firstCode & 0xFF);
+ info->lastCol = info->lastRow ? 0xFF : (lastCode & 0xFF);
+ if ( firstCode == 0 ) zero_code=0;
+ } else {
+ /* matrix indexing */
+ info->firstRow = font->mapping.mapping->encoding->first;
+ info->lastRow = MIN(font->mapping.mapping->encoding->size-1,
+ lastCode/0x100);
+ info->firstCol = font->mapping.mapping->encoding->first_col;
+ info->lastCol = MIN(font->mapping.mapping->encoding->row_size-1,
+ lastCode<0x100?lastCode:0xFF);
+ if( info->firstRow == 0 && info->firstCol == 0 ) zero_code=0;
+ }
+
+ /* firstCode and lastCode are not valid in case of a matrix
+ encoding */
+
+ if( dynStrTTCapCodeRange ) {
+ restrict_code_range_by_str(0,&info->firstCol, &info->firstRow,
+ &info->lastCol, &info->lastRow,
+ dynStrTTCapCodeRange);
+ }
+ restrict_code_range(&info->firstCol, &info->firstRow,
+ &info->lastCol, &info->lastRow,
+ font->ranges, font->nranges);
+ }
+ font->info = info;
+
+ /* zero code is frequently used. */
+ if ( zero_code < 0 ) {
+ /* The fontenc should have the information of DefaultCh.
+ But we do not have such a information.
+ So we cannot but set 0. */
+ font->zero_idx = 0;
+ }
+ else
+ font->zero_idx = FTRemap(face->face,
+ &font->mapping, zero_code);
+
+ post = FT_Get_Sfnt_Table(face->face, ft_sfnt_post);
+
+#ifdef DEFAULT_VERY_LAZY
+ if( !( tmp_ttcap->flags & TTCAP_DISABLE_DEFAULT_VERY_LAZY ) )
+ if( DEFAULT_VERY_LAZY <= 1 + info->lastRow - info->firstRow ) {
+ if( post ){
+ tmp_ttcap->flags |= TTCAP_IS_VERY_LAZY;
+ }
+ }
+#endif
+ /* We should always reset. */
+ tmp_ttcap->flags &= ~TTCAP_DISABLE_DEFAULT_VERY_LAZY;
+
+ if ( face->bitmap || actual_spacing == FT_CHARCELL )
+ tmp_ttcap->flags &= ~TTCAP_IS_VERY_LAZY;
+ /* "vl=y" is available when TrueType or OpenType only */
+ if ( !face->bitmap && !(FT_IS_SFNT( face->face )) )
+ tmp_ttcap->flags &= ~TTCAP_IS_VERY_LAZY;
+
+ if( post ) {
+ if( post->italicAngle != 0 )
+ tmp_ttcap->vl_slant = -sin( (post->italicAngle/1024./5760.)*1.57079632679489661923 );
+ /* fprintf(stderr,"angle=%g(%g)\n",tmp_ttcap->vl_slant,(post->italicAngle/1024./5760.)*90); */
+ }
+
+ xrc = FreeTypeOpenInstance(&font->instance, face,
+ FTFileName, &trans, actual_spacing, bmfmt,
+ tmp_ttcap, load_flags );
+ return xrc;
+}
+
+static void
+adjust_min_max(xCharInfo *minc, xCharInfo *maxc, xCharInfo *tmp)
+{
+#define MINMAX(field,ci) \
+ if (minc->field > (ci)->field) \
+ minc->field = (ci)->field; \
+ if (maxc->field < (ci)->field) \
+ maxc->field = (ci)->field;
+
+ MINMAX(ascent, tmp);
+ MINMAX(descent, tmp);
+ MINMAX(leftSideBearing, tmp);
+ MINMAX(rightSideBearing, tmp);
+ MINMAX(characterWidth, tmp);
+
+ if ((INT16)minc->attributes > (INT16)tmp->attributes)
+ minc->attributes = tmp->attributes;
+ if ((INT16)maxc->attributes < (INT16)tmp->attributes)
+ maxc->attributes = tmp->attributes;
+#undef MINMAX
+}
+
+static void
+ft_compute_bounds(FTFontPtr font, FontInfoPtr pinfo, FontScalablePtr vals )
+{
+ FTInstancePtr instance;
+ int row, col;
+ unsigned int c;
+ xCharInfo minchar, maxchar, *tmpchar = NULL;
+ int overlap, maxOverlap;
+ long swidth = 0;
+ long total_width = 0;
+ int num_cols, num_chars = 0;
+ int flags, skip_ok = 0;
+ int force_c_outside ;
+
+ instance = font->instance;
+ force_c_outside = instance->ttcap.flags & TTCAP_FORCE_C_OUTSIDE;
+
+ minchar.ascent = minchar.descent =
+ minchar.leftSideBearing = minchar.rightSideBearing =
+ minchar.characterWidth = minchar.attributes = 32767;
+ maxchar.ascent = maxchar.descent =
+ maxchar.leftSideBearing = maxchar.rightSideBearing =
+ maxchar.characterWidth = maxchar.attributes = -32767;
+ maxOverlap = -32767;
+
+ /* Parse all glyphs */
+ num_cols = 1 + pinfo->lastCol - pinfo->firstCol;
+ for (row = pinfo->firstRow; row <= pinfo->lastRow; row++) {
+ if ( skip_ok && tmpchar ) {
+ if ( !force_c_outside ) {
+ if ( instance->ttcap.forceConstantSpacingBegin < row<<8
+ && row<<8 < (instance->ttcap.forceConstantSpacingEnd & 0x0ff00) ) {
+ if (tmpchar->characterWidth) {
+ num_chars += num_cols;
+ swidth += ABS(tmpchar->characterWidth)*num_cols;
+ total_width += tmpchar->characterWidth*num_cols;
+ continue;
+ }
+ }
+ else skip_ok=0;
+ }
+ else { /* for GB18030 proportional */
+ if ( instance->ttcap.forceConstantSpacingBegin < row<<8
+ || row<<8 < (instance->ttcap.forceConstantSpacingEnd & 0x0ff00) ) {
+ if (tmpchar->characterWidth) {
+ num_chars += num_cols;
+ swidth += ABS(tmpchar->characterWidth)*num_cols;
+ total_width += tmpchar->characterWidth*num_cols;
+ continue;
+ }
+ }
+ else skip_ok=0;
+ }
+ }
+ for (col = pinfo->firstCol; col <= pinfo->lastCol; col++) {
+ c = row<<8|col;
+ flags=0;
+ if ( !force_c_outside ) {
+ if ( c <= instance->ttcap.forceConstantSpacingEnd
+ && instance->ttcap.forceConstantSpacingBegin <= c )
+ flags|=FT_FORCE_CONSTANT_SPACING;
+ }
+ else { /* for GB18030 proportional */
+ if ( c <= instance->ttcap.forceConstantSpacingEnd
+ || instance->ttcap.forceConstantSpacingBegin <= c )
+ flags|=FT_FORCE_CONSTANT_SPACING;
+ }
+#if 0
+ fprintf(stderr, "comp_bounds: %x ->", c);
+#endif
+ if ( skip_ok == 0 || flags == 0 ){
+ tmpchar=NULL;
+#if 0
+ fprintf(stderr, "%x\n", c);
+#endif
+ if( FreeTypeFontGetGlyphMetrics(c, flags, &tmpchar, font) != Successful )
+ continue;
+ }
+ if ( !tmpchar ) continue;
+ adjust_min_max(&minchar, &maxchar, tmpchar);
+ overlap = tmpchar->rightSideBearing - tmpchar->characterWidth;
+ if (maxOverlap < overlap)
+ maxOverlap = overlap;
+
+ if (!tmpchar->characterWidth)
+ continue;
+ num_chars++;
+ swidth += ABS(tmpchar->characterWidth);
+ total_width += tmpchar->characterWidth;
+
+ if ( flags & FT_FORCE_CONSTANT_SPACING ) skip_ok=1;
+ }
+ }
+
+#ifndef X_ACCEPTS_NO_SUCH_CHAR
+ /* Check code 0 */
+ if( FreeTypeInstanceGetGlyphMetrics(font->zero_idx, 0, &tmpchar, font->instance) != Successful || tmpchar == NULL)
+ if( FreeTypeInstanceGetGlyphMetrics(font->zero_idx, FT_GET_DUMMY, &tmpchar, font->instance) != Successful )
+ tmpchar = NULL;
+ if ( tmpchar ) {
+ adjust_min_max(&minchar, &maxchar, tmpchar);
+ overlap = tmpchar->rightSideBearing - tmpchar->characterWidth;
+ if (maxOverlap < overlap)
+ maxOverlap = overlap;
+ }
+#endif
+
+ /* AVERAGE_WIDTH ... 1/10 pixel unit */
+ if (num_chars > 0) {
+ swidth = (swidth * 10.0 + num_chars / 2.0) / num_chars;
+ if (total_width < 0)
+ swidth = -swidth;
+ vals->width = swidth;
+ } else
+ vals->width = 0;
+
+ /*
+ if (char_width.pixel) {
+ maxchar.characterWidth = char_width.pixel;
+ minchar.characterWidth = char_width.pixel;
+ }
+ */
+
+ pinfo->maxbounds = maxchar;
+ pinfo->minbounds = minchar;
+ pinfo->ink_maxbounds = maxchar;
+ pinfo->ink_minbounds = minchar;
+ pinfo->maxOverlap = maxOverlap;
+}
+
+static int
+compute_new_extents( FontScalablePtr vals, double scale, double lsb, double rsb, double desc, double asc,
+ int *lsb_result, int *rsb_result, int *desc_result, int *asc_result )
+{
+#define TRANSFORM_POINT(matrix, x, y, dest) \
+ ((dest)[0] = (matrix)[0] * (x) + (matrix)[2] * (y), \
+ (dest)[1] = (matrix)[1] * (x) + (matrix)[3] * (y))
+
+#define CHECK_EXTENT(lsb, rsb, desc, asc, data) \
+ ((lsb) > (data)[0] ? (lsb) = (data)[0] : 0 , \
+ (rsb) < (data)[0] ? (rsb) = (data)[0] : 0, \
+ (-desc) > (data)[1] ? (desc) = -(data)[1] : 0 , \
+ (asc) < (data)[1] ? (asc) = (data)[1] : 0)
+ double newlsb, newrsb, newdesc, newasc;
+ double point[2];
+
+ /* Compute new extents for this glyph */
+ TRANSFORM_POINT(vals->pixel_matrix, lsb, -desc, point);
+ newlsb = point[0];
+ newrsb = newlsb;
+ newdesc = -point[1];
+ newasc = -newdesc;
+ TRANSFORM_POINT(vals->pixel_matrix, lsb, asc, point);
+ CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
+ TRANSFORM_POINT(vals->pixel_matrix, rsb, -desc, point);
+ CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
+ TRANSFORM_POINT(vals->pixel_matrix, rsb, asc, point);
+ CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
+
+ /* ???: lsb = (int)floor(newlsb * scale); */
+ *lsb_result = (int)floor(newlsb * scale + 0.5);
+ *rsb_result = (int)floor(newrsb * scale + 0.5);
+ *desc_result = (int)ceil(newdesc * scale - 0.5);
+ *asc_result = (int)floor(newasc * scale + 0.5);
+
+ return 0;
+#undef CHECK_EXTENT
+#undef TRANSFORM_POINT
+}
+
+static int
+is_matrix_unit(FontScalablePtr vals)
+{
+ double base_size;
+ FT_Matrix m;
+
+ base_size = hypot(vals->point_matrix[2], vals->point_matrix[3]);
+
+ m.xx = vals->point_matrix[0] / base_size * 65536;
+ m.xy = vals->point_matrix[2] / base_size * 65536;
+ m.yx = vals->point_matrix[1] / base_size * 65536;
+ m.yy = vals->point_matrix[3] / base_size * 65536;
+
+ return (m.xx == 65536) && (m.yx == 0) &&
+ (m.xy == 0) && (m.yy == 65536);
+}
+
+/* Do all the real work for OpenFont or FontInfo */
+/* xf->info is only accessed through info, and xf might be null */
+
+static int
+FreeTypeLoadXFont(char *fileName,
+ FontScalablePtr vals, FontPtr xf, FontInfoPtr info,
+ FontBitmapFormatPtr bmfmt, FontEntryPtr entry)
+{
+ FTFontPtr font = NULL;
+ FTFacePtr face = NULL;
+ FTInstancePtr instance;
+ FT_Size_Metrics *smetrics;
+ int xrc=Successful;
+ int charcell;
+ long rawWidth = 0, rawAverageWidth = 0;
+ int upm, minLsb, maxRsb, ascent, descent, width, averageWidth;
+ double scale, base_width, base_height;
+ Bool orig_is_matrix_unit, font_properties;
+ int face_number, ttcap_spacing;
+ struct TTCapInfo tmp_ttcap;
+ struct TTCapInfo *ins_ttcap;
+ FT_Int32 load_flags = FT_LOAD_DEFAULT; /* orig: FT_LOAD_RENDER | FT_LOAD_MONOCHROME */
+ char *dynStrRealFileName = NULL; /* foo.ttc */
+ char *dynStrFTFileName = NULL; /* :1:foo.ttc */
+ char *dynStrTTCapCodeRange = NULL;
+
+ font = calloc(1, sizeof(FTFontRec));
+ if(font == NULL) {
+ xrc = AllocError;
+ goto quit;
+ }
+
+ xrc = FreeTypeSetUpTTCap(fileName, vals,
+ &dynStrRealFileName, &dynStrFTFileName,
+ &tmp_ttcap, &face_number,
+ &load_flags, &ttcap_spacing,
+ &font_properties, &dynStrTTCapCodeRange);
+ if ( xrc != Successful ) {
+ goto quit;
+ }
+
+ xrc = FreeTypeOpenFace(&face, dynStrFTFileName, dynStrRealFileName, face_number);
+ if(xrc != Successful) {
+ goto quit;
+ }
+
+ if( is_matrix_unit(vals) )
+ orig_is_matrix_unit = True;
+ else {
+ orig_is_matrix_unit = False;
+ /* Turn off EmbeddedBitmap when original matrix is not diagonal. */
+ load_flags |= FT_LOAD_NO_BITMAP;
+ }
+
+ if( face->bitmap ) load_flags &= ~FT_LOAD_NO_BITMAP;
+
+ /* Slant control by TTCap */
+ if(!face->bitmap) {
+ vals->pixel_matrix[2] +=
+ vals->pixel_matrix[0] * tmp_ttcap.autoItalic;
+ vals->point_matrix[2] +=
+ vals->point_matrix[0] * tmp_ttcap.autoItalic;
+ vals->pixel_matrix[3] +=
+ vals->pixel_matrix[1] * tmp_ttcap.autoItalic;
+ vals->point_matrix[3] +=
+ vals->point_matrix[1] * tmp_ttcap.autoItalic;
+ }
+
+ base_width=hypot(vals->pixel_matrix[0], vals->pixel_matrix[1]);
+ base_height=hypot(vals->pixel_matrix[2], vals->pixel_matrix[3]);
+ if(MAX(base_width, base_height) < 1.0 ) {
+ xrc = BadFontName;
+ goto quit;
+ }
+
+ xrc = FreeTypeLoadFont(font, info, face, dynStrFTFileName, vals, entry, bmfmt,
+ load_flags, &tmp_ttcap, dynStrTTCapCodeRange,
+ ttcap_spacing );
+ if(xrc != Successful) {
+ goto quit;
+ }
+
+ instance = font->instance;
+ smetrics = &instance->size->metrics;
+ ins_ttcap = &instance->ttcap;
+
+ upm = face->face->units_per_EM;
+ if(upm == 0) {
+ /* Work around FreeType bug */
+ upm = WORK_AROUND_UPM;
+ }
+ scale = 1.0 / upm;
+
+ charcell = (instance->spacing == FT_CHARCELL);
+
+ if( instance->charcellMetrics == NULL ) {
+
+ /* New instance */
+
+ long force_c_rawWidth = 0;
+ int force_c_lsb,force_c_rsb,force_c_width;
+ double unit_x=0,unit_y=0,advance;
+ CharInfoPtr tmpglyph;
+
+ /*
+ * CALCULATE HEADER'S METRICS
+ */
+
+ /* for OUTLINE fonts */
+ if(!face->bitmap) {
+ int new_width;
+ double ratio,force_c_ratio;
+ double width_x=0,width_y=0;
+ double force_c_width_x, force_c_rsb_x, force_c_lsb_x;
+ double tmp_rsb,tmp_lsb,tmp_asc,tmp_des;
+ double max_advance_height;
+ tmp_asc = face->face->bbox.yMax;
+ tmp_des = -(face->face->bbox.yMin);
+ if ( tmp_asc < face->face->ascender ) tmp_asc = face->face->ascender;
+ if ( tmp_des < -(face->face->descender) ) tmp_des = -(face->face->descender);
+ tmp_lsb = face->face->bbox.xMin;
+ tmp_rsb = face->face->bbox.xMax;
+ if ( tmp_rsb < face->face->max_advance_width ) tmp_rsb = face->face->max_advance_width;
+ /* apply scaleBBoxWidth */
+ /* we should not ...??? */
+ tmp_lsb *= ins_ttcap->scaleBBoxWidth;
+ tmp_rsb *= ins_ttcap->scaleBBoxWidth;
+ /* transform and rescale */
+ compute_new_extents( vals, scale, tmp_lsb, tmp_rsb, tmp_des, tmp_asc,
+ &minLsb, &maxRsb, &descent, &ascent );
+ /* */
+ /* Consider vertical layouts */
+ if( 0 < face->face->max_advance_height )
+ max_advance_height = face->face->max_advance_height;
+ else
+ max_advance_height = tmp_asc + tmp_des;
+ if( vals->pixel_matrix[1] == 0 ){
+ unit_x = fabs(vals->pixel_matrix[0]);
+ unit_y = 0;
+ width_x = face->face->max_advance_width * ins_ttcap->scaleBBoxWidth * unit_x;
+ }
+ else if( vals->pixel_matrix[3] == 0 ){
+ unit_y = fabs(vals->pixel_matrix[2]);
+ unit_x = 0;
+ width_x = max_advance_height * ins_ttcap->scaleBBoxHeight * unit_y;
+ }
+ else{
+ unit_x = fabs(vals->pixel_matrix[0] -
+ vals->pixel_matrix[1]*vals->pixel_matrix[2]/vals->pixel_matrix[3]);
+ unit_y = fabs(vals->pixel_matrix[2] -
+ vals->pixel_matrix[3]*vals->pixel_matrix[0]/vals->pixel_matrix[1]);
+ width_x = face->face->max_advance_width * ins_ttcap->scaleBBoxWidth * unit_x;
+ width_y = max_advance_height * ins_ttcap->scaleBBoxHeight * unit_y;
+ if( width_y < width_x ){
+ width_x = width_y;
+ unit_x = 0;
+ }
+ else{
+ unit_y = 0;
+ }
+ }
+ /* calculate correction ratio */
+ width = (int)floor( (advance = width_x * scale) + 0.5);
+ new_width = width;
+ if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH )
+ new_width += ins_ttcap->doubleStrikeShift;
+ new_width += ins_ttcap->adjustBBoxWidthByPixel;
+ ratio = (double)new_width/width;
+ width = new_width;
+ /* force constant */
+ if( unit_x != 0 ) {
+ force_c_width_x = face->face->max_advance_width
+ * ins_ttcap->force_c_scale_b_box_width * unit_x;
+ force_c_lsb_x = face->face->max_advance_width
+ * ins_ttcap->force_c_scale_lsb * unit_x;
+ force_c_rsb_x = face->face->max_advance_width
+ * ins_ttcap->force_c_scale_rsb * unit_x;
+ }
+ else {
+ force_c_width_x = max_advance_height
+ * ins_ttcap->force_c_scale_b_box_height * unit_y;
+ force_c_lsb_x = max_advance_height
+ * ins_ttcap->force_c_scale_lsb * unit_y;
+ force_c_rsb_x = max_advance_height
+ * ins_ttcap->force_c_scale_rsb * unit_y;
+ }
+ /* calculate correction ratio */
+ force_c_width = (int)floor(force_c_width_x * scale + 0.5);
+ new_width = force_c_width;
+ if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH )
+ force_c_width += ins_ttcap->doubleStrikeShift;
+ new_width += ins_ttcap->force_c_adjust_width_by_pixel;
+ force_c_ratio = (double)new_width/force_c_width;
+ force_c_width = new_width;
+ /* force_c_lsb, force_c_rsb */
+ if( ins_ttcap->flags & TTCAP_FORCE_C_LSB_FLAG )
+ force_c_lsb = (int)floor( force_c_lsb_x * scale + 0.5 );
+ else
+ force_c_lsb = minLsb;
+ if( ins_ttcap->flags & TTCAP_FORCE_C_RSB_FLAG )
+ force_c_rsb = (int)floor( force_c_rsb_x * scale + 0.5 );
+ else
+ force_c_rsb = maxRsb;
+ /* calculate shift of BitmapAutoItalic
+ (when diagonal matrix only) */
+ if( orig_is_matrix_unit == True ) {
+ if( ins_ttcap->autoItalic != 0 ) {
+ double ai;
+ int ai_lsb,ai_rsb,ai_total;
+ if( 0 < ins_ttcap->autoItalic ) ai=ins_ttcap->autoItalic;
+ else ai = -ins_ttcap->autoItalic;
+ ai_total = (int)( (ascent+descent) * ai + 0.5);
+ ai_rsb = (int)((double)ai_total * ascent / ( ascent + descent ) + 0.5 );
+ ai_lsb = -(ai_total - ai_rsb);
+ if( 0 < ins_ttcap->autoItalic ) {
+ ins_ttcap->lsbShiftOfBitmapAutoItalic = ai_lsb;
+ ins_ttcap->rsbShiftOfBitmapAutoItalic = ai_rsb;
+ }
+ else {
+ ins_ttcap->lsbShiftOfBitmapAutoItalic = -ai_rsb;
+ ins_ttcap->rsbShiftOfBitmapAutoItalic = -ai_lsb;
+ }
+ }
+ }
+ /* integer adjustment by TTCap */
+ if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE )
+ maxRsb += ins_ttcap->doubleStrikeShift;
+ maxRsb += ins_ttcap->adjustRightSideBearingByPixel;
+ minLsb += ins_ttcap->adjustLeftSideBearingByPixel;
+ /* */
+ if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE )
+ force_c_rsb += ins_ttcap->doubleStrikeShift;
+ force_c_rsb += ins_ttcap->force_c_adjust_rsb_by_pixel;
+ force_c_lsb += ins_ttcap->force_c_adjust_lsb_by_pixel;
+ /* apply to rawWidth */
+ averageWidth = (int)floor(10 * width_x * scale
+ * ratio + 0.5);
+ rawWidth = floor(width_x * scale
+ * ratio * 1000. / base_height + 0.5);
+ rawAverageWidth = floor(width_x * scale * ratio * 10.
+ * 1000. / base_height + 0.5);
+ force_c_rawWidth = floor(force_c_width_x * scale
+ * force_c_ratio * 1000. / base_height + 0.5);
+ /* */
+ }
+ /* for BITMAP fonts [if(face->bitmap)] */
+ else {
+ /* These values differ from actual when outline,
+ so we must use them ONLY FOR BITMAP. */
+ width = (int)floor(smetrics->max_advance * ins_ttcap->scaleBBoxWidth / 64.0 + .5);
+ descent = -smetrics->descender / 64;
+ ascent = smetrics->ascender / 64;
+ /* force constant */
+ force_c_width = (int)floor(smetrics->max_advance
+ * ins_ttcap->force_c_scale_b_box_width / 64.0 + .5);
+ /* Preserve average width for bitmap fonts */
+ if(vals->width != 0)
+ averageWidth = (int)floor(vals->width * ins_ttcap->scaleBBoxWidth +.5);
+ else
+ averageWidth = (int)floor(10.0 * smetrics->max_advance
+ * ins_ttcap->scaleBBoxWidth / 64.0 + .5);
+ rawWidth = 0;
+ rawAverageWidth = 0;
+ force_c_rawWidth = 0;
+ /* We don't consider vertical layouts */
+ advance = (int)floor(smetrics->max_advance / 64.0 +.5);
+ unit_x = vals->pixel_matrix[0];
+ unit_y = 0;
+ /* We can use 'width' only when bitmap.
+ This should not be set when outline. */
+ minLsb = 0;
+ maxRsb = width;
+ /* force constant */
+ if( ins_ttcap->flags & TTCAP_FORCE_C_LSB_FLAG )
+ force_c_lsb = (int)floor(smetrics->max_advance
+ * ins_ttcap->force_c_scale_lsb / 64.0 + .5);
+ else
+ force_c_lsb = minLsb;
+ if( ins_ttcap->flags & TTCAP_FORCE_C_RSB_FLAG )
+ force_c_rsb = (int)floor(smetrics->max_advance
+ * ins_ttcap->force_c_scale_rsb / 64.0 + .5);
+ else
+ force_c_rsb = maxRsb;
+ /* calculate shift of BitmapAutoItalic */
+ if( ins_ttcap->autoItalic != 0 ) {
+ double ai;
+ int ai_lsb,ai_rsb,ai_total;
+ if( 0 < ins_ttcap->autoItalic ) ai=ins_ttcap->autoItalic;
+ else ai = -ins_ttcap->autoItalic;
+ ai_total = (int)( (ascent+descent) * ai + 0.5);
+ ai_rsb = (int)((double)ai_total * ascent / ( ascent + descent ) + 0.5 );
+ ai_lsb = -(ai_total - ai_rsb);
+ if( 0 < ins_ttcap->autoItalic ) {
+ ins_ttcap->lsbShiftOfBitmapAutoItalic = ai_lsb;
+ ins_ttcap->rsbShiftOfBitmapAutoItalic = ai_rsb;
+ }
+ else {
+ ins_ttcap->lsbShiftOfBitmapAutoItalic = -ai_rsb;
+ ins_ttcap->rsbShiftOfBitmapAutoItalic = -ai_lsb;
+ }
+ }
+ /* integer adjustment by TTCap */
+ if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH )
+ width += ins_ttcap->doubleStrikeShift;
+ if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE )
+ maxRsb += ins_ttcap->doubleStrikeShift;
+ maxRsb += ins_ttcap->adjustRightSideBearingByPixel;
+ minLsb += ins_ttcap->adjustLeftSideBearingByPixel;
+ /* We have not carried out matrix calculation, so this is done. */
+ maxRsb += ins_ttcap->rsbShiftOfBitmapAutoItalic;
+ minLsb += ins_ttcap->lsbShiftOfBitmapAutoItalic;
+ /* force constant */
+ if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE )
+ force_c_rsb += ins_ttcap->doubleStrikeShift;
+ force_c_rsb += ins_ttcap->force_c_adjust_rsb_by_pixel;
+ force_c_lsb += ins_ttcap->force_c_adjust_lsb_by_pixel;
+ force_c_rsb += ins_ttcap->rsbShiftOfBitmapAutoItalic;
+ force_c_lsb += ins_ttcap->lsbShiftOfBitmapAutoItalic;
+ }
+
+ /* SET CALCULATED VALUES TO INSTANCE */
+
+ /* Set actual height and cosine */
+ instance->pixel_size = base_height;
+ instance->advance = advance;
+ if ( unit_x != 0 ){
+ instance->pixel_width_unit_x = unit_x/base_height;
+ instance->pixel_width_unit_y = 0;
+ }
+ else{
+ instance->pixel_width_unit_x = 0;
+ instance->pixel_width_unit_y = unit_y/base_height;
+ }
+
+ /* header's metrics */
+ instance->charcellMetrics = malloc(sizeof(xCharInfo));
+ if(instance->charcellMetrics == NULL) {
+ xrc = AllocError;
+ goto quit;
+ }
+ instance->charcellMetrics->ascent = ascent;
+ instance->charcellMetrics->descent = descent;
+ instance->charcellMetrics->attributes = rawWidth;
+ instance->charcellMetrics->rightSideBearing = maxRsb;
+ instance->charcellMetrics->leftSideBearing = minLsb;
+ instance->charcellMetrics->characterWidth = width;
+ instance->averageWidth = averageWidth;
+ instance->rawAverageWidth = rawAverageWidth;
+
+ /* Check code 0 */
+ if( FreeTypeInstanceGetGlyph(font->zero_idx, 0, &tmpglyph, font->instance) != Successful
+ || tmpglyph == NULL)
+ if( FreeTypeInstanceGetGlyph(font->zero_idx, FT_GET_DUMMY, &tmpglyph, font->instance)
+ != Successful )
+ tmpglyph = NULL;
+ if ( !tmpglyph ) {
+ xrc = AllocError;
+ goto quit;
+ }
+
+ /* FORCE CONSTANT METRICS */
+ if( 0 <= ins_ttcap->forceConstantSpacingEnd ) {
+ xCharInfo *tmpchar = NULL;
+ int c = ins_ttcap->force_c_representative_metrics_char_code;
+ /* header's metrics */
+ if( instance->forceConstantMetrics == NULL ){
+ instance->forceConstantMetrics = malloc(sizeof(xCharInfo));
+ if(instance->forceConstantMetrics == NULL) {
+ xrc = AllocError;
+ goto quit;
+ }
+ }
+ /* Get Representative Metrics */
+ if ( 0 <= c ) {
+ if( FreeTypeFontGetGlyphMetrics(c, 0, &tmpchar, font) != Successful )
+ tmpchar = NULL;
+ }
+ if ( tmpchar && 0 < tmpchar->characterWidth ) {
+ instance->forceConstantMetrics->leftSideBearing = tmpchar->leftSideBearing;
+ instance->forceConstantMetrics->rightSideBearing = tmpchar->rightSideBearing;
+ instance->forceConstantMetrics->characterWidth = tmpchar->characterWidth;
+ instance->forceConstantMetrics->ascent = tmpchar->ascent;
+ instance->forceConstantMetrics->descent = tmpchar->descent;
+ instance->forceConstantMetrics->attributes = tmpchar->attributes;
+ }
+ else {
+ instance->forceConstantMetrics->leftSideBearing = force_c_lsb;
+ instance->forceConstantMetrics->rightSideBearing = force_c_rsb;
+ instance->forceConstantMetrics->characterWidth = force_c_width;
+ instance->forceConstantMetrics->ascent = ascent;
+ instance->forceConstantMetrics->descent = descent;
+ instance->forceConstantMetrics->attributes = force_c_rawWidth;
+ }
+ /* Check code 0 */
+ if( FreeTypeInstanceGetGlyph(font->zero_idx, FT_FORCE_CONSTANT_SPACING,
+ &tmpglyph, font->instance) != Successful
+ || tmpglyph == NULL)
+ if( FreeTypeInstanceGetGlyph(font->zero_idx, FT_FORCE_CONSTANT_SPACING | FT_GET_DUMMY,
+ &tmpglyph, font->instance)
+ != Successful )
+ tmpglyph = NULL;
+ if ( !tmpglyph ) {
+ xrc = AllocError;
+ goto quit;
+ }
+ }
+ }
+ else{
+
+ /*
+ * CACHED VALUES
+ */
+
+ width = instance->charcellMetrics->characterWidth;
+ ascent = instance->charcellMetrics->ascent;
+ descent = instance->charcellMetrics->descent;
+ rawWidth = instance->charcellMetrics->attributes;
+ maxRsb = instance->charcellMetrics->rightSideBearing;
+ minLsb = instance->charcellMetrics->leftSideBearing;
+ averageWidth = instance->averageWidth;
+ rawAverageWidth = instance->rawAverageWidth;
+
+ }
+
+ /*
+ * SET maxbounds, minbounds ...
+ */
+
+ if( !charcell ) { /* NOT CHARCELL */
+ if( info ){
+ /*
+ Calculate all glyphs' metrics.
+ maxbounds.ascent and maxbounds.descent are quite important values
+ for XAA. If ascent/descent of each glyph exceeds
+ maxbounds.ascent/maxbounds.descent, XAA causes SERVER CRASH.
+ Therefore, THIS MUST BE DONE.
+ */
+ ft_compute_bounds(font,info,vals);
+ }
+ }
+ else{ /* CHARCELL */
+
+ /*
+ * SET CALCULATED OR CACHED VARIABLES
+ */
+
+ vals->width = averageWidth;
+
+ if( info ){
+
+ info->maxbounds.leftSideBearing = minLsb;
+ info->maxbounds.rightSideBearing = maxRsb;
+ info->maxbounds.characterWidth = width;
+ info->maxbounds.ascent = ascent;
+ info->maxbounds.descent = descent;
+ info->maxbounds.attributes =
+ (unsigned short)(short)rawWidth;
+
+ info->minbounds = info->maxbounds;
+ }
+ }
+
+ /* set info */
+
+ if( info ){
+ /*
+ info->fontAscent = ascent;
+ info->fontDescent = descent;
+ */
+ info->fontAscent = info->maxbounds.ascent;
+ info->fontDescent = info->maxbounds.descent;
+ /* Glyph metrics are accurate */
+ info->inkMetrics=1;
+
+ memcpy((char *)&info->ink_maxbounds,
+ (char *)&info->maxbounds, sizeof(xCharInfo));
+ memcpy((char *)&info->ink_minbounds,
+ (char *)&info->minbounds, sizeof(xCharInfo));
+
+ /* XXX - hack */
+ info->defaultCh=0;
+
+ /* Set the pInfo flags */
+ /* Properties set by FontComputeInfoAccelerators:
+ pInfo->noOverlap;
+ pInfo->terminalFont;
+ pInfo->constantMetrics;
+ pInfo->constantWidth;
+ pInfo->inkInside;
+ */
+ /* from lib/font/util/fontaccel.c */
+ FontComputeInfoAccelerators(info);
+ }
+
+ if(xf)
+ xf->fontPrivate = (void*)font;
+
+ if(info) {
+ xrc = FreeTypeAddProperties(font, vals, info, entry->name.name,
+ rawAverageWidth, font_properties);
+ if (xrc != Successful) {
+ goto quit;
+ }
+ }
+
+ quit:
+ if ( dynStrTTCapCodeRange ) free(dynStrTTCapCodeRange);
+ if ( dynStrFTFileName ) free(dynStrFTFileName);
+ if ( dynStrRealFileName ) free(dynStrRealFileName);
+ if ( xrc != Successful ) {
+ if( font ){
+ if( face && font->instance == NULL ) FreeTypeFreeFace(face);
+ FreeTypeFreeFont(font);
+ }
+ }
+ return xrc;
+}
+
+/* Routines used by X11 to get info and glyphs from the font. */
+
+static int
+FreeTypeGetMetrics(FontPtr pFont, unsigned long count, unsigned char *chars,
+ FontEncoding charEncoding, unsigned long *metricCount,
+ xCharInfo **metrics)
+{
+ unsigned int code = 0;
+ int flags = 0;
+ FTFontPtr tf;
+ struct TTCapInfo *ttcap;
+ xCharInfo **mp, *m;
+
+ /* MUMBLE("Get metrics for %ld characters\n", count);*/
+
+ tf = (FTFontPtr)pFont->fontPrivate;
+ ttcap = &tf->instance->ttcap;
+ mp = metrics;
+
+ while (count-- > 0) {
+ switch (charEncoding) {
+ case Linear8Bit:
+ case TwoD8Bit:
+ code = *chars++;
+ break;
+ case Linear16Bit:
+ case TwoD16Bit:
+ code = (*chars++ << 8);
+ code |= *chars++;
+ /* */
+ if ( !(ttcap->flags & TTCAP_FORCE_C_OUTSIDE) ) {
+ if ( (int)code <= ttcap->forceConstantSpacingEnd
+ && ttcap->forceConstantSpacingBegin <= (int)code )
+ flags|=FT_FORCE_CONSTANT_SPACING;
+ else flags=0;
+ }
+ else { /* for GB18030 proportional */
+ if ( (int)code <= ttcap->forceConstantSpacingEnd
+ || ttcap->forceConstantSpacingBegin <= (int)code )
+ flags|=FT_FORCE_CONSTANT_SPACING;
+ else flags=0;
+ }
+ break;
+ }
+
+ if(FreeTypeFontGetGlyphMetrics(code, flags, &m, tf) == Successful && m!=NULL) {
+ *mp++ = m;
+ }
+#ifdef X_ACCEPTS_NO_SUCH_CHAR
+ else *mp++ = &noSuchChar.metrics;
+#endif
+ }
+
+ *metricCount = mp - metrics;
+ return Successful;
+}
+
+static int
+FreeTypeGetGlyphs(FontPtr pFont, unsigned long count, unsigned char *chars,
+ FontEncoding charEncoding, unsigned long *glyphCount,
+ CharInfoPtr *glyphs)
+{
+ unsigned int code = 0;
+ int flags = 0;
+ FTFontPtr tf;
+ CharInfoPtr *gp;
+ CharInfoPtr g;
+ struct TTCapInfo *ttcap;
+
+ tf = (FTFontPtr)pFont->fontPrivate;
+ ttcap = &tf->instance->ttcap;
+ gp = glyphs;
+
+ while (count-- > 0) {
+ switch (charEncoding) {
+ case Linear8Bit: case TwoD8Bit:
+ code = *chars++;
+ break;
+ case Linear16Bit: case TwoD16Bit:
+ code = *chars++ << 8;
+ code |= *chars++;
+ /* */
+ if ( !(ttcap->flags & TTCAP_FORCE_C_OUTSIDE) ) {
+ if ( (int)code <= ttcap->forceConstantSpacingEnd
+ && ttcap->forceConstantSpacingBegin <= (int)code )
+ flags|=FT_FORCE_CONSTANT_SPACING;
+ else flags=0;
+ }
+ else { /* for GB18030 proportional */
+ if ( (int)code <= ttcap->forceConstantSpacingEnd
+ || ttcap->forceConstantSpacingBegin <= (int)code )
+ flags|=FT_FORCE_CONSTANT_SPACING;
+ else flags=0;
+ }
+ break;
+ }
+
+ if(FreeTypeFontGetGlyph(code, flags, &g, tf) == Successful && g!=NULL) {
+ *gp++ = g;
+ }
+#ifdef X_ACCEPTS_NO_SUCH_CHAR
+ else {
+#ifdef XAA_ACCEPTS_NULL_BITS
+ *gp++ = &noSuchChar;
+#else
+ if ( tf->dummy_char.bits ) {
+ *gp++ = &tf->dummy_char;
+ }
+ else {
+ char *raster = NULL;
+ int wd_actual, ht_actual, wd, ht, bpr;
+ wd_actual = tf->info->maxbounds.rightSideBearing - tf->info->maxbounds.leftSideBearing;
+ ht_actual = tf->info->maxbounds.ascent + tf->info->maxbounds.descent;
+ if(wd_actual <= 0) wd = 1;
+ else wd=wd_actual;
+ if(ht_actual <= 0) ht = 1;
+ else ht=ht_actual;
+ bpr = (((wd + (tf->instance->bmfmt.glyph<<3) - 1) >> 3) &
+ -tf->instance->bmfmt.glyph);
+ raster = calloc(1, ht * bpr);
+ if(raster) {
+ tf->dummy_char.bits = raster;
+ *gp++ = &tf->dummy_char;
+ }
+ }
+#endif
+ }
+#endif
+ }
+
+ *glyphCount = gp - glyphs;
+ return Successful;
+}
+
+static int
+FreeTypeSetUpFont(FontPathElementPtr fpe, FontPtr xf, FontInfoPtr info,
+ fsBitmapFormat format, fsBitmapFormatMask fmask,
+ FontBitmapFormatPtr bmfmt)
+{
+ int xrc;
+ int image;
+
+ /* Get the default bitmap format information for this X installation.
+ Also update it for the client if running in the font server. */
+ FontDefaultFormat(&bmfmt->bit, &bmfmt->byte, &bmfmt->glyph, &bmfmt->scan);
+ if ((xrc = CheckFSFormat(format, fmask, &bmfmt->bit, &bmfmt->byte,
+ &bmfmt->scan, &bmfmt->glyph,
+ &image)) != Successful) {
+ MUMBLE("Aborting after checking FS format: %d\n", xrc);
+ return xrc;
+ }
+
+ if(xf) {
+ xf->refcnt = 0;
+ xf->bit = bmfmt->bit;
+ xf->byte = bmfmt->byte;
+ xf->glyph = bmfmt->glyph;
+ xf->scan = bmfmt->scan;
+ xf->format = format;
+ xf->get_glyphs = FreeTypeGetGlyphs;
+ xf->get_metrics = FreeTypeGetMetrics;
+ xf->unload_font = FreeTypeUnloadXFont;
+ xf->unload_glyphs = 0;
+ xf->fpe = fpe;
+ xf->svrPrivate = 0;
+ xf->fontPrivate = 0; /* we'll set it later */
+ xf->fpePrivate = 0;
+ }
+
+ info->defaultCh = 0;
+ info->noOverlap = 0; /* not updated */
+ info->terminalFont = 0; /* not updated */
+ info->constantMetrics = 0; /* we'll set it later */
+ info->constantWidth = 0; /* we'll set it later */
+ info->inkInside = 1;
+ info->inkMetrics = 1;
+ info->allExist=0; /* not updated */
+ info->drawDirection = LeftToRight; /* we'll set it later */
+ info->cachable = 1; /* we don't do licensing */
+ info->anamorphic = 0; /* can hinting lead to anamorphic scaling? */
+ info->maxOverlap = 0; /* we'll set it later. */
+ info->pad = 0; /* ??? */
+ return Successful;
+}
+
+/* Functions exported by the backend */
+
+static int
+FreeTypeOpenScalable(FontPathElementPtr fpe, FontPtr *ppFont, int flags,
+ FontEntryPtr entry, char *fileName, FontScalablePtr vals,
+ fsBitmapFormat format, fsBitmapFormatMask fmask,
+ FontPtr non_cachable_font)
+{
+ int xrc;
+ FontPtr xf;
+ FontBitmapFormatRec bmfmt;
+
+ MUMBLE("Open Scalable %s, XLFD=%s\n",fileName, entry->name.length ? entry->name.name : "");
+
+ xf = CreateFontRec();
+ if (xf == NULL)
+ return AllocError;
+
+ xrc = FreeTypeSetUpFont(fpe, xf, &xf->info, format, fmask, &bmfmt);
+ if(xrc != Successful) {
+ DestroyFontRec(xf);
+ return xrc;
+ }
+ xrc = FreeTypeLoadXFont(fileName, vals, xf, &xf->info, &bmfmt, entry);
+ if(xrc != Successful) {
+ MUMBLE("Error during load: %d\n",xrc);
+ DestroyFontRec(xf);
+ return xrc;
+ }
+
+ *ppFont = xf;
+
+ return xrc;
+}
+
+/* Routine to get requested font info. */
+
+static int
+FreeTypeGetInfoScalable(FontPathElementPtr fpe, FontInfoPtr info,
+ FontEntryPtr entry, FontNamePtr fontName,
+ char *fileName, FontScalablePtr vals)
+{
+ int xrc;
+ FontBitmapFormatRec bmfmt;
+
+ MUMBLE("Get info, XLFD=%s\n", entry->name.length ? entry->name.name : "");
+
+ xrc = FreeTypeSetUpFont(fpe, 0, info, 0, 0, &bmfmt);
+ if(xrc != Successful) {
+ return xrc;
+ }
+
+ bmfmt.glyph <<= 3;
+
+ xrc = FreeTypeLoadXFont(fileName, vals, 0, info, &bmfmt, entry);
+ if(xrc != Successful) {
+ MUMBLE("Error during load: %d\n", xrc);
+ return xrc;
+ }
+
+ return Successful;
+}
+
+/* Renderer registration. */
+
+/* Set the capabilities of this renderer. */
+#define CAPABILITIES (CAP_CHARSUBSETTING | CAP_MATRIX)
+
+/* Set it up so file names with either upper or lower case can be
+ loaded. We don't support compressed fonts. */
+static FontRendererRec renderers[] = {
+ {".ttf", 4, 0, FreeTypeOpenScalable, 0,
+ FreeTypeGetInfoScalable, 0, CAPABILITIES},
+ {".ttc", 4, 0, FreeTypeOpenScalable, 0,
+ FreeTypeGetInfoScalable, 0, CAPABILITIES},
+ {".otf", 4, 0, FreeTypeOpenScalable, 0,
+ FreeTypeGetInfoScalable, 0, CAPABILITIES},
+ {".otc", 4, 0, FreeTypeOpenScalable, 0,
+ FreeTypeGetInfoScalable, 0, CAPABILITIES},
+ {".pfa", 4, 0, FreeTypeOpenScalable, 0,
+ FreeTypeGetInfoScalable, 0, CAPABILITIES},
+ {".pfb", 4, 0, FreeTypeOpenScalable, 0,
+ FreeTypeGetInfoScalable, 0, CAPABILITIES},
+};
+static int num_renderers = sizeof(renderers) / sizeof(renderers[0]);
+
+static FontRendererRec alt_renderers[] = {
+ {".bdf", 4, 0, FreeTypeOpenScalable, 0,
+ FreeTypeGetInfoScalable, 0, CAPABILITIES},
+ {".pcf", 4, 0, FreeTypeOpenScalable, 0,
+ FreeTypeGetInfoScalable, 0, CAPABILITIES},
+};
+
+static int num_alt_renderers =
+sizeof(alt_renderers) / sizeof(alt_renderers[0]);
+
+
+void
+FreeTypeRegisterFontFileFunctions(void)
+{
+ int i;
+
+ for (i = 0; i < num_renderers; i++)
+ FontFileRegisterRenderer(&renderers[i]);
+
+ for (i = 0; i < num_alt_renderers; i++)
+ FontFilePriorityRegisterRenderer(&alt_renderers[i], -10);
+}
diff --git a/libXfont/src/FreeType/ftfuncs.h b/libXfont/src/FreeType/ftfuncs.h index 068a59523..a39271e1c 100644 --- a/libXfont/src/FreeType/ftfuncs.h +++ b/libXfont/src/FreeType/ftfuncs.h @@ -1,189 +1,189 @@ -/* -Copyright (c) 1998-2002 by Juliusz Chroboczek -Copyright (c) 2003 After X-TT Project, All rights reserved. - -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. -*/ - -/* Number of buckets in the hashtable holding faces */ -#define NUMFACEBUCKETS 32 - -/* Glyphs are held in segments of this size */ -#define FONTSEGMENTSIZE 16 - -/* A structure that holds bitmap order and padding info. */ - -typedef struct { - int bit; /* bit order */ - int byte; /* byte order */ - int glyph; /* glyph pad size */ - int scan; /* machine word size */ -} FontBitmapFormatRec, *FontBitmapFormatPtr; - -struct FTSize_s; - -/* At the lowest level, there is face; FTFaces are in one-to-one - correspondence with TrueType faces. Multiple instance may share - the same face. */ - -typedef struct _FTFace { - char *filename; - FT_Face face; - int bitmap; - FT_UInt num_hmetrics; - struct _FTInstance *instances; - struct _FTInstance *active_instance; - struct _FTFace *next; /* link to next face in bucket */ -} FTFaceRec, *FTFacePtr; - -/* A transformation matrix with resolution information */ -typedef struct _FTNormalisedTransformation { - double scale; - int nonIdentity; /* if 0, matrix is the identity */ - FT_Matrix matrix; - int xres, yres; -} FTNormalisedTransformationRec, *FTNormalisedTransformationPtr; - -#define FT_PROPORTIONAL 0 -#define FT_MONOSPACED 1 -#define FT_CHARCELL 2 - -#define FT_AVAILABLE_UNKNOWN 0 -#define FT_AVAILABLE_NO 1 -#define FT_AVAILABLE_METRICS 2 -#define FT_AVAILABLE_RASTERISED 3 - -#define FT_GET_GLYPH_BOTH 0x01 -#define FT_GET_GLYPH_METRICS_ONLY 0x02 -#define FT_GET_DUMMY 0x04 -#define FT_FORCE_CONSTANT_SPACING 0x08 - -#define TTCAP_DOUBLE_STRIKE 0x0001 -#define TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT 0x0002 -#define TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH 0x0008 -#define TTCAP_IS_VERY_LAZY 0x0010 -#define TTCAP_DISABLE_DEFAULT_VERY_LAZY 0x0020 -#define TTCAP_FORCE_C_LSB_FLAG 0x0100 -#define TTCAP_FORCE_C_RSB_FLAG 0x0200 -#define TTCAP_FORCE_C_OUTSIDE 0x0400 -#define TTCAP_MONO_CENTER 0x0800 - -/* TTCap */ -struct TTCapInfo { - long flags; - double autoItalic; - double scaleWidth; - double scaleBBoxWidth; - double scaleBBoxHeight; - int doubleStrikeShift; - int adjustBBoxWidthByPixel; - int adjustLeftSideBearingByPixel; - int adjustRightSideBearingByPixel; - double scaleBitmap; - int forceConstantSpacingBegin; - int forceConstantSpacingEnd; - /* We don't compare */ - int force_c_adjust_width_by_pixel; - int force_c_adjust_lsb_by_pixel; - int force_c_adjust_rsb_by_pixel; - int force_c_representative_metrics_char_code; - double force_c_scale_b_box_width; - double force_c_scale_b_box_height; - double force_c_scale_lsb; - double force_c_scale_rsb; - double vl_slant; - int lsbShiftOfBitmapAutoItalic; - int rsbShiftOfBitmapAutoItalic; -}; - -/* An instance builds on a face by specifying the transformation - matrix. Multiple fonts may share the same instance. */ - -/* This structure caches bitmap data */ -typedef struct _FTInstance { - FTFacePtr face; /* the associated face */ - FT_Size size; - FTNormalisedTransformationRec transformation; - FT_Int32 load_flags; - FT_ULong strike_index; - int spacing; /* actual spacing */ - double pixel_size; /* to calc attributes (actual height) */ - double pixel_width_unit_x; /* to calc horiz. width (cosine) */ - double pixel_width_unit_y; /* to calc vert. width (cosine) */ - xCharInfo *charcellMetrics; /* the header's metrics */ - int averageWidth; /* the header's metrics */ - long rawAverageWidth; /* the header's metrics */ - double advance; /* the header's metrics */ - xCharInfo *forceConstantMetrics; - FontBitmapFormatRec bmfmt; - unsigned nglyphs; - CharInfoPtr *glyphs; /* glyphs and available are used in parallel */ - int **available; - struct TTCapInfo ttcap; - int refcount; - struct _FTInstance *next; /* link to next instance */ -} FTInstanceRec, *FTInstancePtr; - -/* A font is an instance with coding information; fonts are in - one-to-one correspondence with X fonts */ -typedef struct _FTFont{ - FTInstancePtr instance; - FTMappingRec mapping; - unsigned zero_idx; - FontInfoPtr info; - int nranges; - CharInfoRec dummy_char; - fsRange *ranges; -} FTFontRec, *FTFontPtr; - -#ifndef NOT_IN_FTFUNCS - -/* Prototypes for some local functions */ - -static int FreeTypeOpenFace(FTFacePtr *facep, char *FTFileName, char *realFileName, int faceNumber); -static void FreeTypeFreeFace(FTFacePtr face); -static int -FreeTypeOpenInstance(FTInstancePtr *instancep, FTFacePtr face, - char *FTFileName, FTNormalisedTransformationPtr trans, - int spacing, FontBitmapFormatPtr bmfmt, - struct TTCapInfo *tmp_ttcap, FT_Int32 load_flags); -static void FreeTypeFreeInstance(FTInstancePtr instance); -static int -FreeTypeInstanceGetGlyph(unsigned idx, int flags, CharInfoPtr *g, FTInstancePtr instance); -static int -FreeTypeInstanceGetGlyphMetrics(unsigned idx, int flags, - xCharInfo **metrics, FTInstancePtr instance ); -static int -FreeTypeRasteriseGlyph(unsigned idx, int flags, CharInfoPtr tgp, - FTInstancePtr instance, int hasMetrics ); -static void FreeTypeFreeFont(FTFontPtr font); -static void FreeTypeFreeXFont(FontPtr pFont, int freeProps); -static void FreeTypeUnloadXFont(FontPtr pFont); -static int -FreeTypeAddProperties(FTFontPtr font, FontScalablePtr vals, FontInfoPtr info, - char *fontname, int rawAverageWidth, Bool font_properties); -static int FreeTypeFontGetGlyph(unsigned code, int flags, CharInfoPtr *g, FTFontPtr font); -static int -FreeTypeLoadFont(FTFontPtr font, FontInfoPtr info, FTFacePtr face, - char *FTFileName, FontScalablePtr vals, FontEntryPtr entry, - FontBitmapFormatPtr bmfmt, FT_Int32 load_flags, - struct TTCapInfo *tmp_ttcap, char *dynStrTTCapCodeRange, - int ttcap_spacing ); - -#endif /* NOT_IN_FTFUNCS */ +/*
+Copyright (c) 1998-2002 by Juliusz Chroboczek
+Copyright (c) 2003 After X-TT Project, All rights reserved.
+
+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.
+*/
+
+/* Number of buckets in the hashtable holding faces */
+#define NUMFACEBUCKETS 32
+
+/* Glyphs are held in segments of this size */
+#define FONTSEGMENTSIZE 16
+
+/* A structure that holds bitmap order and padding info. */
+
+typedef struct {
+ int bit; /* bit order */
+ int byte; /* byte order */
+ int glyph; /* glyph pad size */
+ int scan; /* machine word size */
+} FontBitmapFormatRec, *FontBitmapFormatPtr;
+
+struct FTSize_s;
+
+/* At the lowest level, there is face; FTFaces are in one-to-one
+ correspondence with TrueType faces. Multiple instance may share
+ the same face. */
+
+typedef struct _FTFace {
+ char *filename;
+ FT_Face face;
+ int bitmap;
+ FT_UInt num_hmetrics;
+ struct _FTInstance *instances;
+ struct _FTInstance *active_instance;
+ struct _FTFace *next; /* link to next face in bucket */
+} FTFaceRec, *FTFacePtr;
+
+/* A transformation matrix with resolution information */
+typedef struct _FTNormalisedTransformation {
+ double scale;
+ int nonIdentity; /* if 0, matrix is the identity */
+ FT_Matrix matrix;
+ int xres, yres;
+} FTNormalisedTransformationRec, *FTNormalisedTransformationPtr;
+
+#define FT_PROPORTIONAL 0
+#define FT_MONOSPACED 1
+#define FT_CHARCELL 2
+
+#define FT_AVAILABLE_UNKNOWN 0
+#define FT_AVAILABLE_NO 1
+#define FT_AVAILABLE_METRICS 2
+#define FT_AVAILABLE_RASTERISED 3
+
+#define FT_GET_GLYPH_BOTH 0x01
+#define FT_GET_GLYPH_METRICS_ONLY 0x02
+#define FT_GET_DUMMY 0x04
+#define FT_FORCE_CONSTANT_SPACING 0x08
+
+#define TTCAP_DOUBLE_STRIKE 0x0001
+#define TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT 0x0002
+#define TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH 0x0008
+#define TTCAP_IS_VERY_LAZY 0x0010
+#define TTCAP_DISABLE_DEFAULT_VERY_LAZY 0x0020
+#define TTCAP_FORCE_C_LSB_FLAG 0x0100
+#define TTCAP_FORCE_C_RSB_FLAG 0x0200
+#define TTCAP_FORCE_C_OUTSIDE 0x0400
+#define TTCAP_MONO_CENTER 0x0800
+
+/* TTCap */
+struct TTCapInfo {
+ long flags;
+ double autoItalic;
+ double scaleWidth;
+ double scaleBBoxWidth;
+ double scaleBBoxHeight;
+ int doubleStrikeShift;
+ int adjustBBoxWidthByPixel;
+ int adjustLeftSideBearingByPixel;
+ int adjustRightSideBearingByPixel;
+ double scaleBitmap;
+ int forceConstantSpacingBegin;
+ int forceConstantSpacingEnd;
+ /* We don't compare */
+ int force_c_adjust_width_by_pixel;
+ int force_c_adjust_lsb_by_pixel;
+ int force_c_adjust_rsb_by_pixel;
+ int force_c_representative_metrics_char_code;
+ double force_c_scale_b_box_width;
+ double force_c_scale_b_box_height;
+ double force_c_scale_lsb;
+ double force_c_scale_rsb;
+ double vl_slant;
+ int lsbShiftOfBitmapAutoItalic;
+ int rsbShiftOfBitmapAutoItalic;
+};
+
+/* An instance builds on a face by specifying the transformation
+ matrix. Multiple fonts may share the same instance. */
+
+/* This structure caches bitmap data */
+typedef struct _FTInstance {
+ FTFacePtr face; /* the associated face */
+ FT_Size size;
+ FTNormalisedTransformationRec transformation;
+ FT_Int32 load_flags;
+ FT_ULong strike_index;
+ int spacing; /* actual spacing */
+ double pixel_size; /* to calc attributes (actual height) */
+ double pixel_width_unit_x; /* to calc horiz. width (cosine) */
+ double pixel_width_unit_y; /* to calc vert. width (cosine) */
+ xCharInfo *charcellMetrics; /* the header's metrics */
+ int averageWidth; /* the header's metrics */
+ long rawAverageWidth; /* the header's metrics */
+ double advance; /* the header's metrics */
+ xCharInfo *forceConstantMetrics;
+ FontBitmapFormatRec bmfmt;
+ unsigned nglyphs;
+ CharInfoPtr *glyphs; /* glyphs and available are used in parallel */
+ int **available;
+ struct TTCapInfo ttcap;
+ int refcount;
+ struct _FTInstance *next; /* link to next instance */
+} FTInstanceRec, *FTInstancePtr;
+
+/* A font is an instance with coding information; fonts are in
+ one-to-one correspondence with X fonts */
+typedef struct _FTFont{
+ FTInstancePtr instance;
+ FTMappingRec mapping;
+ unsigned zero_idx;
+ FontInfoPtr info;
+ int nranges;
+ CharInfoRec dummy_char;
+ fsRange *ranges;
+} FTFontRec, *FTFontPtr;
+
+#ifndef NOT_IN_FTFUNCS
+
+/* Prototypes for some local functions */
+
+static int FreeTypeOpenFace(FTFacePtr *facep, char *FTFileName, char *realFileName, int faceNumber);
+static void FreeTypeFreeFace(FTFacePtr face);
+static int
+FreeTypeOpenInstance(FTInstancePtr *instancep, FTFacePtr face,
+ char *FTFileName, FTNormalisedTransformationPtr trans,
+ int spacing, FontBitmapFormatPtr bmfmt,
+ struct TTCapInfo *tmp_ttcap, FT_Int32 load_flags);
+static void FreeTypeFreeInstance(FTInstancePtr instance);
+static int
+FreeTypeInstanceGetGlyph(unsigned idx, int flags, CharInfoPtr *g, FTInstancePtr instance);
+static int
+FreeTypeInstanceGetGlyphMetrics(unsigned idx, int flags,
+ xCharInfo **metrics, FTInstancePtr instance );
+static int
+FreeTypeRasteriseGlyph(unsigned idx, int flags, CharInfoPtr tgp,
+ FTInstancePtr instance, int hasMetrics );
+static void FreeTypeFreeFont(FTFontPtr font);
+static void FreeTypeFreeXFont(FontPtr pFont, int freeProps);
+static void FreeTypeUnloadXFont(FontPtr pFont);
+static int
+FreeTypeAddProperties(FTFontPtr font, FontScalablePtr vals, FontInfoPtr info,
+ char *fontname, int rawAverageWidth, Bool font_properties);
+static int FreeTypeFontGetGlyph(unsigned code, int flags, CharInfoPtr *g, FTFontPtr font);
+static int
+FreeTypeLoadFont(FTFontPtr font, FontInfoPtr info, FTFacePtr face,
+ char *FTFileName, FontScalablePtr vals, FontEntryPtr entry,
+ FontBitmapFormatPtr bmfmt, FT_Int32 load_flags,
+ struct TTCapInfo *tmp_ttcap, char *dynStrTTCapCodeRange,
+ int ttcap_spacing );
+
+#endif /* NOT_IN_FTFUNCS */
diff --git a/libXfont/src/FreeType/fttools.c b/libXfont/src/FreeType/fttools.c index bc75b7e4f..24e78ce24 100644 --- a/libXfont/src/FreeType/fttools.c +++ b/libXfont/src/FreeType/fttools.c @@ -1,140 +1,140 @@ -/* - Copyright (c) 1997 by Mark Leisher - Copyright (c) 1998-2002 by Juliusz Chroboczek - - 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. -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fontmisc.h> -#include <ctype.h> -#include <string.h> - -#include <X11/fonts/font.h> -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_SFNT_NAMES_H -#include FT_TRUETYPE_IDS_H -#include "ft.h" - -#ifndef LSBFirst -#define LSBFirst 0 -#define MSBFirst 1 -#endif - -#define LOBYTE(s,byte) ((byte)==LSBFirst?*(char*)(s):*((char*)(s)+1)) -#define HIBYTE(s,byte) ((byte)==LSBFirst?*((char*)(s)+1):*(char*)(s)) - -int FTtoXReturnCode(int rc) -{ - if(rc == 0x40) - return AllocError; - /* Anything else stops the font matching mechanism */ - else return BadFontName; - -} - -/* Convert slen bytes from UCS-2 to ISO 8859-1. Byte specifies the - endianness of the string, max the maximum number of bytes written into - to. */ -static int -FTu2a(int slen, FT_Byte *from, char *to, int byte, int max) -{ - int i, n; - - n = 0; - for (i = 0; i < slen; i += 2) { - if(n >= max - 1) - break; - if(HIBYTE(from+i, byte)!=0) - *to++='?'; - else - *to++ = LOBYTE(from+i,byte); - n++; - } - *to = 0; - return n; -} - -static int -FTGetName(FT_Face face, int nid, int pid, int eid, FT_SfntName *name_return) -{ - FT_SfntName name; - int n, i; - - n = FT_Get_Sfnt_Name_Count(face); - if(n <= 0) - return 0; - - for(i = 0; i < n; i++) { - if(FT_Get_Sfnt_Name(face, i, &name)) - continue; - if(name.name_id == nid && - name.platform_id == pid && - (eid < 0 || name.encoding_id == eid)) { - switch(name.platform_id) { - case TT_PLATFORM_APPLE_UNICODE: - case TT_PLATFORM_MACINTOSH: - if(name.language_id != TT_MAC_LANGID_ENGLISH) - continue; - break; - case TT_PLATFORM_MICROSOFT: - if(name.language_id != TT_MS_LANGID_ENGLISH_UNITED_STATES && - name.language_id != TT_MS_LANGID_ENGLISH_UNITED_KINGDOM) - break; - continue; - break; - default: - break; - } - *name_return = name; - return 1; - } - } - return 0; -} - -int -FTGetEnglishName(FT_Face face, int nid, char *name_return, int name_len) -{ - FT_SfntName name; - int len; - - if(FTGetName(face, nid, - TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, &name) || - FTGetName(face, nid, - TT_PLATFORM_APPLE_UNICODE, -1, &name)) - return FTu2a(name.string_len, name.string, name_return, - MSBFirst, name_len); - - /* Pretend that Apple Roman is ISO 8859-1. */ - if(FTGetName(face, nid, TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, &name)) { - len = name.string_len; - if(len > name_len - 1) - len = name_len - 1; - memcpy(name_return, name.string, len); - name_return[len] = '\0'; /* ensure nul terminaison */ - return len; - } - - /* Must be some font that can only be named in Polish or something. */ - return -1; -} +/*
+ Copyright (c) 1997 by Mark Leisher
+ Copyright (c) 1998-2002 by Juliusz Chroboczek
+
+ 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fontmisc.h>
+#include <ctype.h>
+#include <string.h>
+
+#include <X11/fonts/font.h>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_SFNT_NAMES_H
+#include FT_TRUETYPE_IDS_H
+#include "ft.h"
+
+#ifndef LSBFirst
+#define LSBFirst 0
+#define MSBFirst 1
+#endif
+
+#define LOBYTE(s,byte) ((byte)==LSBFirst?*(char*)(s):*((char*)(s)+1))
+#define HIBYTE(s,byte) ((byte)==LSBFirst?*((char*)(s)+1):*(char*)(s))
+
+int FTtoXReturnCode(int rc)
+{
+ if(rc == 0x40)
+ return AllocError;
+ /* Anything else stops the font matching mechanism */
+ else return BadFontName;
+
+}
+
+/* Convert slen bytes from UCS-2 to ISO 8859-1. Byte specifies the
+ endianness of the string, max the maximum number of bytes written into
+ to. */
+static int
+FTu2a(int slen, FT_Byte *from, char *to, int byte, int max)
+{
+ int i, n;
+
+ n = 0;
+ for (i = 0; i < slen; i += 2) {
+ if(n >= max - 1)
+ break;
+ if(HIBYTE(from+i, byte)!=0)
+ *to++='?';
+ else
+ *to++ = LOBYTE(from+i,byte);
+ n++;
+ }
+ *to = 0;
+ return n;
+}
+
+static int
+FTGetName(FT_Face face, int nid, int pid, int eid, FT_SfntName *name_return)
+{
+ FT_SfntName name;
+ int n, i;
+
+ n = FT_Get_Sfnt_Name_Count(face);
+ if(n <= 0)
+ return 0;
+
+ for(i = 0; i < n; i++) {
+ if(FT_Get_Sfnt_Name(face, i, &name))
+ continue;
+ if(name.name_id == nid &&
+ name.platform_id == pid &&
+ (eid < 0 || name.encoding_id == eid)) {
+ switch(name.platform_id) {
+ case TT_PLATFORM_APPLE_UNICODE:
+ case TT_PLATFORM_MACINTOSH:
+ if(name.language_id != TT_MAC_LANGID_ENGLISH)
+ continue;
+ break;
+ case TT_PLATFORM_MICROSOFT:
+ if(name.language_id != TT_MS_LANGID_ENGLISH_UNITED_STATES &&
+ name.language_id != TT_MS_LANGID_ENGLISH_UNITED_KINGDOM)
+ break;
+ continue;
+ break;
+ default:
+ break;
+ }
+ *name_return = name;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int
+FTGetEnglishName(FT_Face face, int nid, char *name_return, int name_len)
+{
+ FT_SfntName name;
+ int len;
+
+ if(FTGetName(face, nid,
+ TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, &name) ||
+ FTGetName(face, nid,
+ TT_PLATFORM_APPLE_UNICODE, -1, &name))
+ return FTu2a(name.string_len, name.string, name_return,
+ MSBFirst, name_len);
+
+ /* Pretend that Apple Roman is ISO 8859-1. */
+ if(FTGetName(face, nid, TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, &name)) {
+ len = name.string_len;
+ if(len > name_len - 1)
+ len = name_len - 1;
+ memcpy(name_return, name.string, len);
+ name_return[len] = '\0'; /* ensure nul terminaison */
+ return len;
+ }
+
+ /* Must be some font that can only be named in Polish or something. */
+ return -1;
+}
diff --git a/libXfont/src/FreeType/makefile b/libXfont/src/FreeType/makefile new file mode 100644 index 000000000..8d4fee2b6 --- /dev/null +++ b/libXfont/src/FreeType/makefile @@ -0,0 +1,15 @@ +LIBRARY = libft + +CSRCS = \ + ftenc.c \ + ftfuncs.c \ + fttools.c \ + xttcap.c + +INCLUDES += $(MHMAKECONF)\freetype\include\freetype $(MHMAKECONF)\freetype\include + +DEFINES += strcasecmp=_stricmp + +INCLUDES := ../.. $(INCLUDES) + + diff --git a/libXfont/src/FreeType/xttcap.c b/libXfont/src/FreeType/xttcap.c index c2a412091..95426f11e 100644 --- a/libXfont/src/FreeType/xttcap.c +++ b/libXfont/src/FreeType/xttcap.c @@ -1,705 +1,705 @@ -/* ===EmacsMode: -*- Mode: C; tab-width:4; c-basic-offset: 4; -*- === */ -/* ===FileName: === - Copyright (c) 1998 Takuya SHIOZAKI, All Rights reserved. - Copyright (c) 1998 X-TrueType Server Project, All rights reserved. - Copyright (c) 2003 After X-TT Project, All rights reserved. - -===Notice - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - - Major Release ID: X-TrueType Server Version 1.4 [Charles's Wain Release 0] - -Notice=== - */ - -/* -#include "xttversion.h" - -static char const * const releaseID = - _XTT_RELEASE_NAME; -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fontmisc.h> -#include <string.h> -#include <ctype.h> -#include <math.h> - -#ifndef True -#define True (-1) -#endif /* True */ -#ifndef False -#define False (0) -#endif /* False */ - -#include "xttcap.h" - - -/************************************************************************** - Private Data Types - */ - -/* Property Record List */ -/* List Node */ -typedef struct TagSPropRecValListNodeP -{ - SPropRecValContainerEntityP containerE; - struct TagSPropRecValListNodeP *nextNode; -} SPropRecValListNodeP; - - -/************************************************************************** - Tables - */ - -/* valid record field */ -static SPropertyRecord const validRecords[] = -{ - { "FontFile", eRecTypeString }, - { "FaceNumber", eRecTypeString }, - { "AutoItalic", eRecTypeDouble }, - { "DoubleStrike", eRecTypeString }, - { "FontProperties", eRecTypeBool }, - { "ForceSpacing", eRecTypeString }, - { "ScaleBBoxWidth", eRecTypeString }, - { "ScaleWidth", eRecTypeDouble }, - { "EncodingOptions", eRecTypeString }, - { "Hinting", eRecTypeBool }, - { "VeryLazyMetrics", eRecTypeBool }, - { "CodeRange", eRecTypeString }, - { "EmbeddedBitmap", eRecTypeString }, - { "VeryLazyBitmapWidthScale", eRecTypeDouble }, - { "ForceConstantSpacingCodeRange", eRecTypeString }, - { "ForceConstantSpacingMetrics", eRecTypeString }, - { "Dummy", eRecTypeVoid } -}; -static int const -numOfValidRecords = sizeof(validRecords)/sizeof(validRecords[0]); - -/* correspondence between record name and cap variable name */ -static struct { - char const * capVariable; - char const * recordName; -} const correspondRelations[] = { - { "fn", "FaceNumber" }, - { "ai", "AutoItalic" }, - { "ds", "DoubleStrike" }, - { "fp", "FontProperties" }, - { "fs", "ForceSpacing" }, - { "bw", "ScaleBBoxWidth" }, - { "sw", "ScaleWidth" }, - { "eo", "EncodingOptions" }, - { "vl", "VeryLazyMetrics" }, - { "bs", "VeryLazyBitmapWidthScale" }, - { "cr", "CodeRange" }, - { "eb", "EmbeddedBitmap" }, - { "hi", "Hinting" }, - { "fc", "ForceConstantSpacingCodeRange" }, - { "fm", "ForceConstantSpacingMetrics" } -}; -static int const -numOfCorrespondRelations -= sizeof(correspondRelations)/sizeof(correspondRelations[0]); - -/************************************************************************** - Functions - */ - -/* get property record type by record name */ -static Bool /* True == Found, False == Not Found */ -get_record_type_by_name(SPropertyRecord const ** const refRefRecord, /*result*/ - char const *strName) -{ - Bool result = False; - int i; - - *refRefRecord = NULL; - for (i=0; i<numOfValidRecords; i++) { - if (!strcasecmp(validRecords[i].strRecordName, strName)) { - result = True; - *refRefRecord = &validRecords[i]; - break; - } - } - - return result; -} - -/* Add Property Record Value */ -static Bool /* True == Error, False == Success */ -SPropRecValList_add_record(SDynPropRecValList *pThisList, - char const * const recordName, - char const * const strValue) -{ - Bool result = False; - SPropRecValContainerEntityP tmpContainerE; - - if (get_record_type_by_name(&tmpContainerE.refRecordType, recordName)) { - switch (tmpContainerE.refRecordType->recordType) { - case eRecTypeInteger: - { - int val; - char *endPtr; - - val = strtol(strValue, &endPtr, 0); - if ('\0' != *endPtr) { - fprintf(stderr, - "truetype font property : " - "%s record needs integer value.\n", - recordName); - result = True; - goto quit; - } - SPropContainer_value_int(&tmpContainerE) = val; - } - break; - case eRecTypeDouble: - { - double val; - char *endPtr; - - val = strtod(strValue, &endPtr); - if ('\0' != *endPtr) { - fprintf(stderr, - "truetype font property : " - "%s record needs floating point value.\n", - recordName); - result = True; - goto quit; - } - SPropContainer_value_dbl(&tmpContainerE) = val; - } - break; - case eRecTypeBool: - { - Bool val; - - if (!strcasecmp(strValue, "yes")) - val = True; - else if (!strcasecmp(strValue, "y")) - val = True; - else if (!strcasecmp(strValue, "on")) - val = True; - else if (!strcasecmp(strValue, "true")) - val = True; - else if (!strcasecmp(strValue, "t")) - val = True; - else if (!strcasecmp(strValue, "ok")) - val = True; - else if (!strcasecmp(strValue, "no")) - val = False; - else if (!strcasecmp(strValue, "n")) - val = False; - else if (!strcasecmp(strValue, "off")) - val = False; - else if (!strcasecmp(strValue, "false")) - val = False; - else if (!strcasecmp(strValue, "f")) - val = False; - else if (!strcasecmp(strValue, "bad")) - val = False; - else { - fprintf(stderr, - "truetype font property : " - "%s record needs boolean value.\n", - recordName); - result = True; - goto quit; - } - SPropContainer_value_bool(&tmpContainerE) = val; - } - break; - case eRecTypeString: - { - char *p; - - if (NULL == (p = malloc(strlen(strValue)+1))) { - fprintf(stderr, - "truetype font property : " - "cannot allocate memory.\n"); - result = True; - goto quit; - } - strcpy(p, strValue); - SPropContainer_value_str(&tmpContainerE) = p; - } - break; - case eRecTypeVoid: - if ('\0' != *strValue) { - fprintf(stderr, - "truetype font property : " - "%s record needs void.\n", recordName); - result = True; - } - break; - } - { - /* add to list */ - SPropRecValListNodeP *newNode; - - if (NULL == (newNode = malloc(sizeof(*newNode)))) { - fprintf(stderr, - "truetype font property : " - "cannot allocate memory.\n"); - result = True; - goto quit; - } - newNode->nextNode = pThisList->headNode; - newNode->containerE = tmpContainerE; - tmpContainerE.refRecordType = NULL; /* invalidate -- - disown value handle. */ - pThisList->headNode = newNode; - } - } else { - /* invalid record name */ - fprintf(stderr, - "truetype font : " - "invalid record name \"%s.\"\n", recordName); - result = True; - } - - quit: - return result; -} - -#ifdef USE_TTP_FILE - -#ifndef LEN_LINEBUF -#define LEN_LINEBUF 2048 -#endif /* !def LEN_LINEBUF */ - -/* get one line */ -static Bool /* True == Error, False == Success */ -get_one_line(FILE *is, char *buf) -{ - Bool result = False; - int count = 0; - Bool flHead = True; - Bool flSpace = False; - Bool flInSingleQuote = False; - Bool flInDoubleQuote = False; - Bool flBackSlash = False; - Bool flFirstElement = True; - - *buf = '\0'; - for (;;) { - int c = fgetc(is); - - if (ferror(is)) { - fprintf(stderr, "truetype font property file : read error.\n"); - result = True; - break; - } - - if (EOF == c) { - if (flInSingleQuote || flInDoubleQuote) { - fprintf(stderr, - "truetype font property file : unmatched quote.\n"); - result = True; - } - break; - } - if (flInSingleQuote) { - if ('\'' == c) { - /* end of single quoted string */ - flInSingleQuote = False; - c = -1; /* NOT extract to buffer. */ - } else - /* others, extract all character to buffer unconditionally. */ - ; - goto trans; - } - if (flBackSlash) { - /* escape --- when just before character is backslash, - next character is escaped. */ - flBackSlash = False; - if ('n' == c) - /* newline */ - c = '\n'; - if ('\n' == c) - /* ignore newline */ - c = -1; - else - /* others, extract all character to buffer unconditionally. */ - ; - goto trans; - } - if ('\\' == c) { - /* set flag to escape next character. */ - flBackSlash = True; - c = -1; /* NOT extract to buffer. */ - goto trans; - } - if (flInDoubleQuote) { - if ('"' == c) { - /* end of double quoted string */ - flInDoubleQuote = False; - c = -1; /* NOT extract to buffer. */ - } else - /* others, extract all character to buffer unconditionally. */ - ; - goto trans; - } - if ('#' == c) { - /* skip comment till end of line. */ - while ('\n' != c) { - c = fgetc(is); - if (ferror(is)) { - fprintf(stderr, - "truetype font property file : read error.\n"); - result = True; - break; - } - if (EOF == c) { - break; - } - } - break; - } - if ('\'' == c) { - /* into single quoted string */ - flInSingleQuote = True; - c = -1; /* NOT extract to buffer. */ - goto trans; - } - if ('"' == c) { - /* into double quoted string */ - flInDoubleQuote = True; - c = -1; /* NOT extract to buffer. */ - goto trans; - } - if ('\n' == c) - /* End of Line */ - break; - if (isspace(c)) { - /* convine multiple spaces */ - if (!flHead) - /* except space at the head of line */ - flSpace = True; - continue; - } - trans: - /* set flHead to False, since current character is not white space - when reaches here. */ - flHead = False; - do { - if (count>=LEN_LINEBUF-1) { - /* overflow */ - fprintf(stderr, - "truetype font property file : too long line.\n"); - result = True; - goto quit; - } - if (flSpace) { - /* just before characters is white space, but - current character is not WS. */ - if (flFirstElement) { - /* this spaces is the first cell(?) of white spaces. */ - flFirstElement = False; - /* separate record name and record value */ - *buf = (char)0xff; - } else - *buf = ' '; - flSpace = False; - } else - if (-1 != c) { - *buf = c; - c = -1; /* invalidate */ - } else - /* skip */ - buf--; - buf++; - } while (-1 != c); /* when 'c' is not -1, it means - that 'c' contains an untreated character. */ - } - *buf = '\0'; - - quit: - return result; -} - -/* parse one line */ -static Bool /* True == Error, False == Success */ -parse_one_line(SDynPropRecValList *pThisList, FILE *is) -{ - Bool result = False; - char *buf = NULL; - char *recordHead, *valueHead = NULL; - - if (NULL == (buf = malloc(LEN_LINEBUF))) { - fprintf(stderr, - "truetype font property file : cannot allocate memory.\n"); - result = True; - goto abort; - } - { - recordHead = buf; -/* refRecordValue->refRecordType = NULL;*/ - do { - if (get_one_line(is, buf)) { - result = True; - goto quit; - } - if (feof(is)) { - if ('\0' == *buf) - goto quit; - break; - } - } while ('\0' == *buf); - - if (NULL != (valueHead = strchr(buf, 0xff))) { - *valueHead = '\0'; - valueHead++; - } else - valueHead = buf+strlen(buf); -#if 0 - fprintf(stderr, - "truetype font property file : \n" - "recName:\"%s\"\nvalue:\"%s\"\n", - recordHead, valueHead); -#endif - result = SPropRecValList_add_record(pThisList, recordHead, valueHead); - } - quit: - free(buf); - abort: - return result; -} - -/* Read Property File */ -Bool /* True == Error, False == Success */ -SPropRecValList_read_prop_file(SDynPropRecValList *pThisList, - char const * const strFileName) -{ - Bool result = False; - FILE *is; - -#if 1 - if (!strcmp(strFileName, "-")) - is = stdin; - else -#endif - is = fopen(strFileName, "r"); - if (NULL == is) { - fprintf(stderr, "truetype font property : cannot open file %s.\n", - strFileName); - result = True; - goto abort; - } - { - for (;;) { - if (False != (result = parse_one_line(pThisList, is))) - goto quit; - if (feof(is)) - break; - } - } - quit: -#if 1 - if (strcmp(strFileName, "-")) -#endif - fclose(is); - abort: - return result; -} -#endif /* USE_TTP_FILE */ - -/* Constructor for Container Node */ -Bool /* True == Error, False == Success */ -SPropRecValList_new(SDynPropRecValList *pThisList) -{ - Bool result = False; - - pThisList->headNode = NULL; - - return result; -} - -#ifdef DUMP -void -SPropRecValList_dump(SRefPropRecValList *pThisList) -{ - SPropRecValListNodeP *p; - for (p=pThisList->headNode; NULL!=p; p=p->nextNode) { - switch (p->containerE.refRecordType->recordType) { - case eRecTypeInteger: - fprintf(stderr, "%s = %d\n", - p->containerE.refRecordType->strRecordName, - p->containerE.uValue.integerValue); - break; - case eRecTypeDouble: - fprintf(stderr, "%s = %f\n", - p->containerE.refRecordType->strRecordName, - p->containerE.uValue.doubleValue); - break; - case eRecTypeBool: - fprintf(stderr, "%s = %s\n", - p->containerE.refRecordType->strRecordName, - p->containerE.uValue.boolValue - ? "True":"False"); - break; - case eRecTypeString: - fprintf(stderr, "%s = \"%s\"\n", - p->containerE.refRecordType->strRecordName, - p->containerE.uValue.dynStringValue); - break; - case eRecTypeVoid: - fprintf(stderr, "%s = void\n", - p->containerE.refRecordType->strRecordName); - break; - } - } -} -#endif - - -/* Search Property Record */ -Bool /* True == Hit, False == Miss */ -SPropRecValList_search_record(SRefPropRecValList *pThisList, - SPropRecValContainer *refRecValue, - char const * const recordName) -{ - Bool result = False; - SPropRecValListNodeP *p; - - *refRecValue = NULL; - for (p=pThisList->headNode; NULL!=p; p=p->nextNode) { - if (!strcasecmp(p->containerE.refRecordType->strRecordName, - recordName)) { - *refRecValue = &p->containerE; - result = True; - break; - } - } - - return result; -} - - -/* Parse TTCap */ -Bool /* True == Error, False == Success */ -SPropRecValList_add_by_font_cap(SDynPropRecValList *pThisList, - char const *strCapHead) -{ - Bool result = False; - /* SPropertyRecord const *refRecordType; */ - char const *term; - - if (NULL == (term = strrchr(strCapHead, ':'))) - goto abort; - - { - /* for xfsft compatible */ - char const *p; - for (p=term-1; p>=strCapHead; p--) { - if ( ':'==*p ) { - /* - * :num:filename - * ^p ^term - */ - if ( p!=term ) { - int len = term-p-1; - char *value; - - len = term-p-1; - value=malloc(len+1); - memcpy(value, p+1, len); - value[len]='\0'; - SPropRecValList_add_record(pThisList, - "FaceNumber", - value); - free(value); - term=p; - } - break; - } - if ( !isdigit(*p) ) - break; - } - } - - while (strCapHead<term) { - int i; - char const *nextColon = strchr(strCapHead, ':'); - if (0<nextColon-strCapHead) { - char *duplicated = malloc((nextColon-strCapHead)+1); - { - char *value; - - memcpy(duplicated, strCapHead, nextColon-strCapHead); - duplicated[nextColon-strCapHead] = '\0'; - if (NULL != (value=strchr(duplicated, '='))) { - *value = '\0'; - value++; - } else - value = &duplicated[nextColon-strCapHead]; - - for (i=0; i<numOfCorrespondRelations; i++) { - if (!strcasecmp(correspondRelations[i].capVariable, - duplicated)) { - if (SPropRecValList_add_record(pThisList, - correspondRelations[i] - .recordName, - value)) - break; - goto next; - } - } - fprintf(stderr, "truetype font : Illegal Font Cap.\n"); - result = True; - break; - next: - ; - } - free(duplicated); - } - strCapHead = nextColon+1; - } - - /* quit: */ - abort: - return result; -} - - -/************************************************************************** - Functions (xttmisc) - */ - -/* strdup clone with using the allocator of X server */ -char * -XttXstrdup(char const *str) -{ - char *result; - - result = malloc(strlen(str)+1); - - if (result) - strcpy(result, str); - - return result; -} - - -/* end of file */ +/* ===EmacsMode: -*- Mode: C; tab-width:4; c-basic-offset: 4; -*- === */
+/* ===FileName: ===
+ Copyright (c) 1998 Takuya SHIOZAKI, All Rights reserved.
+ Copyright (c) 1998 X-TrueType Server Project, All rights reserved.
+ Copyright (c) 2003 After X-TT Project, All rights reserved.
+
+===Notice
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+ Major Release ID: X-TrueType Server Version 1.4 [Charles's Wain Release 0]
+
+Notice===
+ */
+
+/*
+#include "xttversion.h"
+
+static char const * const releaseID =
+ _XTT_RELEASE_NAME;
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fontmisc.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+
+#ifndef True
+#define True (-1)
+#endif /* True */
+#ifndef False
+#define False (0)
+#endif /* False */
+
+#include "xttcap.h"
+
+
+/**************************************************************************
+ Private Data Types
+ */
+
+/* Property Record List */
+/* List Node */
+typedef struct TagSPropRecValListNodeP
+{
+ SPropRecValContainerEntityP containerE;
+ struct TagSPropRecValListNodeP *nextNode;
+} SPropRecValListNodeP;
+
+
+/**************************************************************************
+ Tables
+ */
+
+/* valid record field */
+static SPropertyRecord const validRecords[] =
+{
+ { "FontFile", eRecTypeString },
+ { "FaceNumber", eRecTypeString },
+ { "AutoItalic", eRecTypeDouble },
+ { "DoubleStrike", eRecTypeString },
+ { "FontProperties", eRecTypeBool },
+ { "ForceSpacing", eRecTypeString },
+ { "ScaleBBoxWidth", eRecTypeString },
+ { "ScaleWidth", eRecTypeDouble },
+ { "EncodingOptions", eRecTypeString },
+ { "Hinting", eRecTypeBool },
+ { "VeryLazyMetrics", eRecTypeBool },
+ { "CodeRange", eRecTypeString },
+ { "EmbeddedBitmap", eRecTypeString },
+ { "VeryLazyBitmapWidthScale", eRecTypeDouble },
+ { "ForceConstantSpacingCodeRange", eRecTypeString },
+ { "ForceConstantSpacingMetrics", eRecTypeString },
+ { "Dummy", eRecTypeVoid }
+};
+static int const
+numOfValidRecords = sizeof(validRecords)/sizeof(validRecords[0]);
+
+/* correspondence between record name and cap variable name */
+static struct {
+ char const * capVariable;
+ char const * recordName;
+} const correspondRelations[] = {
+ { "fn", "FaceNumber" },
+ { "ai", "AutoItalic" },
+ { "ds", "DoubleStrike" },
+ { "fp", "FontProperties" },
+ { "fs", "ForceSpacing" },
+ { "bw", "ScaleBBoxWidth" },
+ { "sw", "ScaleWidth" },
+ { "eo", "EncodingOptions" },
+ { "vl", "VeryLazyMetrics" },
+ { "bs", "VeryLazyBitmapWidthScale" },
+ { "cr", "CodeRange" },
+ { "eb", "EmbeddedBitmap" },
+ { "hi", "Hinting" },
+ { "fc", "ForceConstantSpacingCodeRange" },
+ { "fm", "ForceConstantSpacingMetrics" }
+};
+static int const
+numOfCorrespondRelations
+= sizeof(correspondRelations)/sizeof(correspondRelations[0]);
+
+/**************************************************************************
+ Functions
+ */
+
+/* get property record type by record name */
+static Bool /* True == Found, False == Not Found */
+get_record_type_by_name(SPropertyRecord const ** const refRefRecord, /*result*/
+ char const *strName)
+{
+ Bool result = False;
+ int i;
+
+ *refRefRecord = NULL;
+ for (i=0; i<numOfValidRecords; i++) {
+ if (!strcasecmp(validRecords[i].strRecordName, strName)) {
+ result = True;
+ *refRefRecord = &validRecords[i];
+ break;
+ }
+ }
+
+ return result;
+}
+
+/* Add Property Record Value */
+static Bool /* True == Error, False == Success */
+SPropRecValList_add_record(SDynPropRecValList *pThisList,
+ char const * const recordName,
+ char const * const strValue)
+{
+ Bool result = False;
+ SPropRecValContainerEntityP tmpContainerE;
+
+ if (get_record_type_by_name(&tmpContainerE.refRecordType, recordName)) {
+ switch (tmpContainerE.refRecordType->recordType) {
+ case eRecTypeInteger:
+ {
+ int val;
+ char *endPtr;
+
+ val = strtol(strValue, &endPtr, 0);
+ if ('\0' != *endPtr) {
+ fprintf(stderr,
+ "truetype font property : "
+ "%s record needs integer value.\n",
+ recordName);
+ result = True;
+ goto quit;
+ }
+ SPropContainer_value_int(&tmpContainerE) = val;
+ }
+ break;
+ case eRecTypeDouble:
+ {
+ double val;
+ char *endPtr;
+
+ val = strtod(strValue, &endPtr);
+ if ('\0' != *endPtr) {
+ fprintf(stderr,
+ "truetype font property : "
+ "%s record needs floating point value.\n",
+ recordName);
+ result = True;
+ goto quit;
+ }
+ SPropContainer_value_dbl(&tmpContainerE) = val;
+ }
+ break;
+ case eRecTypeBool:
+ {
+ Bool val;
+
+ if (!strcasecmp(strValue, "yes"))
+ val = True;
+ else if (!strcasecmp(strValue, "y"))
+ val = True;
+ else if (!strcasecmp(strValue, "on"))
+ val = True;
+ else if (!strcasecmp(strValue, "true"))
+ val = True;
+ else if (!strcasecmp(strValue, "t"))
+ val = True;
+ else if (!strcasecmp(strValue, "ok"))
+ val = True;
+ else if (!strcasecmp(strValue, "no"))
+ val = False;
+ else if (!strcasecmp(strValue, "n"))
+ val = False;
+ else if (!strcasecmp(strValue, "off"))
+ val = False;
+ else if (!strcasecmp(strValue, "false"))
+ val = False;
+ else if (!strcasecmp(strValue, "f"))
+ val = False;
+ else if (!strcasecmp(strValue, "bad"))
+ val = False;
+ else {
+ fprintf(stderr,
+ "truetype font property : "
+ "%s record needs boolean value.\n",
+ recordName);
+ result = True;
+ goto quit;
+ }
+ SPropContainer_value_bool(&tmpContainerE) = val;
+ }
+ break;
+ case eRecTypeString:
+ {
+ char *p;
+
+ if (NULL == (p = malloc(strlen(strValue)+1))) {
+ fprintf(stderr,
+ "truetype font property : "
+ "cannot allocate memory.\n");
+ result = True;
+ goto quit;
+ }
+ strcpy(p, strValue);
+ SPropContainer_value_str(&tmpContainerE) = p;
+ }
+ break;
+ case eRecTypeVoid:
+ if ('\0' != *strValue) {
+ fprintf(stderr,
+ "truetype font property : "
+ "%s record needs void.\n", recordName);
+ result = True;
+ }
+ break;
+ }
+ {
+ /* add to list */
+ SPropRecValListNodeP *newNode;
+
+ if (NULL == (newNode = malloc(sizeof(*newNode)))) {
+ fprintf(stderr,
+ "truetype font property : "
+ "cannot allocate memory.\n");
+ result = True;
+ goto quit;
+ }
+ newNode->nextNode = pThisList->headNode;
+ newNode->containerE = tmpContainerE;
+ tmpContainerE.refRecordType = NULL; /* invalidate --
+ disown value handle. */
+ pThisList->headNode = newNode;
+ }
+ } else {
+ /* invalid record name */
+ fprintf(stderr,
+ "truetype font : "
+ "invalid record name \"%s.\"\n", recordName);
+ result = True;
+ }
+
+ quit:
+ return result;
+}
+
+#ifdef USE_TTP_FILE
+
+#ifndef LEN_LINEBUF
+#define LEN_LINEBUF 2048
+#endif /* !def LEN_LINEBUF */
+
+/* get one line */
+static Bool /* True == Error, False == Success */
+get_one_line(FILE *is, char *buf)
+{
+ Bool result = False;
+ int count = 0;
+ Bool flHead = True;
+ Bool flSpace = False;
+ Bool flInSingleQuote = False;
+ Bool flInDoubleQuote = False;
+ Bool flBackSlash = False;
+ Bool flFirstElement = True;
+
+ *buf = '\0';
+ for (;;) {
+ int c = fgetc(is);
+
+ if (ferror(is)) {
+ fprintf(stderr, "truetype font property file : read error.\n");
+ result = True;
+ break;
+ }
+
+ if (EOF == c) {
+ if (flInSingleQuote || flInDoubleQuote) {
+ fprintf(stderr,
+ "truetype font property file : unmatched quote.\n");
+ result = True;
+ }
+ break;
+ }
+ if (flInSingleQuote) {
+ if ('\'' == c) {
+ /* end of single quoted string */
+ flInSingleQuote = False;
+ c = -1; /* NOT extract to buffer. */
+ } else
+ /* others, extract all character to buffer unconditionally. */
+ ;
+ goto trans;
+ }
+ if (flBackSlash) {
+ /* escape --- when just before character is backslash,
+ next character is escaped. */
+ flBackSlash = False;
+ if ('n' == c)
+ /* newline */
+ c = '\n';
+ if ('\n' == c)
+ /* ignore newline */
+ c = -1;
+ else
+ /* others, extract all character to buffer unconditionally. */
+ ;
+ goto trans;
+ }
+ if ('\\' == c) {
+ /* set flag to escape next character. */
+ flBackSlash = True;
+ c = -1; /* NOT extract to buffer. */
+ goto trans;
+ }
+ if (flInDoubleQuote) {
+ if ('"' == c) {
+ /* end of double quoted string */
+ flInDoubleQuote = False;
+ c = -1; /* NOT extract to buffer. */
+ } else
+ /* others, extract all character to buffer unconditionally. */
+ ;
+ goto trans;
+ }
+ if ('#' == c) {
+ /* skip comment till end of line. */
+ while ('\n' != c) {
+ c = fgetc(is);
+ if (ferror(is)) {
+ fprintf(stderr,
+ "truetype font property file : read error.\n");
+ result = True;
+ break;
+ }
+ if (EOF == c) {
+ break;
+ }
+ }
+ break;
+ }
+ if ('\'' == c) {
+ /* into single quoted string */
+ flInSingleQuote = True;
+ c = -1; /* NOT extract to buffer. */
+ goto trans;
+ }
+ if ('"' == c) {
+ /* into double quoted string */
+ flInDoubleQuote = True;
+ c = -1; /* NOT extract to buffer. */
+ goto trans;
+ }
+ if ('\n' == c)
+ /* End of Line */
+ break;
+ if (isspace(c)) {
+ /* convine multiple spaces */
+ if (!flHead)
+ /* except space at the head of line */
+ flSpace = True;
+ continue;
+ }
+ trans:
+ /* set flHead to False, since current character is not white space
+ when reaches here. */
+ flHead = False;
+ do {
+ if (count>=LEN_LINEBUF-1) {
+ /* overflow */
+ fprintf(stderr,
+ "truetype font property file : too long line.\n");
+ result = True;
+ goto quit;
+ }
+ if (flSpace) {
+ /* just before characters is white space, but
+ current character is not WS. */
+ if (flFirstElement) {
+ /* this spaces is the first cell(?) of white spaces. */
+ flFirstElement = False;
+ /* separate record name and record value */
+ *buf = (char)0xff;
+ } else
+ *buf = ' ';
+ flSpace = False;
+ } else
+ if (-1 != c) {
+ *buf = c;
+ c = -1; /* invalidate */
+ } else
+ /* skip */
+ buf--;
+ buf++;
+ } while (-1 != c); /* when 'c' is not -1, it means
+ that 'c' contains an untreated character. */
+ }
+ *buf = '\0';
+
+ quit:
+ return result;
+}
+
+/* parse one line */
+static Bool /* True == Error, False == Success */
+parse_one_line(SDynPropRecValList *pThisList, FILE *is)
+{
+ Bool result = False;
+ char *buf = NULL;
+ char *recordHead, *valueHead = NULL;
+
+ if (NULL == (buf = malloc(LEN_LINEBUF))) {
+ fprintf(stderr,
+ "truetype font property file : cannot allocate memory.\n");
+ result = True;
+ goto abort;
+ }
+ {
+ recordHead = buf;
+/* refRecordValue->refRecordType = NULL;*/
+ do {
+ if (get_one_line(is, buf)) {
+ result = True;
+ goto quit;
+ }
+ if (feof(is)) {
+ if ('\0' == *buf)
+ goto quit;
+ break;
+ }
+ } while ('\0' == *buf);
+
+ if (NULL != (valueHead = strchr(buf, 0xff))) {
+ *valueHead = '\0';
+ valueHead++;
+ } else
+ valueHead = buf+strlen(buf);
+#if 0
+ fprintf(stderr,
+ "truetype font property file : \n"
+ "recName:\"%s\"\nvalue:\"%s\"\n",
+ recordHead, valueHead);
+#endif
+ result = SPropRecValList_add_record(pThisList, recordHead, valueHead);
+ }
+ quit:
+ free(buf);
+ abort:
+ return result;
+}
+
+/* Read Property File */
+Bool /* True == Error, False == Success */
+SPropRecValList_read_prop_file(SDynPropRecValList *pThisList,
+ char const * const strFileName)
+{
+ Bool result = False;
+ FILE *is;
+
+#if 1
+ if (!strcmp(strFileName, "-"))
+ is = stdin;
+ else
+#endif
+ is = fopen(strFileName, "r");
+ if (NULL == is) {
+ fprintf(stderr, "truetype font property : cannot open file %s.\n",
+ strFileName);
+ result = True;
+ goto abort;
+ }
+ {
+ for (;;) {
+ if (False != (result = parse_one_line(pThisList, is)))
+ goto quit;
+ if (feof(is))
+ break;
+ }
+ }
+ quit:
+#if 1
+ if (strcmp(strFileName, "-"))
+#endif
+ fclose(is);
+ abort:
+ return result;
+}
+#endif /* USE_TTP_FILE */
+
+/* Constructor for Container Node */
+Bool /* True == Error, False == Success */
+SPropRecValList_new(SDynPropRecValList *pThisList)
+{
+ Bool result = False;
+
+ pThisList->headNode = NULL;
+
+ return result;
+}
+
+#ifdef DUMP
+void
+SPropRecValList_dump(SRefPropRecValList *pThisList)
+{
+ SPropRecValListNodeP *p;
+ for (p=pThisList->headNode; NULL!=p; p=p->nextNode) {
+ switch (p->containerE.refRecordType->recordType) {
+ case eRecTypeInteger:
+ fprintf(stderr, "%s = %d\n",
+ p->containerE.refRecordType->strRecordName,
+ p->containerE.uValue.integerValue);
+ break;
+ case eRecTypeDouble:
+ fprintf(stderr, "%s = %f\n",
+ p->containerE.refRecordType->strRecordName,
+ p->containerE.uValue.doubleValue);
+ break;
+ case eRecTypeBool:
+ fprintf(stderr, "%s = %s\n",
+ p->containerE.refRecordType->strRecordName,
+ p->containerE.uValue.boolValue
+ ? "True":"False");
+ break;
+ case eRecTypeString:
+ fprintf(stderr, "%s = \"%s\"\n",
+ p->containerE.refRecordType->strRecordName,
+ p->containerE.uValue.dynStringValue);
+ break;
+ case eRecTypeVoid:
+ fprintf(stderr, "%s = void\n",
+ p->containerE.refRecordType->strRecordName);
+ break;
+ }
+ }
+}
+#endif
+
+
+/* Search Property Record */
+Bool /* True == Hit, False == Miss */
+SPropRecValList_search_record(SRefPropRecValList *pThisList,
+ SPropRecValContainer *refRecValue,
+ char const * const recordName)
+{
+ Bool result = False;
+ SPropRecValListNodeP *p;
+
+ *refRecValue = NULL;
+ for (p=pThisList->headNode; NULL!=p; p=p->nextNode) {
+ if (!strcasecmp(p->containerE.refRecordType->strRecordName,
+ recordName)) {
+ *refRecValue = &p->containerE;
+ result = True;
+ break;
+ }
+ }
+
+ return result;
+}
+
+
+/* Parse TTCap */
+Bool /* True == Error, False == Success */
+SPropRecValList_add_by_font_cap(SDynPropRecValList *pThisList,
+ char const *strCapHead)
+{
+ Bool result = False;
+ /* SPropertyRecord const *refRecordType; */
+ char const *term;
+
+ if (NULL == (term = strrchr(strCapHead, ':')))
+ goto abort;
+
+ {
+ /* for xfsft compatible */
+ char const *p;
+ for (p=term-1; p>=strCapHead; p--) {
+ if ( ':'==*p ) {
+ /*
+ * :num:filename
+ * ^p ^term
+ */
+ if ( p!=term ) {
+ int len = term-p-1;
+ char *value;
+
+ len = term-p-1;
+ value=malloc(len+1);
+ memcpy(value, p+1, len);
+ value[len]='\0';
+ SPropRecValList_add_record(pThisList,
+ "FaceNumber",
+ value);
+ free(value);
+ term=p;
+ }
+ break;
+ }
+ if ( !isdigit(*p) )
+ break;
+ }
+ }
+
+ while (strCapHead<term) {
+ int i;
+ char const *nextColon = strchr(strCapHead, ':');
+ if (0<nextColon-strCapHead) {
+ char *duplicated = malloc((nextColon-strCapHead)+1);
+ {
+ char *value;
+
+ memcpy(duplicated, strCapHead, nextColon-strCapHead);
+ duplicated[nextColon-strCapHead] = '\0';
+ if (NULL != (value=strchr(duplicated, '='))) {
+ *value = '\0';
+ value++;
+ } else
+ value = &duplicated[nextColon-strCapHead];
+
+ for (i=0; i<numOfCorrespondRelations; i++) {
+ if (!strcasecmp(correspondRelations[i].capVariable,
+ duplicated)) {
+ if (SPropRecValList_add_record(pThisList,
+ correspondRelations[i]
+ .recordName,
+ value))
+ break;
+ goto next;
+ }
+ }
+ fprintf(stderr, "truetype font : Illegal Font Cap.\n");
+ result = True;
+ break;
+ next:
+ ;
+ }
+ free(duplicated);
+ }
+ strCapHead = nextColon+1;
+ }
+
+ /* quit: */
+ abort:
+ return result;
+}
+
+
+/**************************************************************************
+ Functions (xttmisc)
+ */
+
+/* strdup clone with using the allocator of X server */
+char *
+XttXstrdup(char const *str)
+{
+ char *result;
+
+ result = malloc(strlen(str)+1);
+
+ if (result)
+ strcpy(result, str);
+
+ return result;
+}
+
+
+/* end of file */
diff --git a/libXfont/src/FreeType/xttcap.h b/libXfont/src/FreeType/xttcap.h index 6a09cf610..480a623ca 100644 --- a/libXfont/src/FreeType/xttcap.h +++ b/libXfont/src/FreeType/xttcap.h @@ -1,130 +1,130 @@ -/* ===EmacsMode: -*- Mode: C; tab-width:4; c-basic-offset: 4; -*- === */ -/* ===FileName: === - Copyright (c) 1998 Takuya SHIOZAKI, All Rights reserved. - Copyright (c) 1998 X-TrueType Server Project, All rights reserved. - Copyright (c) 2003 After X-TT Project, All rights reserved. - -===Notice - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - - Major Release ID: X-TrueType Server Version 1.3 [Aoi MATSUBARA Release 3] - -Notice=== - */ - -#ifndef _XTTCAP_H_ -#define _XTTCAP_H_ (1) - -#include <X11/Xdefs.h> - -/******************************************************************* - Data Types - */ - -/* Record Type */ -typedef enum -{ - eRecTypeInteger, - eRecTypeDouble, - eRecTypeBool, - eRecTypeString, - eRecTypeVoid=-1 -} ERecType; - -/* Record Name vs Record Type */ -typedef struct -{ - char const *strRecordName; - ERecType const recordType; -} SPropertyRecord; - -/* Record Value Container */ -typedef struct -{ - SPropertyRecord const *refRecordType; - union { - int integerValue; - double doubleValue; - Bool boolValue; - char *dynStringValue; - } uValue; -} SPropRecValContainerEntityP, *SPropRecValContainer; - -/* Record Value List */ -typedef struct TagSPropRecValListNodeP SPropRecValListNode; -typedef struct -{ - SPropRecValListNode *headNode; -} SDynPropRecValList; -typedef SDynPropRecValList const SRefPropRecValList; - - -/******************************************************************* - Functions - */ - -/* Constructor for Rec Val List */ -extern Bool /* True == Error, False == Success */ -SPropRecValList_new(SDynPropRecValList *pThisList); -/* Destructor for Rec Val List */ -extern Bool /* True == Error, False == Success */ -SPropRecValList_delete(SDynPropRecValList *pThisList); -/* Read Property File */ -extern Bool /* True == Error, False == Success */ -SPropRecValList_read_prop_file(SDynPropRecValList *pThisList, - char const * const strFileName); -/* Search Property Record */ -extern Bool /* True == Hit, False == Miss */ -SPropRecValList_search_record(SRefPropRecValList *pThisList, - SPropRecValContainer *refContRecVal, - char const * const recordName); -/* Add by Font Cap */ -extern Bool /* True == Error, False == Success */ -SPropRecValList_add_by_font_cap(SDynPropRecValList *pThisList, - char const *strCapHead); - -#ifdef DUMP -void -SPropRecValList_dump(SRefPropRecValList *refList); -#endif - -#define SPropContainer_value_int(contRecVal)\ - ((contRecVal)->uValue.integerValue) -#define SPropContainer_value_dbl(contRecVal)\ - ((contRecVal)->uValue.doubleValue) -#define SPropContainer_value_bool(contRecVal)\ - ((contRecVal)->uValue.boolValue) -#define SPropContainer_value_str(contRecVal)\ - ((contRecVal)->uValue.dynStringValue) - -/****************************************************** - Prototypes (xttmisc) - */ - -/* strdup clone */ -char * XttXstrdup(char const *str); -#undef xstrdup -#define xstrdup(s) XttXstrdup((char const*)s) - -#endif /* !def _XTTCAP_H_ */ - -/* end of file */ +/* ===EmacsMode: -*- Mode: C; tab-width:4; c-basic-offset: 4; -*- === */
+/* ===FileName: ===
+ Copyright (c) 1998 Takuya SHIOZAKI, All Rights reserved.
+ Copyright (c) 1998 X-TrueType Server Project, All rights reserved.
+ Copyright (c) 2003 After X-TT Project, All rights reserved.
+
+===Notice
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+ Major Release ID: X-TrueType Server Version 1.3 [Aoi MATSUBARA Release 3]
+
+Notice===
+ */
+
+#ifndef _XTTCAP_H_
+#define _XTTCAP_H_ (1)
+
+#include <X11/Xdefs.h>
+
+/*******************************************************************
+ Data Types
+ */
+
+/* Record Type */
+typedef enum
+{
+ eRecTypeInteger,
+ eRecTypeDouble,
+ eRecTypeBool,
+ eRecTypeString,
+ eRecTypeVoid=-1
+} ERecType;
+
+/* Record Name vs Record Type */
+typedef struct
+{
+ char const *strRecordName;
+ ERecType const recordType;
+} SPropertyRecord;
+
+/* Record Value Container */
+typedef struct
+{
+ SPropertyRecord const *refRecordType;
+ union {
+ int integerValue;
+ double doubleValue;
+ Bool boolValue;
+ char *dynStringValue;
+ } uValue;
+} SPropRecValContainerEntityP, *SPropRecValContainer;
+
+/* Record Value List */
+typedef struct TagSPropRecValListNodeP SPropRecValListNode;
+typedef struct
+{
+ SPropRecValListNode *headNode;
+} SDynPropRecValList;
+typedef SDynPropRecValList const SRefPropRecValList;
+
+
+/*******************************************************************
+ Functions
+ */
+
+/* Constructor for Rec Val List */
+extern Bool /* True == Error, False == Success */
+SPropRecValList_new(SDynPropRecValList *pThisList);
+/* Destructor for Rec Val List */
+extern Bool /* True == Error, False == Success */
+SPropRecValList_delete(SDynPropRecValList *pThisList);
+/* Read Property File */
+extern Bool /* True == Error, False == Success */
+SPropRecValList_read_prop_file(SDynPropRecValList *pThisList,
+ char const * const strFileName);
+/* Search Property Record */
+extern Bool /* True == Hit, False == Miss */
+SPropRecValList_search_record(SRefPropRecValList *pThisList,
+ SPropRecValContainer *refContRecVal,
+ char const * const recordName);
+/* Add by Font Cap */
+extern Bool /* True == Error, False == Success */
+SPropRecValList_add_by_font_cap(SDynPropRecValList *pThisList,
+ char const *strCapHead);
+
+#ifdef DUMP
+void
+SPropRecValList_dump(SRefPropRecValList *refList);
+#endif
+
+#define SPropContainer_value_int(contRecVal)\
+ ((contRecVal)->uValue.integerValue)
+#define SPropContainer_value_dbl(contRecVal)\
+ ((contRecVal)->uValue.doubleValue)
+#define SPropContainer_value_bool(contRecVal)\
+ ((contRecVal)->uValue.boolValue)
+#define SPropContainer_value_str(contRecVal)\
+ ((contRecVal)->uValue.dynStringValue)
+
+/******************************************************
+ Prototypes (xttmisc)
+ */
+
+/* strdup clone */
+char * XttXstrdup(char const *str);
+#undef xstrdup
+#define xstrdup(s) XttXstrdup((char const*)s)
+
+#endif /* !def _XTTCAP_H_ */
+
+/* end of file */
diff --git a/libXfont/src/Makefile.am b/libXfont/src/Makefile.am index 26551bc04..3f6575e99 100644 --- a/libXfont/src/Makefile.am +++ b/libXfont/src/Makefile.am @@ -1,68 +1,68 @@ -# -# Copyright © 2003 Keith Packard, Noah Levitt -# -# 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, and that the name of Keith Packard not be used in -# advertising or publicity pertaining to distribution of the software without -# specific, written prior permission. Keith Packard makes no -# representations about the suitability of this software for any purpose. It -# is provided "as is" without express or implied warranty. -# -# KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO -# EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR -# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -# PERFORMANCE OF THIS SOFTWARE. - -lib_LTLIBRARIES = libXfont.la - -AM_CFLAGS = $(OS_CFLAGS) $(CWARNFLAGS) - -if XFONT_FONTFILE -FONTFILE_DIR = fontfile -FONTFILE_LIB = fontfile/libfontfile.la -endif - -if XFONT_FREETYPE -FREETYPE_DIR = FreeType -FREETYPE_LIB = FreeType/libft.la -endif - -if XFONT_BITMAP -BITMAP_DIR = bitmap -BITMAP_LIB = bitmap/libbitmap.la -endif - -if XFONT_BUILTINS -BUILTINS_DIR = builtins -BUILTINS_LIB = builtins/libbuiltins.la -endif - -if XFONT_FC -FC_DIR = fc -FC_LIB = fc/libfc.la -endif - -UTIL_DIR = util -UTIL_LIB = util/libutil.la - -STUBS_LIB = stubs/libstubs.la -STUBS_DIR = stubs - -SUBDIRS=\ - $(FONTFILE_DIR) $(FREETYPE_DIR) $(BITMAP_DIR) \ - $(BUILTINS_DIR) $(FC_DIR) $(UTIL_DIR) $(STUBS_DIR) - -libXfont_la_LIBADD = \ - $(FONTFILE_LIB) $(FREETYPE_LIB) $(BITMAP_LIB) \ - $(BUILTINS_LIB) $(FC_LIB) $(UTIL_LIB) $(STUBS_LIB) \ - $(FREETYPE_LIBS) $(Z_LIBS) $(MATH_LIBS) $(XFONT_LIBS) - -libXfont_la_SOURCES = dummy.c - -libXfont_la_LDFLAGS = -version-number 1:4:1 +#
+# Copyright © 2003 Keith Packard, Noah Levitt
+#
+# 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, and that the name of Keith Packard not be used in
+# advertising or publicity pertaining to distribution of the software without
+# specific, written prior permission. Keith Packard makes no
+# representations about the suitability of this software for any purpose. It
+# is provided "as is" without express or implied warranty.
+#
+# KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+# EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+lib_LTLIBRARIES = libXfont.la
+
+AM_CFLAGS = $(OS_CFLAGS) $(CWARNFLAGS)
+
+if XFONT_FONTFILE
+FONTFILE_DIR = fontfile
+FONTFILE_LIB = fontfile/libfontfile.la
+endif
+
+if XFONT_FREETYPE
+FREETYPE_DIR = FreeType
+FREETYPE_LIB = FreeType/libft.la
+endif
+
+if XFONT_BITMAP
+BITMAP_DIR = bitmap
+BITMAP_LIB = bitmap/libbitmap.la
+endif
+
+if XFONT_BUILTINS
+BUILTINS_DIR = builtins
+BUILTINS_LIB = builtins/libbuiltins.la
+endif
+
+if XFONT_FC
+FC_DIR = fc
+FC_LIB = fc/libfc.la
+endif
+
+UTIL_DIR = util
+UTIL_LIB = util/libutil.la
+
+STUBS_LIB = stubs/libstubs.la
+STUBS_DIR = stubs
+
+SUBDIRS=\
+ $(FONTFILE_DIR) $(FREETYPE_DIR) $(BITMAP_DIR) \
+ $(BUILTINS_DIR) $(FC_DIR) $(UTIL_DIR) $(STUBS_DIR)
+
+libXfont_la_LIBADD = \
+ $(FONTFILE_LIB) $(FREETYPE_LIB) $(BITMAP_LIB) \
+ $(BUILTINS_LIB) $(FC_LIB) $(UTIL_LIB) $(STUBS_LIB) \
+ $(FREETYPE_LIBS) $(Z_LIBS) $(MATH_LIBS) $(XFONT_LIBS)
+
+libXfont_la_SOURCES = dummy.c
+
+libXfont_la_LDFLAGS = -version-number 1:4:1
diff --git a/libXfont/src/bitmap/bdfread.c b/libXfont/src/bitmap/bdfread.c index 2464c03cc..1ae3b85cd 100644 --- a/libXfont/src/bitmap/bdfread.c +++ b/libXfont/src/bitmap/bdfread.c @@ -1,955 +1,955 @@ -/************************************************************************ -Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -************************************************************************/ - -/* - -Copyright 1994, 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. - -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <ctype.h> -#include <X11/fonts/fntfilst.h> -#include <X11/fonts/fontutil.h> -/* use bitmap structure */ -#include <X11/fonts/bitmap.h> -#include <X11/fonts/bdfint.h> - -#if HAVE_STDINT_H -#include <stdint.h> -#elif !defined(INT32_MAX) -#define INT32_MAX 0x7fffffff -#endif - -#define INDICES 256 -#define MAXENCODING 0xFFFF -#define BDFLINELEN 1024 - -static Bool bdfPadToTerminal(FontPtr pFont); -extern int bdfFileLineNum; - -/***====================================================================***/ - -static Bool -bdfReadBitmap(CharInfoPtr pCI, FontFilePtr file, int bit, int byte, - int glyph, int scan, CARD32 *sizes) -{ - int widthBits, - widthBytes, - widthHexChars; - int height, - row; - int i, - inLineLen, - nextByte; - unsigned char *pInBits, - *picture, - *line = NULL; - unsigned char lineBuf[BDFLINELEN]; - - widthBits = GLYPHWIDTHPIXELS(pCI); - height = GLYPHHEIGHTPIXELS(pCI); - - widthBytes = BYTES_PER_ROW(widthBits, glyph); - if (widthBytes * height > 0) { - picture = malloc(widthBytes * height); - if (!picture) { - bdfError("Couldn't allocate picture (%d*%d)\n", widthBytes, height); - goto BAILOUT; - } - } else - picture = NULL; - pCI->bits = (char *) picture; - - if (sizes) { - for (i = 0; i < GLYPHPADOPTIONS; i++) - sizes[i] += BYTES_PER_ROW(widthBits, (1 << i)) * height; - } - nextByte = 0; - widthHexChars = BYTES_PER_ROW(widthBits, 1); - -/* 5/31/89 (ef) -- hack, hack, hack. what *am* I supposed to do with */ -/* 0 width characters? */ - - for (row = 0; row < height; row++) { - line = bdfGetLine(file, lineBuf, BDFLINELEN); - if (!line) - break; - - if (widthBits == 0) { - if ((!line) || (bdfIsPrefix(line, "ENDCHAR"))) - break; - else - continue; - } - pInBits = line; - inLineLen = strlen((char *) pInBits); - - if (inLineLen & 1) { - bdfError("odd number of characters in hex encoding\n"); - line[inLineLen++] = '0'; - line[inLineLen] = '\0'; - } - inLineLen >>= 1; - i = inLineLen; - if (i > widthHexChars) - i = widthHexChars; - for (; i > 0; i--, pInBits += 2) - picture[nextByte++] = bdfHexByte(pInBits); - - /* pad if line is too short */ - if (inLineLen < widthHexChars) { - for (i = widthHexChars - inLineLen; i > 0; i--) - picture[nextByte++] = 0; - } else { - unsigned char mask; - - mask = 0xff << (8 - (widthBits & 0x7)); - if (mask && picture[nextByte - 1] & ~mask) { - picture[nextByte - 1] &= mask; - } - } - - if (widthBytes > widthHexChars) { - i = widthBytes - widthHexChars; - while (i-- > 0) - picture[nextByte++] = 0; - } - } - - if ((line && (!bdfIsPrefix(line, "ENDCHAR"))) || (height == 0)) - line = bdfGetLine(file, lineBuf, BDFLINELEN); - - if ((!line) || (!bdfIsPrefix(line, "ENDCHAR"))) { - bdfError("missing 'ENDCHAR'\n"); - goto BAILOUT; - } - if (nextByte != height * widthBytes) { - bdfError("bytes != rows * bytes_per_row (%d != %d * %d)\n", - nextByte, height, widthBytes); - goto BAILOUT; - } - if (picture != NULL) { - if (bit == LSBFirst) - BitOrderInvert(picture, nextByte); - if (bit != byte) { - if (scan == 2) - TwoByteSwap(picture, nextByte); - else if (scan == 4) - FourByteSwap(picture, nextByte); - } - } - return (TRUE); -BAILOUT: - if (picture) - free(picture); - pCI->bits = NULL; - return (FALSE); -} - -/***====================================================================***/ - -static Bool -bdfSkipBitmap(FontFilePtr file, int height) -{ - unsigned char *line; - int i = 0; - unsigned char lineBuf[BDFLINELEN]; - - do { - line = bdfGetLine(file, lineBuf, BDFLINELEN); - i++; - } while (line && !bdfIsPrefix(line, "ENDCHAR") && i <= height); - - if (i > 1 && line && !bdfIsPrefix(line, "ENDCHAR")) { - bdfError("Error in bitmap, missing 'ENDCHAR'\n"); - return (FALSE); - } - return (TRUE); -} - -/***====================================================================***/ - -static void -bdfFreeFontBits(FontPtr pFont) -{ - BitmapFontPtr bitmapFont; - BitmapExtraPtr bitmapExtra; - int i, nencoding; - - bitmapFont = (BitmapFontPtr) pFont->fontPrivate; - bitmapExtra = (BitmapExtraPtr) bitmapFont->bitmapExtra; - free(bitmapFont->ink_metrics); - if(bitmapFont->encoding) { - nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * - (pFont->info.lastRow - pFont->info.firstRow + 1); - for(i=0; i<NUM_SEGMENTS(nencoding); i++) - free(bitmapFont->encoding[i]); - } - free(bitmapFont->encoding); - for (i = 0; i < bitmapFont->num_chars; i++) - free(bitmapFont->metrics[i].bits); - free(bitmapFont->metrics); - if (bitmapExtra) - { - free (bitmapExtra->glyphNames); - free (bitmapExtra->sWidths); - free (bitmapExtra); - } - free(pFont->info.props); - free(bitmapFont); -} - - -static Bool -bdfReadCharacters(FontFilePtr file, FontPtr pFont, bdfFileState *pState, - int bit, int byte, int glyph, int scan) -{ - unsigned char *line; - register CharInfoPtr ci; - int i, - ndx, - nchars, - nignored; - unsigned int char_row, char_col; - int numEncodedGlyphs = 0; - CharInfoPtr *bdfEncoding[256]; - BitmapFontPtr bitmapFont; - BitmapExtraPtr bitmapExtra; - CARD32 *bitmapsSizes; - unsigned char lineBuf[BDFLINELEN]; - int nencoding; - - bitmapFont = (BitmapFontPtr) pFont->fontPrivate; - bitmapExtra = (BitmapExtraPtr) bitmapFont->bitmapExtra; - - if (bitmapExtra) { - bitmapsSizes = bitmapExtra->bitmapsSizes; - for (i = 0; i < GLYPHPADOPTIONS; i++) - bitmapsSizes[i] = 0; - } else - bitmapsSizes = NULL; - - bzero(bdfEncoding, sizeof(bdfEncoding)); - bitmapFont->metrics = NULL; - ndx = 0; - - line = bdfGetLine(file, lineBuf, BDFLINELEN); - - if ((!line) || (sscanf((char *) line, "CHARS %d", &nchars) != 1)) { - bdfError("bad 'CHARS' in bdf file\n"); - return (FALSE); - } - if (nchars < 1) { - bdfError("invalid number of CHARS in BDF file\n"); - return (FALSE); - } - if (nchars > INT32_MAX / sizeof(CharInfoRec)) { - bdfError("Couldn't allocate pCI (%d*%d)\n", nchars, - sizeof(CharInfoRec)); - goto BAILOUT; - } - ci = calloc(nchars, sizeof(CharInfoRec)); - if (!ci) { - bdfError("Couldn't allocate pCI (%d*%d)\n", nchars, - sizeof(CharInfoRec)); - goto BAILOUT; - } - bitmapFont->metrics = ci; - - if (bitmapExtra) { - bitmapExtra->glyphNames = malloc(nchars * sizeof(Atom)); - if (!bitmapExtra->glyphNames) { - bdfError("Couldn't allocate glyphNames (%d*%d)\n", - nchars, sizeof(Atom)); - goto BAILOUT; - } - } - if (bitmapExtra) { - bitmapExtra->sWidths = malloc(nchars * sizeof(int)); - if (!bitmapExtra->sWidths) { - bdfError("Couldn't allocate sWidth (%d *%d)\n", - nchars, sizeof(int)); - return FALSE; - } - } - line = bdfGetLine(file, lineBuf, BDFLINELEN); - pFont->info.firstRow = 256; - pFont->info.lastRow = 0; - pFont->info.firstCol = 256; - pFont->info.lastCol = 0; - nignored = 0; - for (ndx = 0; (ndx < nchars) && (line) && (bdfIsPrefix(line, "STARTCHAR"));) { - int t; - int wx; /* x component of width */ - int wy; /* y component of width */ - int bw; /* bounding-box width */ - int bh; /* bounding-box height */ - int bl; /* bounding-box left */ - int bb; /* bounding-box bottom */ - int enc, - enc2; /* encoding */ - unsigned char *p; /* temp pointer into line */ - char charName[100]; - int ignore; - - if (sscanf((char *) line, "STARTCHAR %s", charName) != 1) { - bdfError("bad character name in BDF file\n"); - goto BAILOUT; /* bottom of function, free and return error */ - } - if (bitmapExtra) - bitmapExtra->glyphNames[ndx] = bdfForceMakeAtom(charName, NULL); - - line = bdfGetLine(file, lineBuf, BDFLINELEN); - if (!line || (t = sscanf((char *) line, "ENCODING %d %d", &enc, &enc2)) < 1) { - bdfError("bad 'ENCODING' in BDF file\n"); - goto BAILOUT; - } - if (enc < -1 || (t == 2 && enc2 < -1)) { - bdfError("bad ENCODING value"); - goto BAILOUT; - } - if (t == 2 && enc == -1) - enc = enc2; - ignore = 0; - if (enc == -1) { - if (!bitmapExtra) { - nignored++; - ignore = 1; - } - } else if (enc > MAXENCODING) { - bdfError("char '%s' has encoding too large (%d)\n", - charName, enc); - } else { - char_row = (enc >> 8) & 0xFF; - char_col = enc & 0xFF; - if (char_row < pFont->info.firstRow) - pFont->info.firstRow = char_row; - if (char_row > pFont->info.lastRow) - pFont->info.lastRow = char_row; - if (char_col < pFont->info.firstCol) - pFont->info.firstCol = char_col; - if (char_col > pFont->info.lastCol) - pFont->info.lastCol = char_col; - if (bdfEncoding[char_row] == (CharInfoPtr *) NULL) { - bdfEncoding[char_row] = malloc(256 * sizeof(CharInfoPtr)); - if (!bdfEncoding[char_row]) { - bdfError("Couldn't allocate row %d of encoding (%d*%d)\n", - char_row, INDICES, sizeof(CharInfoPtr)); - goto BAILOUT; - } - for (i = 0; i < 256; i++) - bdfEncoding[char_row][i] = (CharInfoPtr) NULL; - } - if (bdfEncoding[char_row] != NULL) { - bdfEncoding[char_row][char_col] = ci; - numEncodedGlyphs++; - } - } - - line = bdfGetLine(file, lineBuf, BDFLINELEN); - if ((!line) || (sscanf((char *) line, "SWIDTH %d %d", &wx, &wy) != 2)) { - bdfError("bad 'SWIDTH'\n"); - goto BAILOUT; - } - if (wy != 0) { - bdfError("SWIDTH y value must be zero\n"); - goto BAILOUT; - } - if (bitmapExtra) - bitmapExtra->sWidths[ndx] = wx; - -/* 5/31/89 (ef) -- we should be able to ditch the character and recover */ -/* from all of these. */ - - line = bdfGetLine(file, lineBuf, BDFLINELEN); - if ((!line) || (sscanf((char *) line, "DWIDTH %d %d", &wx, &wy) != 2)) { - bdfError("bad 'DWIDTH'\n"); - goto BAILOUT; - } - if (wy != 0) { - bdfError("DWIDTH y value must be zero\n"); - goto BAILOUT; - } - line = bdfGetLine(file, lineBuf, BDFLINELEN); - if ((!line) || (sscanf((char *) line, "BBX %d %d %d %d", &bw, &bh, &bl, &bb) != 4)) { - bdfError("bad 'BBX'\n"); - goto BAILOUT; - } - if ((bh < 0) || (bw < 0)) { - bdfError("character '%s' has a negative sized bitmap, %dx%d\n", - charName, bw, bh); - goto BAILOUT; - } - line = bdfGetLine(file, lineBuf, BDFLINELEN); - if ((line) && (bdfIsPrefix(line, "ATTRIBUTES"))) { - for (p = line + strlen("ATTRIBUTES "); - (*p == ' ') || (*p == '\t'); - p++) - /* empty for loop */ ; - ci->metrics.attributes = (bdfHexByte(p) << 8) + bdfHexByte(p + 2); - line = bdfGetLine(file, lineBuf, BDFLINELEN); - } else - ci->metrics.attributes = 0; - - if (!line || !bdfIsPrefix(line, "BITMAP")) { - bdfError("missing 'BITMAP'\n"); - goto BAILOUT; - } - /* collect data for generated properties */ - if ((strlen(charName) == 1)) { - if ((charName[0] >= '0') && (charName[0] <= '9')) { - pState->digitWidths += wx; - pState->digitCount++; - } else if (charName[0] == 'x') { - pState->exHeight = (bh + bb) <= 0 ? bh : bh + bb; - } - } - if (!ignore) { - ci->metrics.leftSideBearing = bl; - ci->metrics.rightSideBearing = bl + bw; - ci->metrics.ascent = bh + bb; - ci->metrics.descent = -bb; - ci->metrics.characterWidth = wx; - ci->bits = NULL; - bdfReadBitmap(ci, file, bit, byte, glyph, scan, bitmapsSizes); - ci++; - ndx++; - } else - bdfSkipBitmap(file, bh); - - line = bdfGetLine(file, lineBuf, BDFLINELEN); /* get STARTCHAR or - * ENDFONT */ - } - - if (ndx + nignored != nchars) { - bdfError("%d too few characters\n", nchars - (ndx + nignored)); - goto BAILOUT; - } - nchars = ndx; - bitmapFont->num_chars = nchars; - if ((line) && (bdfIsPrefix(line, "STARTCHAR"))) { - bdfError("more characters than specified\n"); - goto BAILOUT; - } - if ((!line) || (!bdfIsPrefix(line, "ENDFONT"))) { - bdfError("missing 'ENDFONT'\n"); - goto BAILOUT; - } - if (numEncodedGlyphs == 0) - bdfWarning("No characters with valid encodings\n"); - - nencoding = (pFont->info.lastRow - pFont->info.firstRow + 1) * - (pFont->info.lastCol - pFont->info.firstCol + 1); - bitmapFont->encoding = calloc(NUM_SEGMENTS(nencoding),sizeof(CharInfoPtr*)); - if (!bitmapFont->encoding) { - bdfError("Couldn't allocate ppCI (%d,%d)\n", - NUM_SEGMENTS(nencoding), - sizeof(CharInfoPtr*)); - goto BAILOUT; - } - pFont->info.allExist = TRUE; - i = 0; - for (char_row = pFont->info.firstRow; - char_row <= pFont->info.lastRow; - char_row++) { - if (bdfEncoding[char_row] == (CharInfoPtr *) NULL) { - pFont->info.allExist = FALSE; - i += pFont->info.lastCol - pFont->info.firstCol + 1; - } else { - for (char_col = pFont->info.firstCol; - char_col <= pFont->info.lastCol; - char_col++) { - if (!bdfEncoding[char_row][char_col]) - pFont->info.allExist = FALSE; - else { - if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) { - bitmapFont->encoding[SEGMENT_MAJOR(i)]= - calloc(BITMAP_FONT_SEGMENT_SIZE, - sizeof(CharInfoPtr)); - if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) - goto BAILOUT; - } - ACCESSENCODINGL(bitmapFont->encoding,i) = - bdfEncoding[char_row][char_col]; - } - i++; - } - } - } - for (i = 0; i < 256; i++) - if (bdfEncoding[i]) - free(bdfEncoding[i]); - return (TRUE); -BAILOUT: - for (i = 0; i < 256; i++) - if (bdfEncoding[i]) - free(bdfEncoding[i]); - /* bdfFreeFontBits will clean up the rest */ - return (FALSE); -} - -/***====================================================================***/ - -static Bool -bdfReadHeader(FontFilePtr file, bdfFileState *pState) -{ - unsigned char *line; - char namebuf[BDFLINELEN]; - unsigned char lineBuf[BDFLINELEN]; - - line = bdfGetLine(file, lineBuf, BDFLINELEN); - if (!line || sscanf((char *) line, "STARTFONT %s", namebuf) != 1 || - !bdfStrEqual(namebuf, "2.1")) { - bdfError("bad 'STARTFONT'\n"); - return (FALSE); - } - line = bdfGetLine(file, lineBuf, BDFLINELEN); - if (!line || sscanf((char *) line, "FONT %[^\n]", pState->fontName) != 1) { - bdfError("bad 'FONT'\n"); - return (FALSE); - } - line = bdfGetLine(file, lineBuf, BDFLINELEN); - if (!line || !bdfIsPrefix(line, "SIZE")) { - bdfError("missing 'SIZE'\n"); - return (FALSE); - } - if (sscanf((char *) line, "SIZE %f%d%d", &pState->pointSize, - &pState->resolution_x, &pState->resolution_y) != 3) { - bdfError("bad 'SIZE'\n"); - return (FALSE); - } - if (pState->pointSize < 1 || - pState->resolution_x < 1 || pState->resolution_y < 1) { - bdfError("SIZE values must be > 0\n"); - return (FALSE); - } - line = bdfGetLine(file, lineBuf, BDFLINELEN); - if (!line || !bdfIsPrefix(line, "FONTBOUNDINGBOX")) { - bdfError("missing 'FONTBOUNDINGBOX'\n"); - return (FALSE); - } - return (TRUE); -} - -/***====================================================================***/ - -static Bool -bdfReadProperties(FontFilePtr file, FontPtr pFont, bdfFileState *pState) -{ - int nProps, props_left, - nextProp; - char *stringProps; - FontPropPtr props; - char namebuf[BDFLINELEN], - secondbuf[BDFLINELEN], - thirdbuf[BDFLINELEN]; - unsigned char *line; - unsigned char lineBuf[BDFLINELEN]; - BitmapFontPtr bitmapFont = (BitmapFontPtr) pFont->fontPrivate; - - line = bdfGetLine(file, lineBuf, BDFLINELEN); - if (!line || !bdfIsPrefix(line, "STARTPROPERTIES")) { - bdfError("missing 'STARTPROPERTIES'\n"); - return (FALSE); - } - if (sscanf((char *) line, "STARTPROPERTIES %d", &nProps) != 1) { - bdfError("bad 'STARTPROPERTIES'\n"); - return (FALSE); - } - pFont->info.isStringProp = NULL; - pFont->info.props = NULL; - pFont->info.nprops = 0; - - stringProps = malloc((nProps + BDF_GENPROPS) * sizeof(char)); - pFont->info.isStringProp = stringProps; - if (stringProps == NULL) { - bdfError("Couldn't allocate stringProps (%d*%d)\n", - (nProps + BDF_GENPROPS), sizeof(Bool)); - goto BAILOUT; - } - pFont->info.props = props = calloc(nProps + BDF_GENPROPS, - sizeof(FontPropRec)); - if (props == NULL) { - bdfError("Couldn't allocate props (%d*%d)\n", nProps + BDF_GENPROPS, - sizeof(FontPropRec)); - goto BAILOUT; - } - - nextProp = 0; - props_left = nProps; - while (props_left-- > 0) { - line = bdfGetLine(file, lineBuf, BDFLINELEN); - if (line == NULL || bdfIsPrefix(line, "ENDPROPERTIES")) { - bdfError("\"STARTPROPERTIES %d\" followed by only %d properties\n", - nProps, nProps - props_left - 1); - goto BAILOUT; - } - while (*line && isspace(*line)) - line++; - - switch (sscanf((char *) line, "%s%s%s", namebuf, secondbuf, thirdbuf)) { - default: - bdfError("missing '%s' parameter value\n", namebuf); - goto BAILOUT; - - case 2: - /* - * Possibilites include: valid quoted string with no white space - * valid integer value invalid value - */ - if (secondbuf[0] == '"') { - stringProps[nextProp] = TRUE; - props[nextProp].value = - bdfGetPropertyValue((char *)line + strlen(namebuf) + 1); - if (!props[nextProp].value) - goto BAILOUT; - break; - } else if (bdfIsInteger(secondbuf)) { - stringProps[nextProp] = FALSE; - props[nextProp].value = atoi(secondbuf); - break; - } else { - bdfError("invalid '%s' parameter value\n", namebuf); - goto BAILOUT; - } - - case 3: - /* - * Possibilites include: valid quoted string with some white space - * invalid value (reject even if second string is integer) - */ - if (secondbuf[0] == '"') { - stringProps[nextProp] = TRUE; - props[nextProp].value = - bdfGetPropertyValue((char *)line + strlen(namebuf) + 1); - if (!props[nextProp].value) - goto BAILOUT; - break; - } else { - bdfError("invalid '%s' parameter value\n", namebuf); - goto BAILOUT; - } - } - props[nextProp].name = bdfForceMakeAtom(namebuf, NULL); - if (props[nextProp].name == None) { - bdfError("Empty property name.\n"); - goto BAILOUT; - } - if (!bdfSpecialProperty(pFont, &props[nextProp], - stringProps[nextProp], pState)) - nextProp++; - } - - line = bdfGetLine(file, lineBuf, BDFLINELEN); - if (!line || !bdfIsPrefix(line, "ENDPROPERTIES")) { - bdfError("missing 'ENDPROPERTIES'\n"); - goto BAILOUT; - } - if (!pState->haveFontAscent || !pState->haveFontDescent) { - bdfError("missing 'FONT_ASCENT' or 'FONT_DESCENT' properties\n"); - goto BAILOUT; - } - if (bitmapFont->bitmapExtra) { - bitmapFont->bitmapExtra->info.fontAscent = pFont->info.fontAscent; - bitmapFont->bitmapExtra->info.fontDescent = pFont->info.fontDescent; - } - if (!pState->pointSizeProp) { - props[nextProp].name = bdfForceMakeAtom("POINT_SIZE", NULL); - props[nextProp].value = (INT32) (pState->pointSize * 10.0); - stringProps[nextProp] = FALSE; - pState->pointSizeProp = &props[nextProp]; - nextProp++; - } - if (!pState->fontProp) { - props[nextProp].name = bdfForceMakeAtom("FONT", NULL); - props[nextProp].value = (INT32) bdfForceMakeAtom(pState->fontName, NULL); - stringProps[nextProp] = TRUE; - pState->fontProp = &props[nextProp]; - nextProp++; - } - if (!pState->weightProp) { - props[nextProp].name = bdfForceMakeAtom("WEIGHT", NULL); - props[nextProp].value = -1; /* computed later */ - stringProps[nextProp] = FALSE; - pState->weightProp = &props[nextProp]; - nextProp++; - } - if (!pState->resolutionProp && - pState->resolution_x == pState->resolution_y) { - props[nextProp].name = bdfForceMakeAtom("RESOLUTION", NULL); - props[nextProp].value = (INT32) ((pState->resolution_x * 100.0) / 72.27); - stringProps[nextProp] = FALSE; - pState->resolutionProp = &props[nextProp]; - nextProp++; - } - if (!pState->resolutionXProp) { - props[nextProp].name = bdfForceMakeAtom("RESOLUTION_X", NULL); - props[nextProp].value = (INT32) pState->resolution_x; - stringProps[nextProp] = FALSE; - pState->resolutionProp = &props[nextProp]; - nextProp++; - } - if (!pState->resolutionYProp) { - props[nextProp].name = bdfForceMakeAtom("RESOLUTION_Y", NULL); - props[nextProp].value = (INT32) pState->resolution_y; - stringProps[nextProp] = FALSE; - pState->resolutionProp = &props[nextProp]; - nextProp++; - } - if (!pState->xHeightProp) { - props[nextProp].name = bdfForceMakeAtom("X_HEIGHT", NULL); - props[nextProp].value = -1; /* computed later */ - stringProps[nextProp] = FALSE; - pState->xHeightProp = &props[nextProp]; - nextProp++; - } - if (!pState->quadWidthProp) { - props[nextProp].name = bdfForceMakeAtom("QUAD_WIDTH", NULL); - props[nextProp].value = -1; /* computed later */ - stringProps[nextProp] = FALSE; - pState->quadWidthProp = &props[nextProp]; - nextProp++; - } - pFont->info.nprops = nextProp; - return (TRUE); -BAILOUT: - if (pFont->info.isStringProp) { - free(pFont->info.isStringProp); - pFont->info.isStringProp = NULL; - } - if (pFont->info.props) { - free(pFont->info.props); - pFont->info.props = NULL; - } - while (line && bdfIsPrefix(line, "ENDPROPERTIES")) - line = bdfGetLine(file, lineBuf, BDFLINELEN); - return (FALSE); -} - -/***====================================================================***/ - -static void -bdfUnloadFont(FontPtr pFont) -{ - bdfFreeFontBits (pFont); - DestroyFontRec(pFont); -} - -int -bdfReadFont(FontPtr pFont, FontFilePtr file, - int bit, int byte, int glyph, int scan) -{ - bdfFileState state; - xCharInfo *min, - *max; - BitmapFontPtr bitmapFont; - - pFont->fontPrivate = 0; - - bzero(&state, sizeof(bdfFileState)); - bdfFileLineNum = 0; - - if (!bdfReadHeader(file, &state)) - goto BAILOUT; - - bitmapFont = calloc(1, sizeof(BitmapFontRec)); - if (!bitmapFont) { - bdfError("Couldn't allocate bitmapFontRec (%d)\n", sizeof(BitmapFontRec)); - goto BAILOUT; - } - - pFont->fontPrivate = (pointer) bitmapFont; - bitmapFont->metrics = 0; - bitmapFont->ink_metrics = 0; - bitmapFont->bitmaps = 0; - bitmapFont->encoding = 0; - bitmapFont->pDefault = NULL; - - bitmapFont->bitmapExtra = calloc(1, sizeof(BitmapExtraRec)); - if (!bitmapFont->bitmapExtra) { - bdfError("Couldn't allocate bitmapExtra (%d)\n", sizeof(BitmapExtraRec)); - goto BAILOUT; - } - - bitmapFont->bitmapExtra->glyphNames = 0; - bitmapFont->bitmapExtra->sWidths = 0; - - if (!bdfReadProperties(file, pFont, &state)) - goto BAILOUT; - - if (!bdfReadCharacters(file, pFont, &state, bit, byte, glyph, scan)) - goto BAILOUT; - - if (state.haveDefaultCh) { - unsigned int r, c, cols; - - r = pFont->info.defaultCh >> 8; - c = pFont->info.defaultCh & 0xFF; - if (pFont->info.firstRow <= r && r <= pFont->info.lastRow && - pFont->info.firstCol <= c && c <= pFont->info.lastCol) { - cols = pFont->info.lastCol - pFont->info.firstCol + 1; - r = r - pFont->info.firstRow; - c = c - pFont->info.firstCol; - bitmapFont->pDefault = ACCESSENCODING(bitmapFont->encoding, - r * cols + c); - } - } - pFont->bit = bit; - pFont->byte = byte; - pFont->glyph = glyph; - pFont->scan = scan; - pFont->info.anamorphic = FALSE; - pFont->info.cachable = TRUE; - bitmapComputeFontBounds(pFont); - if (FontCouldBeTerminal(&pFont->info)) { - bdfPadToTerminal(pFont); - bitmapComputeFontBounds(pFont); - } - FontComputeInfoAccelerators(&pFont->info); - if (bitmapFont->bitmapExtra) - FontComputeInfoAccelerators(&bitmapFont->bitmapExtra->info); - if (pFont->info.constantMetrics) { - if (!bitmapAddInkMetrics(pFont)) { - bdfError("Failed to add bitmap ink metrics\n"); - goto BAILOUT; - } - } - if (bitmapFont->bitmapExtra) - bitmapFont->bitmapExtra->info.inkMetrics = pFont->info.inkMetrics; - - bitmapComputeFontInkBounds(pFont); -/* ComputeFontAccelerators (pFont); */ - - /* generate properties */ - min = &pFont->info.ink_minbounds; - max = &pFont->info.ink_maxbounds; - if (state.xHeightProp && (state.xHeightProp->value == -1)) - state.xHeightProp->value = state.exHeight ? - state.exHeight : min->ascent; - - if (state.quadWidthProp && (state.quadWidthProp->value == -1)) - state.quadWidthProp->value = state.digitCount ? - (INT32) (state.digitWidths / state.digitCount) : - (min->characterWidth + max->characterWidth) / 2; - - if (state.weightProp && (state.weightProp->value == -1)) - state.weightProp->value = bitmapComputeWeight(pFont); - - pFont->get_glyphs = bitmapGetGlyphs; - pFont->get_metrics = bitmapGetMetrics; - pFont->unload_font = bdfUnloadFont; - pFont->unload_glyphs = NULL; - return Successful; -BAILOUT: - if (pFont->fontPrivate) - bdfFreeFontBits (pFont); - return AllocError; -} - -int -bdfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file) -{ - FontRec font; - int ret; - - bzero(&font, sizeof (FontRec)); - - ret = bdfReadFont(&font, file, MSBFirst, LSBFirst, 1, 1); - if (ret == Successful) { - *pFontInfo = font.info; - font.info.props = 0; - font.info.isStringProp = 0; - font.info.nprops = 0; - bdfFreeFontBits (&font); - } - return ret; -} - -static Bool -bdfPadToTerminal(FontPtr pFont) -{ - BitmapFontPtr bitmapFont; - BitmapExtraPtr bitmapExtra; - int i; - int new_size; - CharInfoRec new; - int w, - h; - - bitmapFont = (BitmapFontPtr) pFont->fontPrivate; - - bzero(&new, sizeof(CharInfoRec)); - new.metrics.ascent = pFont->info.fontAscent; - new.metrics.descent = pFont->info.fontDescent; - new.metrics.leftSideBearing = 0; - new.metrics.rightSideBearing = pFont->info.minbounds.characterWidth; - new.metrics.characterWidth = new.metrics.rightSideBearing; - new_size = BYTES_FOR_GLYPH(&new, pFont->glyph); - - for (i = 0; i < bitmapFont->num_chars; i++) { - new.bits = malloc(new_size); - if (!new.bits) { - bdfError("Couldn't allocate bits (%d)\n", new_size); - return FALSE; - } - FontCharReshape(pFont, &bitmapFont->metrics[i], &new); - new.metrics.attributes = bitmapFont->metrics[i].metrics.attributes; - free(bitmapFont->metrics[i].bits); - bitmapFont->metrics[i] = new; - } - bitmapExtra = bitmapFont->bitmapExtra; - if (bitmapExtra) { - w = GLYPHWIDTHPIXELS(&new); - h = GLYPHHEIGHTPIXELS(&new); - for (i = 0; i < GLYPHPADOPTIONS; i++) - bitmapExtra->bitmapsSizes[i] = bitmapFont->num_chars * - (BYTES_PER_ROW(w, 1 << i) * h); - } - return TRUE; -} +/************************************************************************
+Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+************************************************************************/
+
+/*
+
+Copyright 1994, 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.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <X11/fonts/fntfilst.h>
+#include <X11/fonts/fontutil.h>
+/* use bitmap structure */
+#include <X11/fonts/bitmap.h>
+#include <X11/fonts/bdfint.h>
+
+#if HAVE_STDINT_H
+#include <stdint.h>
+#elif !defined(INT32_MAX)
+#define INT32_MAX 0x7fffffff
+#endif
+
+#define INDICES 256
+#define MAXENCODING 0xFFFF
+#define BDFLINELEN 1024
+
+static Bool bdfPadToTerminal(FontPtr pFont);
+extern int bdfFileLineNum;
+
+/***====================================================================***/
+
+static Bool
+bdfReadBitmap(CharInfoPtr pCI, FontFilePtr file, int bit, int byte,
+ int glyph, int scan, CARD32 *sizes)
+{
+ int widthBits,
+ widthBytes,
+ widthHexChars;
+ int height,
+ row;
+ int i,
+ inLineLen,
+ nextByte;
+ unsigned char *pInBits,
+ *picture,
+ *line = NULL;
+ unsigned char lineBuf[BDFLINELEN];
+
+ widthBits = GLYPHWIDTHPIXELS(pCI);
+ height = GLYPHHEIGHTPIXELS(pCI);
+
+ widthBytes = BYTES_PER_ROW(widthBits, glyph);
+ if (widthBytes * height > 0) {
+ picture = malloc(widthBytes * height);
+ if (!picture) {
+ bdfError("Couldn't allocate picture (%d*%d)\n", widthBytes, height);
+ goto BAILOUT;
+ }
+ } else
+ picture = NULL;
+ pCI->bits = (char *) picture;
+
+ if (sizes) {
+ for (i = 0; i < GLYPHPADOPTIONS; i++)
+ sizes[i] += BYTES_PER_ROW(widthBits, (1 << i)) * height;
+ }
+ nextByte = 0;
+ widthHexChars = BYTES_PER_ROW(widthBits, 1);
+
+/* 5/31/89 (ef) -- hack, hack, hack. what *am* I supposed to do with */
+/* 0 width characters? */
+
+ for (row = 0; row < height; row++) {
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+ if (!line)
+ break;
+
+ if (widthBits == 0) {
+ if ((!line) || (bdfIsPrefix(line, "ENDCHAR")))
+ break;
+ else
+ continue;
+ }
+ pInBits = line;
+ inLineLen = strlen((char *) pInBits);
+
+ if (inLineLen & 1) {
+ bdfError("odd number of characters in hex encoding\n");
+ line[inLineLen++] = '0';
+ line[inLineLen] = '\0';
+ }
+ inLineLen >>= 1;
+ i = inLineLen;
+ if (i > widthHexChars)
+ i = widthHexChars;
+ for (; i > 0; i--, pInBits += 2)
+ picture[nextByte++] = bdfHexByte(pInBits);
+
+ /* pad if line is too short */
+ if (inLineLen < widthHexChars) {
+ for (i = widthHexChars - inLineLen; i > 0; i--)
+ picture[nextByte++] = 0;
+ } else {
+ unsigned char mask;
+
+ mask = 0xff << (8 - (widthBits & 0x7));
+ if (mask && picture[nextByte - 1] & ~mask) {
+ picture[nextByte - 1] &= mask;
+ }
+ }
+
+ if (widthBytes > widthHexChars) {
+ i = widthBytes - widthHexChars;
+ while (i-- > 0)
+ picture[nextByte++] = 0;
+ }
+ }
+
+ if ((line && (!bdfIsPrefix(line, "ENDCHAR"))) || (height == 0))
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+
+ if ((!line) || (!bdfIsPrefix(line, "ENDCHAR"))) {
+ bdfError("missing 'ENDCHAR'\n");
+ goto BAILOUT;
+ }
+ if (nextByte != height * widthBytes) {
+ bdfError("bytes != rows * bytes_per_row (%d != %d * %d)\n",
+ nextByte, height, widthBytes);
+ goto BAILOUT;
+ }
+ if (picture != NULL) {
+ if (bit == LSBFirst)
+ BitOrderInvert(picture, nextByte);
+ if (bit != byte) {
+ if (scan == 2)
+ TwoByteSwap(picture, nextByte);
+ else if (scan == 4)
+ FourByteSwap(picture, nextByte);
+ }
+ }
+ return (TRUE);
+BAILOUT:
+ if (picture)
+ free(picture);
+ pCI->bits = NULL;
+ return (FALSE);
+}
+
+/***====================================================================***/
+
+static Bool
+bdfSkipBitmap(FontFilePtr file, int height)
+{
+ unsigned char *line;
+ int i = 0;
+ unsigned char lineBuf[BDFLINELEN];
+
+ do {
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+ i++;
+ } while (line && !bdfIsPrefix(line, "ENDCHAR") && i <= height);
+
+ if (i > 1 && line && !bdfIsPrefix(line, "ENDCHAR")) {
+ bdfError("Error in bitmap, missing 'ENDCHAR'\n");
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/***====================================================================***/
+
+static void
+bdfFreeFontBits(FontPtr pFont)
+{
+ BitmapFontPtr bitmapFont;
+ BitmapExtraPtr bitmapExtra;
+ int i, nencoding;
+
+ bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
+ bitmapExtra = (BitmapExtraPtr) bitmapFont->bitmapExtra;
+ free(bitmapFont->ink_metrics);
+ if(bitmapFont->encoding) {
+ nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
+ (pFont->info.lastRow - pFont->info.firstRow + 1);
+ for(i=0; i<NUM_SEGMENTS(nencoding); i++)
+ free(bitmapFont->encoding[i]);
+ }
+ free(bitmapFont->encoding);
+ for (i = 0; i < bitmapFont->num_chars; i++)
+ free(bitmapFont->metrics[i].bits);
+ free(bitmapFont->metrics);
+ if (bitmapExtra)
+ {
+ free (bitmapExtra->glyphNames);
+ free (bitmapExtra->sWidths);
+ free (bitmapExtra);
+ }
+ free(pFont->info.props);
+ free(bitmapFont);
+}
+
+
+static Bool
+bdfReadCharacters(FontFilePtr file, FontPtr pFont, bdfFileState *pState,
+ int bit, int byte, int glyph, int scan)
+{
+ unsigned char *line;
+ register CharInfoPtr ci;
+ int i,
+ ndx,
+ nchars,
+ nignored;
+ unsigned int char_row, char_col;
+ int numEncodedGlyphs = 0;
+ CharInfoPtr *bdfEncoding[256];
+ BitmapFontPtr bitmapFont;
+ BitmapExtraPtr bitmapExtra;
+ CARD32 *bitmapsSizes;
+ unsigned char lineBuf[BDFLINELEN];
+ int nencoding;
+
+ bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
+ bitmapExtra = (BitmapExtraPtr) bitmapFont->bitmapExtra;
+
+ if (bitmapExtra) {
+ bitmapsSizes = bitmapExtra->bitmapsSizes;
+ for (i = 0; i < GLYPHPADOPTIONS; i++)
+ bitmapsSizes[i] = 0;
+ } else
+ bitmapsSizes = NULL;
+
+ bzero(bdfEncoding, sizeof(bdfEncoding));
+ bitmapFont->metrics = NULL;
+ ndx = 0;
+
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+
+ if ((!line) || (sscanf((char *) line, "CHARS %d", &nchars) != 1)) {
+ bdfError("bad 'CHARS' in bdf file\n");
+ return (FALSE);
+ }
+ if (nchars < 1) {
+ bdfError("invalid number of CHARS in BDF file\n");
+ return (FALSE);
+ }
+ if (nchars > INT32_MAX / sizeof(CharInfoRec)) {
+ bdfError("Couldn't allocate pCI (%d*%d)\n", nchars,
+ sizeof(CharInfoRec));
+ goto BAILOUT;
+ }
+ ci = calloc(nchars, sizeof(CharInfoRec));
+ if (!ci) {
+ bdfError("Couldn't allocate pCI (%d*%d)\n", nchars,
+ sizeof(CharInfoRec));
+ goto BAILOUT;
+ }
+ bitmapFont->metrics = ci;
+
+ if (bitmapExtra) {
+ bitmapExtra->glyphNames = malloc(nchars * sizeof(Atom));
+ if (!bitmapExtra->glyphNames) {
+ bdfError("Couldn't allocate glyphNames (%d*%d)\n",
+ nchars, sizeof(Atom));
+ goto BAILOUT;
+ }
+ }
+ if (bitmapExtra) {
+ bitmapExtra->sWidths = malloc(nchars * sizeof(int));
+ if (!bitmapExtra->sWidths) {
+ bdfError("Couldn't allocate sWidth (%d *%d)\n",
+ nchars, sizeof(int));
+ return FALSE;
+ }
+ }
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+ pFont->info.firstRow = 256;
+ pFont->info.lastRow = 0;
+ pFont->info.firstCol = 256;
+ pFont->info.lastCol = 0;
+ nignored = 0;
+ for (ndx = 0; (ndx < nchars) && (line) && (bdfIsPrefix(line, "STARTCHAR"));) {
+ int t;
+ int wx; /* x component of width */
+ int wy; /* y component of width */
+ int bw; /* bounding-box width */
+ int bh; /* bounding-box height */
+ int bl; /* bounding-box left */
+ int bb; /* bounding-box bottom */
+ int enc,
+ enc2; /* encoding */
+ unsigned char *p; /* temp pointer into line */
+ char charName[100];
+ int ignore;
+
+ if (sscanf((char *) line, "STARTCHAR %s", charName) != 1) {
+ bdfError("bad character name in BDF file\n");
+ goto BAILOUT; /* bottom of function, free and return error */
+ }
+ if (bitmapExtra)
+ bitmapExtra->glyphNames[ndx] = bdfForceMakeAtom(charName, NULL);
+
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+ if (!line || (t = sscanf((char *) line, "ENCODING %d %d", &enc, &enc2)) < 1) {
+ bdfError("bad 'ENCODING' in BDF file\n");
+ goto BAILOUT;
+ }
+ if (enc < -1 || (t == 2 && enc2 < -1)) {
+ bdfError("bad ENCODING value");
+ goto BAILOUT;
+ }
+ if (t == 2 && enc == -1)
+ enc = enc2;
+ ignore = 0;
+ if (enc == -1) {
+ if (!bitmapExtra) {
+ nignored++;
+ ignore = 1;
+ }
+ } else if (enc > MAXENCODING) {
+ bdfError("char '%s' has encoding too large (%d)\n",
+ charName, enc);
+ } else {
+ char_row = (enc >> 8) & 0xFF;
+ char_col = enc & 0xFF;
+ if (char_row < pFont->info.firstRow)
+ pFont->info.firstRow = char_row;
+ if (char_row > pFont->info.lastRow)
+ pFont->info.lastRow = char_row;
+ if (char_col < pFont->info.firstCol)
+ pFont->info.firstCol = char_col;
+ if (char_col > pFont->info.lastCol)
+ pFont->info.lastCol = char_col;
+ if (bdfEncoding[char_row] == (CharInfoPtr *) NULL) {
+ bdfEncoding[char_row] = malloc(256 * sizeof(CharInfoPtr));
+ if (!bdfEncoding[char_row]) {
+ bdfError("Couldn't allocate row %d of encoding (%d*%d)\n",
+ char_row, INDICES, sizeof(CharInfoPtr));
+ goto BAILOUT;
+ }
+ for (i = 0; i < 256; i++)
+ bdfEncoding[char_row][i] = (CharInfoPtr) NULL;
+ }
+ if (bdfEncoding[char_row] != NULL) {
+ bdfEncoding[char_row][char_col] = ci;
+ numEncodedGlyphs++;
+ }
+ }
+
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+ if ((!line) || (sscanf((char *) line, "SWIDTH %d %d", &wx, &wy) != 2)) {
+ bdfError("bad 'SWIDTH'\n");
+ goto BAILOUT;
+ }
+ if (wy != 0) {
+ bdfError("SWIDTH y value must be zero\n");
+ goto BAILOUT;
+ }
+ if (bitmapExtra)
+ bitmapExtra->sWidths[ndx] = wx;
+
+/* 5/31/89 (ef) -- we should be able to ditch the character and recover */
+/* from all of these. */
+
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+ if ((!line) || (sscanf((char *) line, "DWIDTH %d %d", &wx, &wy) != 2)) {
+ bdfError("bad 'DWIDTH'\n");
+ goto BAILOUT;
+ }
+ if (wy != 0) {
+ bdfError("DWIDTH y value must be zero\n");
+ goto BAILOUT;
+ }
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+ if ((!line) || (sscanf((char *) line, "BBX %d %d %d %d", &bw, &bh, &bl, &bb) != 4)) {
+ bdfError("bad 'BBX'\n");
+ goto BAILOUT;
+ }
+ if ((bh < 0) || (bw < 0)) {
+ bdfError("character '%s' has a negative sized bitmap, %dx%d\n",
+ charName, bw, bh);
+ goto BAILOUT;
+ }
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+ if ((line) && (bdfIsPrefix(line, "ATTRIBUTES"))) {
+ for (p = line + strlen("ATTRIBUTES ");
+ (*p == ' ') || (*p == '\t');
+ p++)
+ /* empty for loop */ ;
+ ci->metrics.attributes = (bdfHexByte(p) << 8) + bdfHexByte(p + 2);
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+ } else
+ ci->metrics.attributes = 0;
+
+ if (!line || !bdfIsPrefix(line, "BITMAP")) {
+ bdfError("missing 'BITMAP'\n");
+ goto BAILOUT;
+ }
+ /* collect data for generated properties */
+ if ((strlen(charName) == 1)) {
+ if ((charName[0] >= '0') && (charName[0] <= '9')) {
+ pState->digitWidths += wx;
+ pState->digitCount++;
+ } else if (charName[0] == 'x') {
+ pState->exHeight = (bh + bb) <= 0 ? bh : bh + bb;
+ }
+ }
+ if (!ignore) {
+ ci->metrics.leftSideBearing = bl;
+ ci->metrics.rightSideBearing = bl + bw;
+ ci->metrics.ascent = bh + bb;
+ ci->metrics.descent = -bb;
+ ci->metrics.characterWidth = wx;
+ ci->bits = NULL;
+ bdfReadBitmap(ci, file, bit, byte, glyph, scan, bitmapsSizes);
+ ci++;
+ ndx++;
+ } else
+ bdfSkipBitmap(file, bh);
+
+ line = bdfGetLine(file, lineBuf, BDFLINELEN); /* get STARTCHAR or
+ * ENDFONT */
+ }
+
+ if (ndx + nignored != nchars) {
+ bdfError("%d too few characters\n", nchars - (ndx + nignored));
+ goto BAILOUT;
+ }
+ nchars = ndx;
+ bitmapFont->num_chars = nchars;
+ if ((line) && (bdfIsPrefix(line, "STARTCHAR"))) {
+ bdfError("more characters than specified\n");
+ goto BAILOUT;
+ }
+ if ((!line) || (!bdfIsPrefix(line, "ENDFONT"))) {
+ bdfError("missing 'ENDFONT'\n");
+ goto BAILOUT;
+ }
+ if (numEncodedGlyphs == 0)
+ bdfWarning("No characters with valid encodings\n");
+
+ nencoding = (pFont->info.lastRow - pFont->info.firstRow + 1) *
+ (pFont->info.lastCol - pFont->info.firstCol + 1);
+ bitmapFont->encoding = calloc(NUM_SEGMENTS(nencoding),sizeof(CharInfoPtr*));
+ if (!bitmapFont->encoding) {
+ bdfError("Couldn't allocate ppCI (%d,%d)\n",
+ NUM_SEGMENTS(nencoding),
+ sizeof(CharInfoPtr*));
+ goto BAILOUT;
+ }
+ pFont->info.allExist = TRUE;
+ i = 0;
+ for (char_row = pFont->info.firstRow;
+ char_row <= pFont->info.lastRow;
+ char_row++) {
+ if (bdfEncoding[char_row] == (CharInfoPtr *) NULL) {
+ pFont->info.allExist = FALSE;
+ i += pFont->info.lastCol - pFont->info.firstCol + 1;
+ } else {
+ for (char_col = pFont->info.firstCol;
+ char_col <= pFont->info.lastCol;
+ char_col++) {
+ if (!bdfEncoding[char_row][char_col])
+ pFont->info.allExist = FALSE;
+ else {
+ if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) {
+ bitmapFont->encoding[SEGMENT_MAJOR(i)]=
+ calloc(BITMAP_FONT_SEGMENT_SIZE,
+ sizeof(CharInfoPtr));
+ if (!bitmapFont->encoding[SEGMENT_MAJOR(i)])
+ goto BAILOUT;
+ }
+ ACCESSENCODINGL(bitmapFont->encoding,i) =
+ bdfEncoding[char_row][char_col];
+ }
+ i++;
+ }
+ }
+ }
+ for (i = 0; i < 256; i++)
+ if (bdfEncoding[i])
+ free(bdfEncoding[i]);
+ return (TRUE);
+BAILOUT:
+ for (i = 0; i < 256; i++)
+ if (bdfEncoding[i])
+ free(bdfEncoding[i]);
+ /* bdfFreeFontBits will clean up the rest */
+ return (FALSE);
+}
+
+/***====================================================================***/
+
+static Bool
+bdfReadHeader(FontFilePtr file, bdfFileState *pState)
+{
+ unsigned char *line;
+ char namebuf[BDFLINELEN];
+ unsigned char lineBuf[BDFLINELEN];
+
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+ if (!line || sscanf((char *) line, "STARTFONT %s", namebuf) != 1 ||
+ !bdfStrEqual(namebuf, "2.1")) {
+ bdfError("bad 'STARTFONT'\n");
+ return (FALSE);
+ }
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+ if (!line || sscanf((char *) line, "FONT %[^\n]", pState->fontName) != 1) {
+ bdfError("bad 'FONT'\n");
+ return (FALSE);
+ }
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+ if (!line || !bdfIsPrefix(line, "SIZE")) {
+ bdfError("missing 'SIZE'\n");
+ return (FALSE);
+ }
+ if (sscanf((char *) line, "SIZE %f%d%d", &pState->pointSize,
+ &pState->resolution_x, &pState->resolution_y) != 3) {
+ bdfError("bad 'SIZE'\n");
+ return (FALSE);
+ }
+ if (pState->pointSize < 1 ||
+ pState->resolution_x < 1 || pState->resolution_y < 1) {
+ bdfError("SIZE values must be > 0\n");
+ return (FALSE);
+ }
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+ if (!line || !bdfIsPrefix(line, "FONTBOUNDINGBOX")) {
+ bdfError("missing 'FONTBOUNDINGBOX'\n");
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/***====================================================================***/
+
+static Bool
+bdfReadProperties(FontFilePtr file, FontPtr pFont, bdfFileState *pState)
+{
+ int nProps, props_left,
+ nextProp;
+ char *stringProps;
+ FontPropPtr props;
+ char namebuf[BDFLINELEN],
+ secondbuf[BDFLINELEN],
+ thirdbuf[BDFLINELEN];
+ unsigned char *line;
+ unsigned char lineBuf[BDFLINELEN];
+ BitmapFontPtr bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
+
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+ if (!line || !bdfIsPrefix(line, "STARTPROPERTIES")) {
+ bdfError("missing 'STARTPROPERTIES'\n");
+ return (FALSE);
+ }
+ if (sscanf((char *) line, "STARTPROPERTIES %d", &nProps) != 1) {
+ bdfError("bad 'STARTPROPERTIES'\n");
+ return (FALSE);
+ }
+ pFont->info.isStringProp = NULL;
+ pFont->info.props = NULL;
+ pFont->info.nprops = 0;
+
+ stringProps = malloc((nProps + BDF_GENPROPS) * sizeof(char));
+ pFont->info.isStringProp = stringProps;
+ if (stringProps == NULL) {
+ bdfError("Couldn't allocate stringProps (%d*%d)\n",
+ (nProps + BDF_GENPROPS), sizeof(Bool));
+ goto BAILOUT;
+ }
+ pFont->info.props = props = calloc(nProps + BDF_GENPROPS,
+ sizeof(FontPropRec));
+ if (props == NULL) {
+ bdfError("Couldn't allocate props (%d*%d)\n", nProps + BDF_GENPROPS,
+ sizeof(FontPropRec));
+ goto BAILOUT;
+ }
+
+ nextProp = 0;
+ props_left = nProps;
+ while (props_left-- > 0) {
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+ if (line == NULL || bdfIsPrefix(line, "ENDPROPERTIES")) {
+ bdfError("\"STARTPROPERTIES %d\" followed by only %d properties\n",
+ nProps, nProps - props_left - 1);
+ goto BAILOUT;
+ }
+ while (*line && isspace(*line))
+ line++;
+
+ switch (sscanf((char *) line, "%s%s%s", namebuf, secondbuf, thirdbuf)) {
+ default:
+ bdfError("missing '%s' parameter value\n", namebuf);
+ goto BAILOUT;
+
+ case 2:
+ /*
+ * Possibilites include: valid quoted string with no white space
+ * valid integer value invalid value
+ */
+ if (secondbuf[0] == '"') {
+ stringProps[nextProp] = TRUE;
+ props[nextProp].value =
+ bdfGetPropertyValue((char *)line + strlen(namebuf) + 1);
+ if (!props[nextProp].value)
+ goto BAILOUT;
+ break;
+ } else if (bdfIsInteger(secondbuf)) {
+ stringProps[nextProp] = FALSE;
+ props[nextProp].value = atoi(secondbuf);
+ break;
+ } else {
+ bdfError("invalid '%s' parameter value\n", namebuf);
+ goto BAILOUT;
+ }
+
+ case 3:
+ /*
+ * Possibilites include: valid quoted string with some white space
+ * invalid value (reject even if second string is integer)
+ */
+ if (secondbuf[0] == '"') {
+ stringProps[nextProp] = TRUE;
+ props[nextProp].value =
+ bdfGetPropertyValue((char *)line + strlen(namebuf) + 1);
+ if (!props[nextProp].value)
+ goto BAILOUT;
+ break;
+ } else {
+ bdfError("invalid '%s' parameter value\n", namebuf);
+ goto BAILOUT;
+ }
+ }
+ props[nextProp].name = bdfForceMakeAtom(namebuf, NULL);
+ if (props[nextProp].name == None) {
+ bdfError("Empty property name.\n");
+ goto BAILOUT;
+ }
+ if (!bdfSpecialProperty(pFont, &props[nextProp],
+ stringProps[nextProp], pState))
+ nextProp++;
+ }
+
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+ if (!line || !bdfIsPrefix(line, "ENDPROPERTIES")) {
+ bdfError("missing 'ENDPROPERTIES'\n");
+ goto BAILOUT;
+ }
+ if (!pState->haveFontAscent || !pState->haveFontDescent) {
+ bdfError("missing 'FONT_ASCENT' or 'FONT_DESCENT' properties\n");
+ goto BAILOUT;
+ }
+ if (bitmapFont->bitmapExtra) {
+ bitmapFont->bitmapExtra->info.fontAscent = pFont->info.fontAscent;
+ bitmapFont->bitmapExtra->info.fontDescent = pFont->info.fontDescent;
+ }
+ if (!pState->pointSizeProp) {
+ props[nextProp].name = bdfForceMakeAtom("POINT_SIZE", NULL);
+ props[nextProp].value = (INT32) (pState->pointSize * 10.0);
+ stringProps[nextProp] = FALSE;
+ pState->pointSizeProp = &props[nextProp];
+ nextProp++;
+ }
+ if (!pState->fontProp) {
+ props[nextProp].name = bdfForceMakeAtom("FONT", NULL);
+ props[nextProp].value = (INT32) bdfForceMakeAtom(pState->fontName, NULL);
+ stringProps[nextProp] = TRUE;
+ pState->fontProp = &props[nextProp];
+ nextProp++;
+ }
+ if (!pState->weightProp) {
+ props[nextProp].name = bdfForceMakeAtom("WEIGHT", NULL);
+ props[nextProp].value = -1; /* computed later */
+ stringProps[nextProp] = FALSE;
+ pState->weightProp = &props[nextProp];
+ nextProp++;
+ }
+ if (!pState->resolutionProp &&
+ pState->resolution_x == pState->resolution_y) {
+ props[nextProp].name = bdfForceMakeAtom("RESOLUTION", NULL);
+ props[nextProp].value = (INT32) ((pState->resolution_x * 100.0) / 72.27);
+ stringProps[nextProp] = FALSE;
+ pState->resolutionProp = &props[nextProp];
+ nextProp++;
+ }
+ if (!pState->resolutionXProp) {
+ props[nextProp].name = bdfForceMakeAtom("RESOLUTION_X", NULL);
+ props[nextProp].value = (INT32) pState->resolution_x;
+ stringProps[nextProp] = FALSE;
+ pState->resolutionProp = &props[nextProp];
+ nextProp++;
+ }
+ if (!pState->resolutionYProp) {
+ props[nextProp].name = bdfForceMakeAtom("RESOLUTION_Y", NULL);
+ props[nextProp].value = (INT32) pState->resolution_y;
+ stringProps[nextProp] = FALSE;
+ pState->resolutionProp = &props[nextProp];
+ nextProp++;
+ }
+ if (!pState->xHeightProp) {
+ props[nextProp].name = bdfForceMakeAtom("X_HEIGHT", NULL);
+ props[nextProp].value = -1; /* computed later */
+ stringProps[nextProp] = FALSE;
+ pState->xHeightProp = &props[nextProp];
+ nextProp++;
+ }
+ if (!pState->quadWidthProp) {
+ props[nextProp].name = bdfForceMakeAtom("QUAD_WIDTH", NULL);
+ props[nextProp].value = -1; /* computed later */
+ stringProps[nextProp] = FALSE;
+ pState->quadWidthProp = &props[nextProp];
+ nextProp++;
+ }
+ pFont->info.nprops = nextProp;
+ return (TRUE);
+BAILOUT:
+ if (pFont->info.isStringProp) {
+ free(pFont->info.isStringProp);
+ pFont->info.isStringProp = NULL;
+ }
+ if (pFont->info.props) {
+ free(pFont->info.props);
+ pFont->info.props = NULL;
+ }
+ while (line && bdfIsPrefix(line, "ENDPROPERTIES"))
+ line = bdfGetLine(file, lineBuf, BDFLINELEN);
+ return (FALSE);
+}
+
+/***====================================================================***/
+
+static void
+bdfUnloadFont(FontPtr pFont)
+{
+ bdfFreeFontBits (pFont);
+ DestroyFontRec(pFont);
+}
+
+int
+bdfReadFont(FontPtr pFont, FontFilePtr file,
+ int bit, int byte, int glyph, int scan)
+{
+ bdfFileState state;
+ xCharInfo *min,
+ *max;
+ BitmapFontPtr bitmapFont;
+
+ pFont->fontPrivate = 0;
+
+ bzero(&state, sizeof(bdfFileState));
+ bdfFileLineNum = 0;
+
+ if (!bdfReadHeader(file, &state))
+ goto BAILOUT;
+
+ bitmapFont = calloc(1, sizeof(BitmapFontRec));
+ if (!bitmapFont) {
+ bdfError("Couldn't allocate bitmapFontRec (%d)\n", sizeof(BitmapFontRec));
+ goto BAILOUT;
+ }
+
+ pFont->fontPrivate = (pointer) bitmapFont;
+ bitmapFont->metrics = 0;
+ bitmapFont->ink_metrics = 0;
+ bitmapFont->bitmaps = 0;
+ bitmapFont->encoding = 0;
+ bitmapFont->pDefault = NULL;
+
+ bitmapFont->bitmapExtra = calloc(1, sizeof(BitmapExtraRec));
+ if (!bitmapFont->bitmapExtra) {
+ bdfError("Couldn't allocate bitmapExtra (%d)\n", sizeof(BitmapExtraRec));
+ goto BAILOUT;
+ }
+
+ bitmapFont->bitmapExtra->glyphNames = 0;
+ bitmapFont->bitmapExtra->sWidths = 0;
+
+ if (!bdfReadProperties(file, pFont, &state))
+ goto BAILOUT;
+
+ if (!bdfReadCharacters(file, pFont, &state, bit, byte, glyph, scan))
+ goto BAILOUT;
+
+ if (state.haveDefaultCh) {
+ unsigned int r, c, cols;
+
+ r = pFont->info.defaultCh >> 8;
+ c = pFont->info.defaultCh & 0xFF;
+ if (pFont->info.firstRow <= r && r <= pFont->info.lastRow &&
+ pFont->info.firstCol <= c && c <= pFont->info.lastCol) {
+ cols = pFont->info.lastCol - pFont->info.firstCol + 1;
+ r = r - pFont->info.firstRow;
+ c = c - pFont->info.firstCol;
+ bitmapFont->pDefault = ACCESSENCODING(bitmapFont->encoding,
+ r * cols + c);
+ }
+ }
+ pFont->bit = bit;
+ pFont->byte = byte;
+ pFont->glyph = glyph;
+ pFont->scan = scan;
+ pFont->info.anamorphic = FALSE;
+ pFont->info.cachable = TRUE;
+ bitmapComputeFontBounds(pFont);
+ if (FontCouldBeTerminal(&pFont->info)) {
+ bdfPadToTerminal(pFont);
+ bitmapComputeFontBounds(pFont);
+ }
+ FontComputeInfoAccelerators(&pFont->info);
+ if (bitmapFont->bitmapExtra)
+ FontComputeInfoAccelerators(&bitmapFont->bitmapExtra->info);
+ if (pFont->info.constantMetrics) {
+ if (!bitmapAddInkMetrics(pFont)) {
+ bdfError("Failed to add bitmap ink metrics\n");
+ goto BAILOUT;
+ }
+ }
+ if (bitmapFont->bitmapExtra)
+ bitmapFont->bitmapExtra->info.inkMetrics = pFont->info.inkMetrics;
+
+ bitmapComputeFontInkBounds(pFont);
+/* ComputeFontAccelerators (pFont); */
+
+ /* generate properties */
+ min = &pFont->info.ink_minbounds;
+ max = &pFont->info.ink_maxbounds;
+ if (state.xHeightProp && (state.xHeightProp->value == -1))
+ state.xHeightProp->value = state.exHeight ?
+ state.exHeight : min->ascent;
+
+ if (state.quadWidthProp && (state.quadWidthProp->value == -1))
+ state.quadWidthProp->value = state.digitCount ?
+ (INT32) (state.digitWidths / state.digitCount) :
+ (min->characterWidth + max->characterWidth) / 2;
+
+ if (state.weightProp && (state.weightProp->value == -1))
+ state.weightProp->value = bitmapComputeWeight(pFont);
+
+ pFont->get_glyphs = bitmapGetGlyphs;
+ pFont->get_metrics = bitmapGetMetrics;
+ pFont->unload_font = bdfUnloadFont;
+ pFont->unload_glyphs = NULL;
+ return Successful;
+BAILOUT:
+ if (pFont->fontPrivate)
+ bdfFreeFontBits (pFont);
+ return AllocError;
+}
+
+int
+bdfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file)
+{
+ FontRec font;
+ int ret;
+
+ bzero(&font, sizeof (FontRec));
+
+ ret = bdfReadFont(&font, file, MSBFirst, LSBFirst, 1, 1);
+ if (ret == Successful) {
+ *pFontInfo = font.info;
+ font.info.props = 0;
+ font.info.isStringProp = 0;
+ font.info.nprops = 0;
+ bdfFreeFontBits (&font);
+ }
+ return ret;
+}
+
+static Bool
+bdfPadToTerminal(FontPtr pFont)
+{
+ BitmapFontPtr bitmapFont;
+ BitmapExtraPtr bitmapExtra;
+ int i;
+ int new_size;
+ CharInfoRec new;
+ int w,
+ h;
+
+ bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
+
+ bzero(&new, sizeof(CharInfoRec));
+ new.metrics.ascent = pFont->info.fontAscent;
+ new.metrics.descent = pFont->info.fontDescent;
+ new.metrics.leftSideBearing = 0;
+ new.metrics.rightSideBearing = pFont->info.minbounds.characterWidth;
+ new.metrics.characterWidth = new.metrics.rightSideBearing;
+ new_size = BYTES_FOR_GLYPH(&new, pFont->glyph);
+
+ for (i = 0; i < bitmapFont->num_chars; i++) {
+ new.bits = malloc(new_size);
+ if (!new.bits) {
+ bdfError("Couldn't allocate bits (%d)\n", new_size);
+ return FALSE;
+ }
+ FontCharReshape(pFont, &bitmapFont->metrics[i], &new);
+ new.metrics.attributes = bitmapFont->metrics[i].metrics.attributes;
+ free(bitmapFont->metrics[i].bits);
+ bitmapFont->metrics[i] = new;
+ }
+ bitmapExtra = bitmapFont->bitmapExtra;
+ if (bitmapExtra) {
+ w = GLYPHWIDTHPIXELS(&new);
+ h = GLYPHHEIGHTPIXELS(&new);
+ for (i = 0; i < GLYPHPADOPTIONS; i++)
+ bitmapExtra->bitmapsSizes[i] = bitmapFont->num_chars *
+ (BYTES_PER_ROW(w, 1 << i) * h);
+ }
+ return TRUE;
+}
diff --git a/libXfont/src/bitmap/bdfutils.c b/libXfont/src/bitmap/bdfutils.c index 1d6cc7253..7cae0de6a 100644 --- a/libXfont/src/bitmap/bdfutils.c +++ b/libXfont/src/bitmap/bdfutils.c @@ -1,336 +1,336 @@ -/************************************************************************ -Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -************************************************************************/ - -/* - -Copyright 1994, 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. - -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <ctype.h> -#include <stdio.h> -#include <stdarg.h> - -#include <X11/fonts/fntfilst.h> -#include <X11/fonts/fontstruct.h> -/* use bitmap structure */ -#include <X11/fonts/bitmap.h> -#include <X11/fonts/bdfint.h> - -int bdfFileLineNum; - -/***====================================================================***/ - -void -bdfError(char* message, ...) -{ - va_list args; - - va_start (args, message); - fprintf(stderr, "BDF Error on line %d: ", bdfFileLineNum); - vfprintf(stderr, message, args); - va_end (args); -} - -/***====================================================================***/ - -void -bdfWarning(char *message, ...) -{ - va_list args; - - va_start (args, message); - fprintf(stderr, "BDF Warning on line %d: ", bdfFileLineNum); - vfprintf(stderr, message, args); - va_end (args); -} - -/* - * read the next (non-comment) line and keep a count for error messages. - * Returns buf, or NULL if EOF. - */ - -unsigned char * -bdfGetLine(FontFilePtr file, unsigned char *buf, int len) -{ - int c; - unsigned char *b; - - for (;;) { - b = buf; - while ((c = FontFileGetc(file)) != FontFileEOF) { - if (c == '\r') - continue; - if (c == '\n') { - bdfFileLineNum++; - break; - } - if (b - buf >= (len - 1)) - break; - *b++ = c; - } - *b = '\0'; - if (c == FontFileEOF) - return NULL; - if (b != buf && !bdfIsPrefix(buf, "COMMENT")) - break; - } - return buf; -} - -/***====================================================================***/ - -Atom -bdfForceMakeAtom(char *str, int *size) -{ - register int len = strlen(str); - Atom the_atom; - - if (size != NULL) - *size += len + 1; - the_atom = MakeAtom(str, len, TRUE); - if (the_atom == None) - bdfError("Atom allocation failed\n"); - return the_atom; -} - -/***====================================================================***/ - -/* - * Handle quoted strings. - */ - -Atom -bdfGetPropertyValue(char *s) -{ - register char *p, - *pp; - char *orig_s = s; - Atom atom; - - /* strip leading white space */ - while (*s && (*s == ' ' || *s == '\t')) - s++; - if (*s == 0) { - return bdfForceMakeAtom(s, NULL); - } - if (*s != '"') { - pp = s; - /* no white space in value */ - for (pp = s; *pp; pp++) - if (*pp == ' ' || *pp == '\t' || *pp == '\015' || *pp == '\n') { - *pp = 0; - break; - } - return bdfForceMakeAtom(s, NULL); - } - /* quoted string: strip outer quotes and undouble inner quotes */ - s++; - pp = p = malloc((unsigned) strlen(s) + 1); - if (pp == NULL) { - bdfError("Couldn't allocate property value string (%d)\n", strlen(s) + 1); - return None; - } - while (*s) { - if (*s == '"') { - if (*(s + 1) != '"') { - *p++ = 0; - atom = bdfForceMakeAtom(pp, NULL); - free(pp); - return atom; - } else { - s++; - } - } - *p++ = *s++; - } - free (pp); - bdfError("unterminated quoted string property: %s\n", (pointer) orig_s); - return None; -} - -/***====================================================================***/ - -/* - * return TRUE if string is a valid integer - */ -int -bdfIsInteger(char *str) -{ - char c; - - c = *str++; - if (!(isdigit(c) || c == '-' || c == '+')) - return (FALSE); - - while ((c = *str++)) - if (!isdigit(c)) - return (FALSE); - - return (TRUE); -} - -/***====================================================================***/ - -/* - * make a byte from the first two hex characters in glyph picture - */ - -unsigned char -bdfHexByte(unsigned char *s) -{ - unsigned char b = 0; - register char c; - int i; - - for (i = 2; i; i--) { - c = *s++; - if ((c >= '0') && (c <= '9')) - b = (b << 4) + (c - '0'); - else if ((c >= 'A') && (c <= 'F')) - b = (b << 4) + 10 + (c - 'A'); - else if ((c >= 'a') && (c <= 'f')) - b = (b << 4) + 10 + (c - 'a'); - else - bdfError("bad hex char '%c'", c); - } - return b; -} - -/***====================================================================***/ - -/* - * check for known special property values - */ - -static char *SpecialAtoms[] = { - "FONT_ASCENT", -#define BDF_FONT_ASCENT 0 - "FONT_DESCENT", -#define BDF_FONT_DESCENT 1 - "DEFAULT_CHAR", -#define BDF_DEFAULT_CHAR 2 - "POINT_SIZE", -#define BDF_POINT_SIZE 3 - "RESOLUTION", -#define BDF_RESOLUTION 4 - "X_HEIGHT", -#define BDF_X_HEIGHT 5 - "WEIGHT", -#define BDF_WEIGHT 6 - "QUAD_WIDTH", -#define BDF_QUAD_WIDTH 7 - "FONT", -#define BDF_FONT 8 - "RESOLUTION_X", -#define BDF_RESOLUTION_X 9 - "RESOLUTION_Y", -#define BDF_RESOLUTION_Y 10 - 0, -}; - -Bool -bdfSpecialProperty(FontPtr pFont, FontPropPtr prop, - char isString, bdfFileState *bdfState) -{ - char **special; - char *name; - - name = NameForAtom(prop->name); - for (special = SpecialAtoms; *special; special++) - if (!strcmp(name, *special)) - break; - - switch (special - SpecialAtoms) { - case BDF_FONT_ASCENT: - if (!isString) { - pFont->info.fontAscent = prop->value; - bdfState->haveFontAscent = TRUE; - } - return TRUE; - case BDF_FONT_DESCENT: - if (!isString) { - pFont->info.fontDescent = prop->value; - bdfState->haveFontDescent = TRUE; - } - return TRUE; - case BDF_DEFAULT_CHAR: - if (!isString) { - pFont->info.defaultCh = prop->value; - bdfState->haveDefaultCh = TRUE; - } - return TRUE; - case BDF_POINT_SIZE: - bdfState->pointSizeProp = prop; - return FALSE; - case BDF_RESOLUTION: - bdfState->resolutionProp = prop; - return FALSE; - case BDF_X_HEIGHT: - bdfState->xHeightProp = prop; - return FALSE; - case BDF_WEIGHT: - bdfState->weightProp = prop; - return FALSE; - case BDF_QUAD_WIDTH: - bdfState->quadWidthProp = prop; - return FALSE; - case BDF_FONT: - bdfState->fontProp = prop; - return FALSE; - case BDF_RESOLUTION_X: - bdfState->resolutionXProp = prop; - return FALSE; - case BDF_RESOLUTION_Y: - bdfState->resolutionYProp = prop; - return FALSE; - default: - return FALSE; - } -} +/************************************************************************
+Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+************************************************************************/
+
+/*
+
+Copyright 1994, 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.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <X11/fonts/fntfilst.h>
+#include <X11/fonts/fontstruct.h>
+/* use bitmap structure */
+#include <X11/fonts/bitmap.h>
+#include <X11/fonts/bdfint.h>
+
+int bdfFileLineNum;
+
+/***====================================================================***/
+
+void
+bdfError(char* message, ...)
+{
+ va_list args;
+
+ va_start (args, message);
+ fprintf(stderr, "BDF Error on line %d: ", bdfFileLineNum);
+ vfprintf(stderr, message, args);
+ va_end (args);
+}
+
+/***====================================================================***/
+
+void
+bdfWarning(char *message, ...)
+{
+ va_list args;
+
+ va_start (args, message);
+ fprintf(stderr, "BDF Warning on line %d: ", bdfFileLineNum);
+ vfprintf(stderr, message, args);
+ va_end (args);
+}
+
+/*
+ * read the next (non-comment) line and keep a count for error messages.
+ * Returns buf, or NULL if EOF.
+ */
+
+unsigned char *
+bdfGetLine(FontFilePtr file, unsigned char *buf, int len)
+{
+ int c;
+ unsigned char *b;
+
+ for (;;) {
+ b = buf;
+ while ((c = FontFileGetc(file)) != FontFileEOF) {
+ if (c == '\r')
+ continue;
+ if (c == '\n') {
+ bdfFileLineNum++;
+ break;
+ }
+ if (b - buf >= (len - 1))
+ break;
+ *b++ = c;
+ }
+ *b = '\0';
+ if (c == FontFileEOF)
+ return NULL;
+ if (b != buf && !bdfIsPrefix(buf, "COMMENT"))
+ break;
+ }
+ return buf;
+}
+
+/***====================================================================***/
+
+Atom
+bdfForceMakeAtom(char *str, int *size)
+{
+ register int len = strlen(str);
+ Atom the_atom;
+
+ if (size != NULL)
+ *size += len + 1;
+ the_atom = MakeAtom(str, len, TRUE);
+ if (the_atom == None)
+ bdfError("Atom allocation failed\n");
+ return the_atom;
+}
+
+/***====================================================================***/
+
+/*
+ * Handle quoted strings.
+ */
+
+Atom
+bdfGetPropertyValue(char *s)
+{
+ register char *p,
+ *pp;
+ char *orig_s = s;
+ Atom atom;
+
+ /* strip leading white space */
+ while (*s && (*s == ' ' || *s == '\t'))
+ s++;
+ if (*s == 0) {
+ return bdfForceMakeAtom(s, NULL);
+ }
+ if (*s != '"') {
+ pp = s;
+ /* no white space in value */
+ for (pp = s; *pp; pp++)
+ if (*pp == ' ' || *pp == '\t' || *pp == '\015' || *pp == '\n') {
+ *pp = 0;
+ break;
+ }
+ return bdfForceMakeAtom(s, NULL);
+ }
+ /* quoted string: strip outer quotes and undouble inner quotes */
+ s++;
+ pp = p = malloc((unsigned) strlen(s) + 1);
+ if (pp == NULL) {
+ bdfError("Couldn't allocate property value string (%d)\n", strlen(s) + 1);
+ return None;
+ }
+ while (*s) {
+ if (*s == '"') {
+ if (*(s + 1) != '"') {
+ *p++ = 0;
+ atom = bdfForceMakeAtom(pp, NULL);
+ free(pp);
+ return atom;
+ } else {
+ s++;
+ }
+ }
+ *p++ = *s++;
+ }
+ free (pp);
+ bdfError("unterminated quoted string property: %s\n", (pointer) orig_s);
+ return None;
+}
+
+/***====================================================================***/
+
+/*
+ * return TRUE if string is a valid integer
+ */
+int
+bdfIsInteger(char *str)
+{
+ char c;
+
+ c = *str++;
+ if (!(isdigit(c) || c == '-' || c == '+'))
+ return (FALSE);
+
+ while ((c = *str++))
+ if (!isdigit(c))
+ return (FALSE);
+
+ return (TRUE);
+}
+
+/***====================================================================***/
+
+/*
+ * make a byte from the first two hex characters in glyph picture
+ */
+
+unsigned char
+bdfHexByte(unsigned char *s)
+{
+ unsigned char b = 0;
+ register char c;
+ int i;
+
+ for (i = 2; i; i--) {
+ c = *s++;
+ if ((c >= '0') && (c <= '9'))
+ b = (b << 4) + (c - '0');
+ else if ((c >= 'A') && (c <= 'F'))
+ b = (b << 4) + 10 + (c - 'A');
+ else if ((c >= 'a') && (c <= 'f'))
+ b = (b << 4) + 10 + (c - 'a');
+ else
+ bdfError("bad hex char '%c'", c);
+ }
+ return b;
+}
+
+/***====================================================================***/
+
+/*
+ * check for known special property values
+ */
+
+static char *SpecialAtoms[] = {
+ "FONT_ASCENT",
+#define BDF_FONT_ASCENT 0
+ "FONT_DESCENT",
+#define BDF_FONT_DESCENT 1
+ "DEFAULT_CHAR",
+#define BDF_DEFAULT_CHAR 2
+ "POINT_SIZE",
+#define BDF_POINT_SIZE 3
+ "RESOLUTION",
+#define BDF_RESOLUTION 4
+ "X_HEIGHT",
+#define BDF_X_HEIGHT 5
+ "WEIGHT",
+#define BDF_WEIGHT 6
+ "QUAD_WIDTH",
+#define BDF_QUAD_WIDTH 7
+ "FONT",
+#define BDF_FONT 8
+ "RESOLUTION_X",
+#define BDF_RESOLUTION_X 9
+ "RESOLUTION_Y",
+#define BDF_RESOLUTION_Y 10
+ 0,
+};
+
+Bool
+bdfSpecialProperty(FontPtr pFont, FontPropPtr prop,
+ char isString, bdfFileState *bdfState)
+{
+ char **special;
+ char *name;
+
+ name = NameForAtom(prop->name);
+ for (special = SpecialAtoms; *special; special++)
+ if (!strcmp(name, *special))
+ break;
+
+ switch (special - SpecialAtoms) {
+ case BDF_FONT_ASCENT:
+ if (!isString) {
+ pFont->info.fontAscent = prop->value;
+ bdfState->haveFontAscent = TRUE;
+ }
+ return TRUE;
+ case BDF_FONT_DESCENT:
+ if (!isString) {
+ pFont->info.fontDescent = prop->value;
+ bdfState->haveFontDescent = TRUE;
+ }
+ return TRUE;
+ case BDF_DEFAULT_CHAR:
+ if (!isString) {
+ pFont->info.defaultCh = prop->value;
+ bdfState->haveDefaultCh = TRUE;
+ }
+ return TRUE;
+ case BDF_POINT_SIZE:
+ bdfState->pointSizeProp = prop;
+ return FALSE;
+ case BDF_RESOLUTION:
+ bdfState->resolutionProp = prop;
+ return FALSE;
+ case BDF_X_HEIGHT:
+ bdfState->xHeightProp = prop;
+ return FALSE;
+ case BDF_WEIGHT:
+ bdfState->weightProp = prop;
+ return FALSE;
+ case BDF_QUAD_WIDTH:
+ bdfState->quadWidthProp = prop;
+ return FALSE;
+ case BDF_FONT:
+ bdfState->fontProp = prop;
+ return FALSE;
+ case BDF_RESOLUTION_X:
+ bdfState->resolutionXProp = prop;
+ return FALSE;
+ case BDF_RESOLUTION_Y:
+ bdfState->resolutionYProp = prop;
+ return FALSE;
+ default:
+ return FALSE;
+ }
+}
diff --git a/libXfont/src/bitmap/bitmap.c b/libXfont/src/bitmap/bitmap.c index 1ceb4bb17..f837deafd 100644 --- a/libXfont/src/bitmap/bitmap.c +++ b/libXfont/src/bitmap/bitmap.c @@ -1,157 +1,157 @@ -/* - -Copyright 1991, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <X11/fonts/fntfilst.h> -#include <X11/fonts/bitmap.h> - -int -bitmapGetGlyphs(FontPtr pFont, unsigned long count, unsigned char *chars, - FontEncoding charEncoding, - unsigned long *glyphCount, /* RETURN */ - CharInfoPtr *glyphs) /* RETURN */ -{ - BitmapFontPtr bitmapFont; - unsigned int firstCol; - register unsigned int numCols; - unsigned int firstRow; - unsigned int numRows; - CharInfoPtr *glyphsBase; - register unsigned int c; - register CharInfoPtr pci; - unsigned int r; - CharInfoPtr **encoding; - CharInfoPtr pDefault; - - bitmapFont = (BitmapFontPtr) pFont->fontPrivate; - encoding = bitmapFont->encoding; - pDefault = bitmapFont->pDefault; - firstCol = pFont->info.firstCol; - numCols = pFont->info.lastCol - firstCol + 1; - glyphsBase = glyphs; - switch (charEncoding) { - - case Linear8Bit: - case TwoD8Bit: - if (pFont->info.firstRow > 0) - break; - if (pFont->info.allExist && pDefault) { - while (count--) { - c = (*chars++) - firstCol; - if (c < numCols) - *glyphs++ = ACCESSENCODING(encoding,c); - else - *glyphs++ = pDefault; - } - } else { - while (count--) { - c = (*chars++) - firstCol; - if (c < numCols && (pci = ACCESSENCODING(encoding,c))) - *glyphs++ = pci; - else if (pDefault) - *glyphs++ = pDefault; - } - } - break; - case Linear16Bit: - if (pFont->info.allExist && pDefault) { - while (count--) { - c = *chars++ << 8; - c = (c | *chars++) - firstCol; - if (c < numCols) - *glyphs++ = ACCESSENCODING(encoding,c); - else - *glyphs++ = pDefault; - } - } else { - while (count--) { - c = *chars++ << 8; - c = (c | *chars++) - firstCol; - if (c < numCols && (pci = ACCESSENCODING(encoding,c))) - *glyphs++ = pci; - else if (pDefault) - *glyphs++ = pDefault; - } - } - break; - - case TwoD16Bit: - firstRow = pFont->info.firstRow; - numRows = pFont->info.lastRow - firstRow + 1; - while (count--) { - r = (*chars++) - firstRow; - c = (*chars++) - firstCol; - if (r < numRows && c < numCols && - (pci = ACCESSENCODING(encoding, r * numCols + c))) - *glyphs++ = pci; - else if (pDefault) - *glyphs++ = pDefault; - } - break; - } - *glyphCount = glyphs - glyphsBase; - return Successful; -} - -static CharInfoRec nonExistantChar; - -int -bitmapGetMetrics(FontPtr pFont, unsigned long count, unsigned char *chars, - FontEncoding charEncoding, - unsigned long *glyphCount, /* RETURN */ - xCharInfo **glyphs) /* RETURN */ -{ - int ret; - xCharInfo *ink_metrics; - CharInfoPtr metrics; - BitmapFontPtr bitmapFont; - CharInfoPtr oldDefault; - int i; - - bitmapFont = (BitmapFontPtr) pFont->fontPrivate; - oldDefault = bitmapFont->pDefault; - bitmapFont->pDefault = &nonExistantChar; - ret = bitmapGetGlyphs(pFont, count, chars, charEncoding, glyphCount, (CharInfoPtr *) glyphs); - if (ret == Successful) { - if (bitmapFont->ink_metrics) { - metrics = bitmapFont->metrics; - ink_metrics = bitmapFont->ink_metrics; - for (i = 0; i < *glyphCount; i++) { - if (glyphs[i] != (xCharInfo *) & nonExistantChar) - glyphs[i] = ink_metrics + (((CharInfoPtr) glyphs[i]) - metrics); - } - } - } - bitmapFont->pDefault = oldDefault; - return ret; -} +/*
+
+Copyright 1991, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <X11/fonts/fntfilst.h>
+#include <X11/fonts/bitmap.h>
+
+int
+bitmapGetGlyphs(FontPtr pFont, unsigned long count, unsigned char *chars,
+ FontEncoding charEncoding,
+ unsigned long *glyphCount, /* RETURN */
+ CharInfoPtr *glyphs) /* RETURN */
+{
+ BitmapFontPtr bitmapFont;
+ unsigned int firstCol;
+ register unsigned int numCols;
+ unsigned int firstRow;
+ unsigned int numRows;
+ CharInfoPtr *glyphsBase;
+ register unsigned int c;
+ register CharInfoPtr pci;
+ unsigned int r;
+ CharInfoPtr **encoding;
+ CharInfoPtr pDefault;
+
+ bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
+ encoding = bitmapFont->encoding;
+ pDefault = bitmapFont->pDefault;
+ firstCol = pFont->info.firstCol;
+ numCols = pFont->info.lastCol - firstCol + 1;
+ glyphsBase = glyphs;
+ switch (charEncoding) {
+
+ case Linear8Bit:
+ case TwoD8Bit:
+ if (pFont->info.firstRow > 0)
+ break;
+ if (pFont->info.allExist && pDefault) {
+ while (count--) {
+ c = (*chars++) - firstCol;
+ if (c < numCols)
+ *glyphs++ = ACCESSENCODING(encoding,c);
+ else
+ *glyphs++ = pDefault;
+ }
+ } else {
+ while (count--) {
+ c = (*chars++) - firstCol;
+ if (c < numCols && (pci = ACCESSENCODING(encoding,c)))
+ *glyphs++ = pci;
+ else if (pDefault)
+ *glyphs++ = pDefault;
+ }
+ }
+ break;
+ case Linear16Bit:
+ if (pFont->info.allExist && pDefault) {
+ while (count--) {
+ c = *chars++ << 8;
+ c = (c | *chars++) - firstCol;
+ if (c < numCols)
+ *glyphs++ = ACCESSENCODING(encoding,c);
+ else
+ *glyphs++ = pDefault;
+ }
+ } else {
+ while (count--) {
+ c = *chars++ << 8;
+ c = (c | *chars++) - firstCol;
+ if (c < numCols && (pci = ACCESSENCODING(encoding,c)))
+ *glyphs++ = pci;
+ else if (pDefault)
+ *glyphs++ = pDefault;
+ }
+ }
+ break;
+
+ case TwoD16Bit:
+ firstRow = pFont->info.firstRow;
+ numRows = pFont->info.lastRow - firstRow + 1;
+ while (count--) {
+ r = (*chars++) - firstRow;
+ c = (*chars++) - firstCol;
+ if (r < numRows && c < numCols &&
+ (pci = ACCESSENCODING(encoding, r * numCols + c)))
+ *glyphs++ = pci;
+ else if (pDefault)
+ *glyphs++ = pDefault;
+ }
+ break;
+ }
+ *glyphCount = glyphs - glyphsBase;
+ return Successful;
+}
+
+static CharInfoRec nonExistantChar;
+
+int
+bitmapGetMetrics(FontPtr pFont, unsigned long count, unsigned char *chars,
+ FontEncoding charEncoding,
+ unsigned long *glyphCount, /* RETURN */
+ xCharInfo **glyphs) /* RETURN */
+{
+ int ret;
+ xCharInfo *ink_metrics;
+ CharInfoPtr metrics;
+ BitmapFontPtr bitmapFont;
+ CharInfoPtr oldDefault;
+ int i;
+
+ bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
+ oldDefault = bitmapFont->pDefault;
+ bitmapFont->pDefault = &nonExistantChar;
+ ret = bitmapGetGlyphs(pFont, count, chars, charEncoding, glyphCount, (CharInfoPtr *) glyphs);
+ if (ret == Successful) {
+ if (bitmapFont->ink_metrics) {
+ metrics = bitmapFont->metrics;
+ ink_metrics = bitmapFont->ink_metrics;
+ for (i = 0; i < *glyphCount; i++) {
+ if (glyphs[i] != (xCharInfo *) & nonExistantChar)
+ glyphs[i] = ink_metrics + (((CharInfoPtr) glyphs[i]) - metrics);
+ }
+ }
+ }
+ bitmapFont->pDefault = oldDefault;
+ return ret;
+}
diff --git a/libXfont/src/bitmap/bitmapfunc.c b/libXfont/src/bitmap/bitmapfunc.c index 47ce488d0..b13a4c42e 100644 --- a/libXfont/src/bitmap/bitmapfunc.c +++ b/libXfont/src/bitmap/bitmapfunc.c @@ -1,254 +1,256 @@ -/* - -Copyright 1991, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -/* - * Translate monolithic #defines to modular definitions - */ - -#ifdef PCFFORMAT -#define XFONT_PCFFORMAT 1 -#endif - -#ifdef SNFFORMAT -#define XFONT_SNFFORMAT 1 -#endif - -#ifdef BDFFORMAT -#define XFONT_BDFFORMAT 1 -#endif - -#include <X11/fonts/fntfilst.h> -#include <X11/fonts/bitmap.h> -#include <X11/fonts/fontutil.h> -#include <X11/fonts/bdfint.h> -#include <X11/fonts/pcf.h> -#include "snfstr.h" - -typedef struct _BitmapFileFunctions { - int (*ReadFont) (FontPtr /* pFont */, FontFilePtr /* file */, - int /* bit */, int /* byte */, - int /* glyph */, int /* scan */); - int (*ReadInfo) ( FontInfoPtr /* pFontInfo */, - FontFilePtr /* file */ ); -} BitmapFileFunctionsRec, *BitmapFileFunctionsPtr; - -static int BitmapGetRenderIndex(FontRendererPtr renderer); - -/* - * the readers[] and renderers[] arrays must be in the same order, - * and also in the same order as scale[] and find_scale[] in bitscale.c - * - */ -static BitmapFileFunctionsRec readers[] = { -#if XFONT_PCFFORMAT - { pcfReadFont, pcfReadFontInfo} , - { pcfReadFont, pcfReadFontInfo} , -# ifdef X_GZIP_FONT_COMPRESSION - { pcfReadFont, pcfReadFontInfo} , -# endif -# ifdef X_BZIP2_FONT_COMPRESSION - { pcfReadFont, pcfReadFontInfo} , -# endif -#endif -#if XFONT_SNFFORMAT - { snfReadFont, snfReadFontInfo}, - { snfReadFont, snfReadFontInfo}, -# ifdef X_GZIP_FONT_COMPRESSION - { snfReadFont, snfReadFontInfo} , -# endif -# ifdef X_BZIP2_FONT_COMPRESSION - { snfReadFont, snfReadFontInfo} , -# endif -#endif -#if XFONT_BDFFORMAT - { bdfReadFont, bdfReadFontInfo} , - { bdfReadFont, bdfReadFontInfo} , -# ifdef X_GZIP_FONT_COMPRESSION - { bdfReadFont, bdfReadFontInfo} , -# endif -# ifdef X_BZIP2_FONT_COMPRESSION - { bdfReadFont, bdfReadFontInfo} , -# endif -#endif -}; - - -#define CAPABILITIES (CAP_MATRIX | CAP_CHARSUBSETTING) - -static int -BitmapOpenBitmap (FontPathElementPtr fpe, FontPtr *ppFont, int flags, - FontEntryPtr entry, char *fileName, - fsBitmapFormat format, fsBitmapFormatMask fmask, - FontPtr non_cachable_font) /* We don't do licensing */ -{ - FontFilePtr file; - FontPtr pFont; - int i; - int ret; - int bit, - byte, - glyph, - scan, - image; - - i = BitmapGetRenderIndex(entry->u.bitmap.renderer); - file = FontFileOpen (fileName); - if (!file) - return BadFontName; - if (!(pFont = CreateFontRec())) { - fprintf(stderr, "Error: Couldn't allocate pFont (%ld)\n", - (unsigned long)sizeof(FontRec)); - FontFileClose (file); - return AllocError; - } - /* set up default values */ - FontDefaultFormat(&bit, &byte, &glyph, &scan); - /* get any changes made from above */ - ret = CheckFSFormat(format, fmask, &bit, &byte, &scan, &glyph, &image); - - /* Fill in font record. Data format filled in by reader. */ - pFont->refcnt = 0; - - ret = (*readers[i].ReadFont) (pFont, file, bit, byte, glyph, scan); - - FontFileClose (file); - if (ret != Successful) { - free(pFont); - } else { - *ppFont = pFont; - } - return ret; -} - -static int -BitmapGetInfoBitmap (FontPathElementPtr fpe, FontInfoPtr pFontInfo, - FontEntryPtr entry, char *fileName) -{ - FontFilePtr file; - int i; - int ret; - FontRendererPtr renderer; - - renderer = FontFileMatchRenderer (fileName); - if (!renderer) - return BadFontName; - i = BitmapGetRenderIndex(renderer); - file = FontFileOpen (fileName); - if (!file) - return BadFontName; - ret = (*readers[i].ReadInfo) (pFontInfo, file); - FontFileClose (file); - return ret; -} - -static FontRendererRec renderers[] = { -#if XFONT_PCFFORMAT - { ".pcf", 4, BitmapOpenBitmap, BitmapOpenScalable, - BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, - CAPABILITIES }, - { ".pcf.Z", 6, BitmapOpenBitmap, BitmapOpenScalable, - BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, - CAPABILITIES }, -# ifdef X_GZIP_FONT_COMPRESSION - { ".pcf.gz", 7, - BitmapOpenBitmap, BitmapOpenScalable, - BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, - CAPABILITIES }, -# endif -# ifdef X_BZIP2_FONT_COMPRESSION - { ".pcf.bz2", 8, - BitmapOpenBitmap, BitmapOpenScalable, - BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, - CAPABILITIES }, -# endif -#endif -#if XFONT_SNFFORMAT - { ".snf", 4, BitmapOpenBitmap, BitmapOpenScalable, - BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, - CAPABILITIES }, - { ".snf.Z", 6, BitmapOpenBitmap, BitmapOpenScalable, - BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, - CAPABILITIES }, -# ifdef X_GZIP_FONT_COMPRESSION - { ".snf.gz", 7, BitmapOpenBitmap, BitmapOpenScalable, - BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, - CAPABILITIES }, -# endif -# ifdef X_BZIP2_FONT_COMPRESSION - { ".snf.bz2", 8, BitmapOpenBitmap, BitmapOpenScalable, - BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, - CAPABILITIES }, -# endif -#endif -#if XFONT_BDFFORMAT - { ".bdf", 4, BitmapOpenBitmap, BitmapOpenScalable, - BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, - CAPABILITIES }, - { ".bdf.Z", 6, BitmapOpenBitmap, BitmapOpenScalable, - BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, - CAPABILITIES }, -# ifdef X_GZIP_FONT_COMPRESSION - { ".bdf.gz", 7, BitmapOpenBitmap, BitmapOpenScalable, - BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, - CAPABILITIES }, -# endif -# ifdef X_BZIP2_FONT_COMPRESSION - { ".bdf.bz2", 8, BitmapOpenBitmap, BitmapOpenScalable, - BitmapGetInfoBitmap, BitmapGetInfoScalable, 0, - CAPABILITIES }, -# endif -#endif -}; - -#define numRenderers (sizeof renderers / sizeof renderers[0]) - -void -BitmapRegisterFontFileFunctions (void) -{ - int i; - - for (i = 0; i < numRenderers; i++) - FontFileRegisterRenderer (&renderers[i]); -} - -/* - * compute offset into renderers array - used to find the font reader, - * the font info reader, and the bitmap scaling routine. All users - * of this routine must be kept in step with the renderer array. - */ -static int -BitmapGetRenderIndex(FontRendererPtr renderer) -{ - return renderer - renderers; -} +/*
+
+Copyright 1991, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/*
+ * Translate monolithic #defines to modular definitions
+ */
+
+#ifdef PCFFORMAT
+#define XFONT_PCFFORMAT 1
+#endif
+
+#ifdef SNFFORMAT
+#define XFONT_SNFFORMAT 1
+#endif
+
+#ifdef BDFFORMAT
+#define XFONT_BDFFORMAT 1
+#endif
+
+#include <X11/fonts/fntfilst.h>
+#include <X11/fonts/bitmap.h>
+#include <X11/fonts/fontutil.h>
+#include <X11/fonts/bdfint.h>
+#include <X11/fonts/pcf.h>
+#include "snfstr.h"
+
+typedef struct _BitmapFileFunctions {
+ int (*ReadFont) (FontPtr /* pFont */, FontFilePtr /* file */,
+ int /* bit */, int /* byte */,
+ int /* glyph */, int /* scan */);
+ int (*ReadInfo) ( FontInfoPtr /* pFontInfo */,
+ FontFilePtr /* file */ );
+} BitmapFileFunctionsRec, *BitmapFileFunctionsPtr;
+
+static int BitmapGetRenderIndex(FontRendererPtr renderer);
+
+/*
+ * the readers[] and renderers[] arrays must be in the same order,
+ * and also in the same order as scale[] and find_scale[] in bitscale.c
+ *
+ */
+static BitmapFileFunctionsRec readers[] = {
+#if XFONT_PCFFORMAT
+ { pcfReadFont, pcfReadFontInfo} ,
+ { pcfReadFont, pcfReadFontInfo} ,
+# ifdef X_GZIP_FONT_COMPRESSION
+ { pcfReadFont, pcfReadFontInfo} ,
+# endif
+# ifdef X_BZIP2_FONT_COMPRESSION
+ { pcfReadFont, pcfReadFontInfo} ,
+# endif
+#endif
+#if XFONT_SNFFORMAT
+ { snfReadFont, snfReadFontInfo},
+ { snfReadFont, snfReadFontInfo},
+# ifdef X_GZIP_FONT_COMPRESSION
+ { snfReadFont, snfReadFontInfo} ,
+# endif
+# ifdef X_BZIP2_FONT_COMPRESSION
+ { snfReadFont, snfReadFontInfo} ,
+# endif
+#endif
+#if XFONT_BDFFORMAT
+ { bdfReadFont, bdfReadFontInfo} ,
+ { bdfReadFont, bdfReadFontInfo} ,
+# ifdef X_GZIP_FONT_COMPRESSION
+ { bdfReadFont, bdfReadFontInfo} ,
+# endif
+# ifdef X_BZIP2_FONT_COMPRESSION
+ { bdfReadFont, bdfReadFontInfo} ,
+# endif
+#endif
+ { NULL, NULL }
+};
+
+
+#define CAPABILITIES (CAP_MATRIX | CAP_CHARSUBSETTING)
+
+static int
+BitmapOpenBitmap (FontPathElementPtr fpe, FontPtr *ppFont, int flags,
+ FontEntryPtr entry, char *fileName,
+ fsBitmapFormat format, fsBitmapFormatMask fmask,
+ FontPtr non_cachable_font) /* We don't do licensing */
+{
+ FontFilePtr file;
+ FontPtr pFont;
+ int i;
+ int ret;
+ int bit,
+ byte,
+ glyph,
+ scan,
+ image;
+
+ i = BitmapGetRenderIndex(entry->u.bitmap.renderer);
+ file = FontFileOpen (fileName);
+ if (!file)
+ return BadFontName;
+ if (!(pFont = CreateFontRec())) {
+ fprintf(stderr, "Error: Couldn't allocate pFont (%ld)\n",
+ (unsigned long)sizeof(FontRec));
+ FontFileClose (file);
+ return AllocError;
+ }
+ /* set up default values */
+ FontDefaultFormat(&bit, &byte, &glyph, &scan);
+ /* get any changes made from above */
+ ret = CheckFSFormat(format, fmask, &bit, &byte, &scan, &glyph, &image);
+
+ /* Fill in font record. Data format filled in by reader. */
+ pFont->refcnt = 0;
+
+ ret = (*readers[i].ReadFont) (pFont, file, bit, byte, glyph, scan);
+
+ FontFileClose (file);
+ if (ret != Successful) {
+ free(pFont);
+ } else {
+ *ppFont = pFont;
+ }
+ return ret;
+}
+
+static int
+BitmapGetInfoBitmap (FontPathElementPtr fpe, FontInfoPtr pFontInfo,
+ FontEntryPtr entry, char *fileName)
+{
+ FontFilePtr file;
+ int i;
+ int ret;
+ FontRendererPtr renderer;
+
+ renderer = FontFileMatchRenderer (fileName);
+ if (!renderer)
+ return BadFontName;
+ i = BitmapGetRenderIndex(renderer);
+ file = FontFileOpen (fileName);
+ if (!file)
+ return BadFontName;
+ ret = (*readers[i].ReadInfo) (pFontInfo, file);
+ FontFileClose (file);
+ return ret;
+}
+
+static FontRendererRec renderers[] = {
+#if XFONT_PCFFORMAT
+ { ".pcf", 4, BitmapOpenBitmap, BitmapOpenScalable,
+ BitmapGetInfoBitmap, BitmapGetInfoScalable, 0,
+ CAPABILITIES },
+ { ".pcf.Z", 6, BitmapOpenBitmap, BitmapOpenScalable,
+ BitmapGetInfoBitmap, BitmapGetInfoScalable, 0,
+ CAPABILITIES },
+# ifdef X_GZIP_FONT_COMPRESSION
+ { ".pcf.gz", 7,
+ BitmapOpenBitmap, BitmapOpenScalable,
+ BitmapGetInfoBitmap, BitmapGetInfoScalable, 0,
+ CAPABILITIES },
+# endif
+# ifdef X_BZIP2_FONT_COMPRESSION
+ { ".pcf.bz2", 8,
+ BitmapOpenBitmap, BitmapOpenScalable,
+ BitmapGetInfoBitmap, BitmapGetInfoScalable, 0,
+ CAPABILITIES },
+# endif
+#endif
+#if XFONT_SNFFORMAT
+ { ".snf", 4, BitmapOpenBitmap, BitmapOpenScalable,
+ BitmapGetInfoBitmap, BitmapGetInfoScalable, 0,
+ CAPABILITIES },
+ { ".snf.Z", 6, BitmapOpenBitmap, BitmapOpenScalable,
+ BitmapGetInfoBitmap, BitmapGetInfoScalable, 0,
+ CAPABILITIES },
+# ifdef X_GZIP_FONT_COMPRESSION
+ { ".snf.gz", 7, BitmapOpenBitmap, BitmapOpenScalable,
+ BitmapGetInfoBitmap, BitmapGetInfoScalable, 0,
+ CAPABILITIES },
+# endif
+# ifdef X_BZIP2_FONT_COMPRESSION
+ { ".snf.bz2", 8, BitmapOpenBitmap, BitmapOpenScalable,
+ BitmapGetInfoBitmap, BitmapGetInfoScalable, 0,
+ CAPABILITIES },
+# endif
+#endif
+#if XFONT_BDFFORMAT
+ { ".bdf", 4, BitmapOpenBitmap, BitmapOpenScalable,
+ BitmapGetInfoBitmap, BitmapGetInfoScalable, 0,
+ CAPABILITIES },
+ { ".bdf.Z", 6, BitmapOpenBitmap, BitmapOpenScalable,
+ BitmapGetInfoBitmap, BitmapGetInfoScalable, 0,
+ CAPABILITIES },
+# ifdef X_GZIP_FONT_COMPRESSION
+ { ".bdf.gz", 7, BitmapOpenBitmap, BitmapOpenScalable,
+ BitmapGetInfoBitmap, BitmapGetInfoScalable, 0,
+ CAPABILITIES },
+# endif
+# ifdef X_BZIP2_FONT_COMPRESSION
+ { ".bdf.bz2", 8, BitmapOpenBitmap, BitmapOpenScalable,
+ BitmapGetInfoBitmap, BitmapGetInfoScalable, 0,
+ CAPABILITIES },
+# endif
+#endif
+ { NULL, 0, NULL, 0, NULL, NULL, 0, 0 }
+};
+
+#define numRenderers (sizeof renderers / sizeof renderers[0] - 1)
+
+void
+BitmapRegisterFontFileFunctions (void)
+{
+ int i;
+
+ for (i = 0; i < numRenderers; i++)
+ FontFileRegisterRenderer (&renderers[i]);
+}
+
+/*
+ * compute offset into renderers array - used to find the font reader,
+ * the font info reader, and the bitmap scaling routine. All users
+ * of this routine must be kept in step with the renderer array.
+ */
+static int
+BitmapGetRenderIndex(FontRendererPtr renderer)
+{
+ return renderer - renderers;
+}
diff --git a/libXfont/src/bitmap/bitmaputil.c b/libXfont/src/bitmap/bitmaputil.c index 0a1c87e73..c44bf9cae 100644 --- a/libXfont/src/bitmap/bitmaputil.c +++ b/libXfont/src/bitmap/bitmaputil.c @@ -1,229 +1,225 @@ -/* - -Copyright 1990, 1994, 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. - -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <X11/fonts/fntfilst.h> -#include <X11/fonts/bitmap.h> -#include <X11/fonts/bdfint.h> - -#ifndef MAXSHORT -#define MAXSHORT 32767 -#endif - -#ifndef MINSHORT -#define MINSHORT -32768 -#endif - -static xCharInfo initMinMetrics = { -MAXSHORT, MAXSHORT, MAXSHORT, MAXSHORT, MAXSHORT, 0xFFFF}; -static xCharInfo initMaxMetrics = { -MINSHORT, MINSHORT, MINSHORT, MINSHORT, MINSHORT, 0x0000}; - -#define MINMAX(field,ci) \ - if (minbounds->field > (ci)->field) \ - minbounds->field = (ci)->field; \ - if (maxbounds->field < (ci)->field) \ - maxbounds->field = (ci)->field; - -#define COMPUTE_MINMAX(ci) \ - if ((ci)->ascent || (ci)->descent || \ - (ci)->leftSideBearing || (ci)->rightSideBearing || \ - (ci)->characterWidth) \ - { \ - MINMAX(ascent, (ci)); \ - MINMAX(descent, (ci)); \ - MINMAX(leftSideBearing, (ci)); \ - MINMAX(rightSideBearing, (ci)); \ - MINMAX(characterWidth, (ci)); \ - } - -void -bitmapComputeFontBounds(FontPtr pFont) -{ - BitmapFontPtr bitmapFont = (BitmapFontPtr) pFont->fontPrivate; - int nchars; - int r, - c; - CharInfoPtr ci; - int maxOverlap; - int overlap; - xCharInfo *minbounds, - *maxbounds; - int i; - int numneg = 0, numpos = 0; - - if (bitmapFont->bitmapExtra) { - minbounds = &bitmapFont->bitmapExtra->info.minbounds; - maxbounds = &bitmapFont->bitmapExtra->info.maxbounds; - } else { - minbounds = &pFont->info.minbounds; - maxbounds = &pFont->info.maxbounds; - } - *minbounds = initMinMetrics; - *maxbounds = initMaxMetrics; - maxOverlap = MINSHORT; - nchars = bitmapFont->num_chars; - for (i = 0, ci = bitmapFont->metrics; i < nchars; i++, ci++) { - COMPUTE_MINMAX(&ci->metrics); - if (ci->metrics.characterWidth < 0) - numneg++; - else - numpos++; - minbounds->attributes &= ci->metrics.attributes; - maxbounds->attributes |= ci->metrics.attributes; - overlap = ci->metrics.rightSideBearing - ci->metrics.characterWidth; - if (maxOverlap < overlap) - maxOverlap = overlap; - } - if (bitmapFont->bitmapExtra) { - if (numneg > numpos) - bitmapFont->bitmapExtra->info.drawDirection = RightToLeft; - else - bitmapFont->bitmapExtra->info.drawDirection = LeftToRight; - bitmapFont->bitmapExtra->info.maxOverlap = maxOverlap; - minbounds = &pFont->info.minbounds; - maxbounds = &pFont->info.maxbounds; - *minbounds = initMinMetrics; - *maxbounds = initMaxMetrics; - i = 0; - maxOverlap = MINSHORT; - for (r = pFont->info.firstRow; r <= pFont->info.lastRow; r++) { - for (c = pFont->info.firstCol; c <= pFont->info.lastCol; c++) { - ci = ACCESSENCODING(bitmapFont->encoding, i); - if (ci) { - COMPUTE_MINMAX(&ci->metrics); - if (ci->metrics.characterWidth < 0) - numneg++; - else - numpos++; - minbounds->attributes &= ci->metrics.attributes; - maxbounds->attributes |= ci->metrics.attributes; - overlap = ci->metrics.rightSideBearing - - ci->metrics.characterWidth; - if (maxOverlap < overlap) - maxOverlap = overlap; - } - i++; - } - } - } - if (numneg > numpos) - pFont->info.drawDirection = RightToLeft; - else - pFont->info.drawDirection = LeftToRight; - pFont->info.maxOverlap = maxOverlap; -} - -void -bitmapComputeFontInkBounds(FontPtr pFont) -{ - BitmapFontPtr bitmapFont = (BitmapFontPtr) pFont->fontPrivate; - int nchars; - int r, - c; - CharInfoPtr cit; - xCharInfo *ci; - int offset; - xCharInfo *minbounds, - *maxbounds; - int i; - - if (!bitmapFont->ink_metrics) { - if (bitmapFont->bitmapExtra) { - bitmapFont->bitmapExtra->info.ink_minbounds = bitmapFont->bitmapExtra->info.minbounds; - bitmapFont->bitmapExtra->info.ink_maxbounds = bitmapFont->bitmapExtra->info.maxbounds; - } - pFont->info.ink_minbounds = pFont->info.minbounds; - pFont->info.ink_maxbounds = pFont->info.maxbounds; - } else { - if (bitmapFont->bitmapExtra) { - minbounds = &bitmapFont->bitmapExtra->info.ink_minbounds; - maxbounds = &bitmapFont->bitmapExtra->info.ink_maxbounds; - } else { - minbounds = &pFont->info.ink_minbounds; - maxbounds = &pFont->info.ink_maxbounds; - } - *minbounds = initMinMetrics; - *maxbounds = initMaxMetrics; - nchars = bitmapFont->num_chars; - for (i = 0, ci = bitmapFont->ink_metrics; i < nchars; i++, ci++) { - COMPUTE_MINMAX(ci); - minbounds->attributes &= ci->attributes; - maxbounds->attributes |= ci->attributes; - } - if (bitmapFont->bitmapExtra) { - minbounds = &pFont->info.ink_minbounds; - maxbounds = &pFont->info.ink_maxbounds; - *minbounds = initMinMetrics; - *maxbounds = initMaxMetrics; - i=0; - for (r = pFont->info.firstRow; r <= pFont->info.lastRow; r++) { - for (c = pFont->info.firstCol; c <= pFont->info.lastCol; c++) { - cit = ACCESSENCODING(bitmapFont->encoding, i); - if (cit) { - offset = cit - bitmapFont->metrics; - ci = &bitmapFont->ink_metrics[offset]; - COMPUTE_MINMAX(ci); - minbounds->attributes &= ci->attributes; - maxbounds->attributes |= ci->attributes; - } - i++; - } - } - } - } -} - -Bool -bitmapAddInkMetrics(FontPtr pFont) -{ - BitmapFontPtr bitmapFont; - int i; - - bitmapFont = (BitmapFontPtr) pFont->fontPrivate; - bitmapFont->ink_metrics = malloc(bitmapFont->num_chars * sizeof(xCharInfo)); - if (!bitmapFont->ink_metrics) { - fprintf(stderr, "Error: Couldn't allocate ink_metrics (%d*%ld)\n", - bitmapFont->num_chars, (unsigned long)sizeof(xCharInfo)); - return FALSE; - } - for (i = 0; i < bitmapFont->num_chars; i++) - FontCharInkMetrics(pFont, &bitmapFont->metrics[i], &bitmapFont->ink_metrics[i]); - pFont->info.inkMetrics = TRUE; - return TRUE; -} - -/* ARGSUSED */ -int -bitmapComputeWeight(FontPtr pFont) -{ - return 10; -} +/*
+
+Copyright 1990, 1994, 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.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <X11/fonts/fntfilst.h>
+#include <X11/fonts/bitmap.h>
+#include <X11/fonts/bdfint.h>
+
+#define MAXSHORT 32767
+
+#define MINSHORT -32768
+
+static xCharInfo initMinMetrics = {
+MAXSHORT, MAXSHORT, MAXSHORT, MAXSHORT, MAXSHORT, 0xFFFF};
+static xCharInfo initMaxMetrics = {
+MINSHORT, MINSHORT, MINSHORT, MINSHORT, MINSHORT, 0x0000};
+
+#define MINMAX(field,ci) \
+ if (minbounds->field > (ci)->field) \
+ minbounds->field = (ci)->field; \
+ if (maxbounds->field < (ci)->field) \
+ maxbounds->field = (ci)->field;
+
+#define COMPUTE_MINMAX(ci) \
+ if ((ci)->ascent || (ci)->descent || \
+ (ci)->leftSideBearing || (ci)->rightSideBearing || \
+ (ci)->characterWidth) \
+ { \
+ MINMAX(ascent, (ci)); \
+ MINMAX(descent, (ci)); \
+ MINMAX(leftSideBearing, (ci)); \
+ MINMAX(rightSideBearing, (ci)); \
+ MINMAX(characterWidth, (ci)); \
+ }
+
+void
+bitmapComputeFontBounds(FontPtr pFont)
+{
+ BitmapFontPtr bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
+ int nchars;
+ int r,
+ c;
+ CharInfoPtr ci;
+ int maxOverlap;
+ int overlap;
+ xCharInfo *minbounds,
+ *maxbounds;
+ int i;
+ int numneg = 0, numpos = 0;
+
+ if (bitmapFont->bitmapExtra) {
+ minbounds = &bitmapFont->bitmapExtra->info.minbounds;
+ maxbounds = &bitmapFont->bitmapExtra->info.maxbounds;
+ } else {
+ minbounds = &pFont->info.minbounds;
+ maxbounds = &pFont->info.maxbounds;
+ }
+ *minbounds = initMinMetrics;
+ *maxbounds = initMaxMetrics;
+ maxOverlap = MINSHORT;
+ nchars = bitmapFont->num_chars;
+ for (i = 0, ci = bitmapFont->metrics; i < nchars; i++, ci++) {
+ COMPUTE_MINMAX(&ci->metrics);
+ if (ci->metrics.characterWidth < 0)
+ numneg++;
+ else
+ numpos++;
+ minbounds->attributes &= ci->metrics.attributes;
+ maxbounds->attributes |= ci->metrics.attributes;
+ overlap = ci->metrics.rightSideBearing - ci->metrics.characterWidth;
+ if (maxOverlap < overlap)
+ maxOverlap = overlap;
+ }
+ if (bitmapFont->bitmapExtra) {
+ if (numneg > numpos)
+ bitmapFont->bitmapExtra->info.drawDirection = RightToLeft;
+ else
+ bitmapFont->bitmapExtra->info.drawDirection = LeftToRight;
+ bitmapFont->bitmapExtra->info.maxOverlap = maxOverlap;
+ minbounds = &pFont->info.minbounds;
+ maxbounds = &pFont->info.maxbounds;
+ *minbounds = initMinMetrics;
+ *maxbounds = initMaxMetrics;
+ i = 0;
+ maxOverlap = MINSHORT;
+ for (r = pFont->info.firstRow; r <= pFont->info.lastRow; r++) {
+ for (c = pFont->info.firstCol; c <= pFont->info.lastCol; c++) {
+ ci = ACCESSENCODING(bitmapFont->encoding, i);
+ if (ci) {
+ COMPUTE_MINMAX(&ci->metrics);
+ if (ci->metrics.characterWidth < 0)
+ numneg++;
+ else
+ numpos++;
+ minbounds->attributes &= ci->metrics.attributes;
+ maxbounds->attributes |= ci->metrics.attributes;
+ overlap = ci->metrics.rightSideBearing -
+ ci->metrics.characterWidth;
+ if (maxOverlap < overlap)
+ maxOverlap = overlap;
+ }
+ i++;
+ }
+ }
+ }
+ if (numneg > numpos)
+ pFont->info.drawDirection = RightToLeft;
+ else
+ pFont->info.drawDirection = LeftToRight;
+ pFont->info.maxOverlap = maxOverlap;
+}
+
+void
+bitmapComputeFontInkBounds(FontPtr pFont)
+{
+ BitmapFontPtr bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
+ int nchars;
+ int r,
+ c;
+ CharInfoPtr cit;
+ xCharInfo *ci;
+ int offset;
+ xCharInfo *minbounds,
+ *maxbounds;
+ int i;
+
+ if (!bitmapFont->ink_metrics) {
+ if (bitmapFont->bitmapExtra) {
+ bitmapFont->bitmapExtra->info.ink_minbounds = bitmapFont->bitmapExtra->info.minbounds;
+ bitmapFont->bitmapExtra->info.ink_maxbounds = bitmapFont->bitmapExtra->info.maxbounds;
+ }
+ pFont->info.ink_minbounds = pFont->info.minbounds;
+ pFont->info.ink_maxbounds = pFont->info.maxbounds;
+ } else {
+ if (bitmapFont->bitmapExtra) {
+ minbounds = &bitmapFont->bitmapExtra->info.ink_minbounds;
+ maxbounds = &bitmapFont->bitmapExtra->info.ink_maxbounds;
+ } else {
+ minbounds = &pFont->info.ink_minbounds;
+ maxbounds = &pFont->info.ink_maxbounds;
+ }
+ *minbounds = initMinMetrics;
+ *maxbounds = initMaxMetrics;
+ nchars = bitmapFont->num_chars;
+ for (i = 0, ci = bitmapFont->ink_metrics; i < nchars; i++, ci++) {
+ COMPUTE_MINMAX(ci);
+ minbounds->attributes &= ci->attributes;
+ maxbounds->attributes |= ci->attributes;
+ }
+ if (bitmapFont->bitmapExtra) {
+ minbounds = &pFont->info.ink_minbounds;
+ maxbounds = &pFont->info.ink_maxbounds;
+ *minbounds = initMinMetrics;
+ *maxbounds = initMaxMetrics;
+ i=0;
+ for (r = pFont->info.firstRow; r <= pFont->info.lastRow; r++) {
+ for (c = pFont->info.firstCol; c <= pFont->info.lastCol; c++) {
+ cit = ACCESSENCODING(bitmapFont->encoding, i);
+ if (cit) {
+ offset = cit - bitmapFont->metrics;
+ ci = &bitmapFont->ink_metrics[offset];
+ COMPUTE_MINMAX(ci);
+ minbounds->attributes &= ci->attributes;
+ maxbounds->attributes |= ci->attributes;
+ }
+ i++;
+ }
+ }
+ }
+ }
+}
+
+Bool
+bitmapAddInkMetrics(FontPtr pFont)
+{
+ BitmapFontPtr bitmapFont;
+ int i;
+
+ bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
+ bitmapFont->ink_metrics = malloc(bitmapFont->num_chars * sizeof(xCharInfo));
+ if (!bitmapFont->ink_metrics) {
+ fprintf(stderr, "Error: Couldn't allocate ink_metrics (%d*%ld)\n",
+ bitmapFont->num_chars, (unsigned long)sizeof(xCharInfo));
+ return FALSE;
+ }
+ for (i = 0; i < bitmapFont->num_chars; i++)
+ FontCharInkMetrics(pFont, &bitmapFont->metrics[i], &bitmapFont->ink_metrics[i]);
+ pFont->info.inkMetrics = TRUE;
+ return TRUE;
+}
+
+/* ARGSUSED */
+int
+bitmapComputeWeight(FontPtr pFont)
+{
+ return 10;
+}
diff --git a/libXfont/src/bitmap/bitscale.c b/libXfont/src/bitmap/bitscale.c index cf16bffed..cf22a4593 100644 --- a/libXfont/src/bitmap/bitscale.c +++ b/libXfont/src/bitmap/bitscale.c @@ -1,1691 +1,1695 @@ -/* - -Copyright 1991, 1994, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -/* - * Translate monolithic #defines to modular definitions - */ - -#ifdef PCFFORMAT -#define XFONT_PCFFORMAT 1 -#endif - -#ifdef SNFFORMAT -#define XFONT_SNFFORMAT 1 -#endif - -#ifdef BDFFORMAT -#define XFONT_BDFFORMAT 1 -#endif - -#include <X11/fonts/fntfilst.h> -#include <X11/fonts/bitmap.h> -#include <X11/fonts/fontutil.h> -#include <math.h> - -#ifndef MAX -#define MAX(a,b) (((a)>(b)) ? a : b) -#endif - -/* Should get this from elsewhere */ -extern unsigned long serverGeneration; - -static void bitmapUnloadScalable (FontPtr pFont); -static void ScaleBitmap ( FontPtr pFont, CharInfoPtr opci, - CharInfoPtr pci, double *inv_xform, - double widthMult, double heightMult ); -static FontPtr BitmapScaleBitmaps(FontPtr pf, FontPtr opf, - double widthMult, double heightMult, - FontScalablePtr vals); - -enum scaleType { - atom, truncate_atom, pixel_size, point_size, resolution_x, - resolution_y, average_width, scaledX, scaledY, unscaled, fontname, - raw_ascent, raw_descent, raw_pixelsize, raw_pointsize, - raw_average_width, uncomputed -}; - -typedef struct _fontProp { - char *name; - Atom atom; - enum scaleType type; -} fontProp; - -static FontEntryPtr FindBestToScale ( FontPathElementPtr fpe, - FontEntryPtr entry, - FontScalablePtr vals, - FontScalablePtr best, - double *dxp, double *dyp, - double *sdxp, double *sdyp, - FontPathElementPtr *fpep ); - -static unsigned long bitscaleGeneration = 0; /* initialization flag */ - -static fontProp fontNamePropTable[] = { - { "FOUNDRY", 0, atom }, - { "FAMILY_NAME", 0, atom }, - { "WEIGHT_NAME", 0, atom }, - { "SLANT", 0, atom }, - { "SETWIDTH_NAME", 0, atom }, - { "ADD_STYLE_NAME", 0, atom }, - { "PIXEL_SIZE", 0, pixel_size }, - { "POINT_SIZE", 0, point_size }, - { "RESOLUTION_X", 0, resolution_x }, - { "RESOLUTION_Y", 0, resolution_y }, - { "SPACING", 0, atom }, - { "AVERAGE_WIDTH", 0, average_width }, - { "CHARSET_REGISTRY", 0, atom }, - { "CHARSET_ENCODING", 0, truncate_atom }, - { "FONT", 0, fontname }, - { "RAW_ASCENT", 0, raw_ascent }, - { "RAW_DESCENT", 0, raw_descent }, - { "RAW_PIXEL_SIZE", 0, raw_pixelsize }, - { "RAW_POINT_SIZE", 0, raw_pointsize }, - { "RAW_AVERAGE_WIDTH", 0, raw_average_width } -}; - -#define TRANSFORM_POINT(matrix, x, y, dest) \ - ((dest)[0] = (matrix)[0] * (x) + (matrix)[2] * (y), \ - (dest)[1] = (matrix)[1] * (x) + (matrix)[3] * (y)) - -#define CHECK_EXTENT(lsb, rsb, desc, asc, data) \ - ((lsb) > (data)[0] ? (lsb) = (data)[0] : 0 , \ - (rsb) < (data)[0] ? (rsb) = (data)[0] : 0, \ - (-desc) > (data)[1] ? (desc) = -(data)[1] : 0 , \ - (asc) < (data)[1] ? (asc) = (data)[1] : 0) - -#define NPROPS (sizeof(fontNamePropTable) / sizeof(fontProp)) - -/* Warning: order of the next two tables is critically interdependent. - Location of "unscaled" properties at the end of fontPropTable[] - is important. */ - -static fontProp fontPropTable[] = { - { "MIN_SPACE", 0, scaledX }, - { "NORM_SPACE", 0, scaledX }, - { "MAX_SPACE", 0, scaledX }, - { "END_SPACE", 0, scaledX }, - { "AVG_CAPITAL_WIDTH", 0, scaledX }, - { "AVG_LOWERCASE_WIDTH", 0, scaledX }, - { "QUAD_WIDTH", 0, scaledX }, - { "FIGURE_WIDTH", 0, scaledX }, - { "SUPERSCRIPT_X", 0, scaledX }, - { "SUPERSCRIPT_Y", 0, scaledY }, - { "SUBSCRIPT_X", 0, scaledX }, - { "SUBSCRIPT_Y", 0, scaledY }, - { "SUPERSCRIPT_SIZE", 0, scaledY }, - { "SUBSCRIPT_SIZE", 0, scaledY }, - { "SMALL_CAP_SIZE", 0, scaledY }, - { "UNDERLINE_POSITION", 0, scaledY }, - { "UNDERLINE_THICKNESS", 0, scaledY }, - { "STRIKEOUT_ASCENT", 0, scaledY }, - { "STRIKEOUT_DESCENT", 0, scaledY }, - { "CAP_HEIGHT", 0, scaledY }, - { "X_HEIGHT", 0, scaledY }, - { "ITALIC_ANGLE", 0, unscaled }, - { "RELATIVE_SETWIDTH", 0, unscaled }, - { "RELATIVE_WEIGHT", 0, unscaled }, - { "WEIGHT", 0, unscaled }, - { "DESTINATION", 0, unscaled }, - { "PCL_FONT_NAME", 0, unscaled }, - { "_ADOBE_POSTSCRIPT_FONTNAME", 0, unscaled } -}; - -static fontProp rawFontPropTable[] = { - { "RAW_MIN_SPACE", 0, }, - { "RAW_NORM_SPACE", 0, }, - { "RAW_MAX_SPACE", 0, }, - { "RAW_END_SPACE", 0, }, - { "RAW_AVG_CAPITAL_WIDTH", 0, }, - { "RAW_AVG_LOWERCASE_WIDTH", 0, }, - { "RAW_QUAD_WIDTH", 0, }, - { "RAW_FIGURE_WIDTH", 0, }, - { "RAW_SUPERSCRIPT_X", 0, }, - { "RAW_SUPERSCRIPT_Y", 0, }, - { "RAW_SUBSCRIPT_X", 0, }, - { "RAW_SUBSCRIPT_Y", 0, }, - { "RAW_SUPERSCRIPT_SIZE", 0, }, - { "RAW_SUBSCRIPT_SIZE", 0, }, - { "RAW_SMALL_CAP_SIZE", 0, }, - { "RAW_UNDERLINE_POSITION", 0, }, - { "RAW_UNDERLINE_THICKNESS", 0, }, - { "RAW_STRIKEOUT_ASCENT", 0, }, - { "RAW_STRIKEOUT_DESCENT", 0, }, - { "RAW_CAP_HEIGHT", 0, }, - { "RAW_X_HEIGHT", 0, } -}; - -static void -initFontPropTable(void) -{ - int i; - fontProp *t; - - i = sizeof(fontNamePropTable) / sizeof(fontProp); - for (t = fontNamePropTable; i; i--, t++) - t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE); - - i = sizeof(fontPropTable) / sizeof(fontProp); - for (t = fontPropTable; i; i--, t++) - t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE); - - i = sizeof(rawFontPropTable) / sizeof(fontProp); - for (t = rawFontPropTable; i; i--, t++) - t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE); -} - -#if 0 -static FontEntryPtr -GetScalableEntry (FontPathElementPtr fpe, FontNamePtr name) -{ - FontDirectoryPtr dir; - - dir = (FontDirectoryPtr) fpe->private; - return FontFileFindNameInDir (&dir->scalable, name); -} -#endif - -static double -get_matrix_horizontal_component(double *matrix) -{ - return hypot(matrix[0], matrix[1]); -} - -static double -get_matrix_vertical_component(double *matrix) -{ - return hypot(matrix[2], matrix[3]); -} - - -static Bool -ComputeScaleFactors(FontScalablePtr from, FontScalablePtr to, - double *dx, double *dy, double *sdx, double *sdy, - double *rescale_x) -{ - double srcpixelset, destpixelset, srcpixel, destpixel; - - srcpixelset = get_matrix_horizontal_component(from->pixel_matrix); - destpixelset = get_matrix_horizontal_component(to->pixel_matrix); - srcpixel = get_matrix_vertical_component(from->pixel_matrix); - destpixel = get_matrix_vertical_component(to->pixel_matrix); - - if (srcpixelset >= EPS) - { - *dx = destpixelset / srcpixelset; - *sdx = 1000.0 / srcpixelset; - } - else - *sdx = *dx = 0; - - *rescale_x = 1.0; - - /* If client specified a width, it overrides setsize; in this - context, we interpret width as applying to the font before any - rotation, even though that's not what is ultimately returned in - the width field. */ - if (from->width > 0 && to->width > 0 && fabs(*dx) > EPS) - { - double rescale = (double)to->width / (double)from->width; - - /* If the client specified a transformation matrix, the rescaling - for width does *not* override the setsize. Instead, just check - for consistency between the setsize from the matrix and the - setsize that would result from rescaling according to the width. - This assumes (perhaps naively) that the width is correctly - reported in the name. As an interesting side effect, this test - may result in choosing a different source bitmap (one that - scales consistently between the setsize *and* the width) than it - would choose if a width were not specified. Sort of a hidden - multiple-master functionality. */ - if ((to->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY || - (to->values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY) - { - /* Reject if resulting width difference is >= 1 pixel */ - if (fabs(rescale * from->width - *dx * from->width) >= 10) - return FALSE; - } - else - { - *rescale_x = rescale/(*dx); - *dx = rescale; - } - } - - if (srcpixel >= EPS) - { - *dy = destpixel / srcpixel; - *sdy = 1000.0 / srcpixel; - } - else - *sdy = *dy = 0; - - return TRUE; -} - -/* favor enlargement over reduction because of aliasing resulting - from reduction */ -#define SCORE(m,s) \ -if (m >= 1.0) { \ - if (m == 1.0) \ - score += (16 * s); \ - else if (m == 2.0) \ - score += (4 * s); \ - else \ - score += (int)(((double)(3 * s)) / m); \ -} else { \ - score += (int)(((double)(2 * s)) * m); \ -} - -/* don't need to favor enlargement when looking for bitmap that can - be used unscalable */ -#define SCORE2(m,s) \ -if (m >= 1.0) \ - score += (int)(((double)(8 * s)) / m); \ -else \ - score += (int)(((double)(8 * s)) * m); - -static FontEntryPtr -FindBestToScale(FontPathElementPtr fpe, FontEntryPtr entry, - FontScalablePtr vals, FontScalablePtr best, - double *dxp, double *dyp, - double *sdxp, double *sdyp, - FontPathElementPtr *fpep) -{ - FontScalableRec temp; - int source, i; - int best_score, best_unscaled_score, - score; - double dx = 0.0, sdx = 0.0, dx_amount = 0.0, - dy = 0.0, sdy = 0.0, dy_amount = 0.0, - best_dx = 0.0, best_sdx = 0.0, best_dx_amount = 0.0, - best_dy = 0.0, best_sdy = 0.0, best_dy_amount = 0.0, - best_unscaled_sdx = 0.0, best_unscaled_sdy = 0.0, - rescale_x = 0.0, best_rescale_x = 0.0, - best_unscaled_rescale_x = 0.0; - FontEntryPtr zero; - FontNameRec zeroName; - char zeroChars[MAXFONTNAMELEN]; - FontDirectoryPtr dir; - FontScaledPtr scaled; - FontScalableExtraPtr extra; - FontScaledPtr best_scaled, best_unscaled; - FontPathElementPtr best_fpe = NULL, best_unscaled_fpe = NULL; - FontEntryPtr bitmap = NULL; - FontEntryPtr result; - int aliascount = 20; - FontPathElementPtr bitmap_fpe = NULL; - FontNameRec xlfdName; - - /* find the best match */ - rescale_x = 1.0; - best_scaled = 0; - best_score = 0; - best_unscaled = 0; - best_unscaled_score = -1; - best_dx_amount = best_dy_amount = HUGE_VAL; - memcpy (zeroChars, entry->name.name, entry->name.length); - zeroChars[entry->name.length] = '\0'; - zeroName.name = zeroChars; - FontParseXLFDName (zeroChars, &temp, FONT_XLFD_REPLACE_ZERO); - zeroName.length = strlen (zeroChars); - zeroName.ndashes = entry->name.ndashes; - xlfdName.name = vals->xlfdName; - xlfdName.length = strlen(xlfdName.name); - xlfdName.ndashes = FontFileCountDashes(xlfdName.name, xlfdName.length); - restart_bestscale_loop: ; - /* - * Look through all the registered bitmap sources for - * the same zero name as ours; entries along that one - * can be scaled as desired. - */ - for (source = 0; source < FontFileBitmapSources.count; source++) - { - /* There might already be a bitmap that satisfies the request - but didn't have a zero name that was found by the scalable - font matching logic. Keep track if there is. */ - if (bitmap == NULL && vals->xlfdName != NULL) - { - bitmap_fpe = FontFileBitmapSources.fpe[source]; - dir = (FontDirectoryPtr) bitmap_fpe->private; - bitmap = FontFileFindNameInDir (&dir->nonScalable, &xlfdName); - if (bitmap && bitmap->type != FONT_ENTRY_BITMAP) - { - if (bitmap->type == FONT_ENTRY_ALIAS && aliascount > 0) - { - aliascount--; - xlfdName.name = bitmap->u.alias.resolved; - xlfdName.length = strlen(xlfdName.name); - xlfdName.ndashes = FontFileCountDashes(xlfdName.name, - xlfdName.length); - bitmap = NULL; - goto restart_bestscale_loop; - } - else - bitmap = NULL; - } - } - - if (FontFileBitmapSources.fpe[source] == fpe) - zero = entry; - else - { - dir = (FontDirectoryPtr) FontFileBitmapSources.fpe[source]->private; - zero = FontFileFindNameInDir (&dir->scalable, &zeroName); - if (!zero) - continue; - } - extra = zero->u.scalable.extra; - for (i = 0; i < extra->numScaled; i++) - { - scaled = &extra->scaled[i]; - if (!scaled->bitmap) - continue; - if (!ComputeScaleFactors(&scaled->vals, vals, &dx, &dy, &sdx, &sdy, - &rescale_x)) - continue; - score = 0; - dx_amount = dx; - dy_amount = dy; - SCORE(dy_amount, 10); - SCORE(dx_amount, 1); - if ((score > best_score) || - ((score == best_score) && - ((dy_amount < best_dy_amount) || - ((dy_amount == best_dy_amount) && - (dx_amount < best_dx_amount))))) - { - best_fpe = FontFileBitmapSources.fpe[source]; - best_scaled = scaled; - best_score = score; - best_dx = dx; - best_dy = dy; - best_sdx = sdx; - best_sdy = sdy; - best_dx_amount = dx_amount; - best_dy_amount = dy_amount; - best_rescale_x = rescale_x; - } - /* Is this font a candidate for use without ugly rescaling? */ - if (fabs(dx) > EPS && fabs(dy) > EPS && - fabs(vals->pixel_matrix[0] * rescale_x - - scaled->vals.pixel_matrix[0]) < 1 && - fabs(vals->pixel_matrix[1] * rescale_x - - scaled->vals.pixel_matrix[1]) < EPS && - fabs(vals->pixel_matrix[2] - - scaled->vals.pixel_matrix[2]) < EPS && - fabs(vals->pixel_matrix[3] - - scaled->vals.pixel_matrix[3]) < 1) - { - /* Yes. The pixel sizes are close on the diagonal and - extremely close off the diagonal. */ - score = 0; - SCORE2(vals->pixel_matrix[3] / - scaled->vals.pixel_matrix[3], 10); - SCORE2(vals->pixel_matrix[0] * rescale_x / - scaled->vals.pixel_matrix[0], 1); - if (score > best_unscaled_score) - { - best_unscaled_fpe = FontFileBitmapSources.fpe[source]; - best_unscaled = scaled; - best_unscaled_sdx = sdx / dx; - best_unscaled_sdy = sdy / dy; - best_unscaled_score = score; - best_unscaled_rescale_x = rescale_x; - } - } - } - } - if (best_unscaled) - { - *best = best_unscaled->vals; - *fpep = best_unscaled_fpe; - *dxp = 1.0; - *dyp = 1.0; - *sdxp = best_unscaled_sdx; - *sdyp = best_unscaled_sdy; - rescale_x = best_unscaled_rescale_x; - result = best_unscaled->bitmap; - } - else if (best_scaled) - { - *best = best_scaled->vals; - *fpep = best_fpe; - *dxp = best_dx; - *dyp = best_dy; - *sdxp = best_sdx; - *sdyp = best_sdy; - rescale_x = best_rescale_x; - result = best_scaled->bitmap; - } - else - result = NULL; - - if (bitmap != NULL && (result == NULL || *dxp != 1.0 || *dyp != 1.0)) - { - *fpep = bitmap_fpe; - FontParseXLFDName (bitmap->name.name, best, FONT_XLFD_REPLACE_NONE); - if (ComputeScaleFactors(best, best, dxp, dyp, sdxp, sdyp, &rescale_x)) - result = bitmap; - else - result = NULL; - } - - if (result && rescale_x != 1.0) - { - /* We have rescaled horizontally due to an XLFD width field. Change - the matrix appropriately */ - vals->pixel_matrix[0] *= rescale_x; - vals->pixel_matrix[1] *= rescale_x; - vals->values_supplied = vals->values_supplied & ~POINTSIZE_MASK; - /* Recompute and reround the FontScalablePtr values after - rescaling for the new width. */ - FontFileCompleteXLFD(vals, vals); - } - - return result; -} - -static long -doround(double x) -{ - return (x >= 0) ? (long)(x + .5) : (long)(x - .5); -} - -static int -computeProps(FontPropPtr pf, char *wasStringProp, - FontPropPtr npf, char *isStringProp, - unsigned int nprops, double xfactor, double yfactor, - double sXfactor, double sYfactor) -{ - int n; - int count; - fontProp *t; - double rawfactor = 0.0; - - for (count = 0; nprops > 0; nprops--, pf++, wasStringProp++) { - n = sizeof(fontPropTable) / sizeof(fontProp); - for (t = fontPropTable; n && (t->atom != pf->name); n--, t++); - if (!n) - continue; - - switch (t->type) { - case scaledX: - npf->value = doround(xfactor * (double)pf->value); - rawfactor = sXfactor; - break; - case scaledY: - npf->value = doround(yfactor * (double)pf->value); - rawfactor = sYfactor; - break; - case unscaled: - npf->value = pf->value; - npf->name = pf->name; - npf++; - count++; - *isStringProp++ = *wasStringProp; - break; - default: - break; - } - if (t->type != unscaled) - { - npf->name = pf->name; - npf++; - count++; - npf->value = doround(rawfactor * (double)pf->value); - npf->name = rawFontPropTable[t - fontPropTable].atom; - npf++; - count++; - *isStringProp++ = *wasStringProp; - *isStringProp++ = *wasStringProp; - } - } - return count; -} - - -static int -ComputeScaledProperties(FontInfoPtr sourceFontInfo, /* the font to be scaled */ - char *name, /* name of resulting font */ - FontScalablePtr vals, - double dx, double dy, /* scale factors in x and y */ - double sdx, double sdy, /* directions */ - long sWidth, /* 1000-pixel average width */ - FontPropPtr *pProps, /* returns properties; - preallocated */ - char **pIsStringProp) /* return booleans; - preallocated */ -{ - int n; - char *ptr1 = NULL, *ptr2 = NULL; - char *ptr3; - FontPropPtr fp; - fontProp *fpt; - char *isStringProp; - int nProps; - - if (bitscaleGeneration != serverGeneration) { - initFontPropTable(); - bitscaleGeneration = serverGeneration; - } - nProps = NPROPS + 1 + sizeof(fontPropTable) / sizeof(fontProp) + - sizeof(rawFontPropTable) / sizeof(fontProp); - fp = malloc(sizeof(FontPropRec) * nProps); - *pProps = fp; - if (!fp) { - fprintf(stderr, "Error: Couldn't allocate font properties (%ld*%d)\n", - (unsigned long)sizeof(FontPropRec), nProps); - return 1; - } - isStringProp = malloc (nProps); - *pIsStringProp = isStringProp; - if (!isStringProp) - { - fprintf(stderr, "Error: Couldn't allocate isStringProp (%d)\n", nProps); - free (fp); - return 1; - } - ptr2 = name; - for (fpt = fontNamePropTable, n = NPROPS; - n; - fp++, fpt++, n--, isStringProp++) - { - - if (*ptr2) - { - ptr1 = ptr2 + 1; - if (!(ptr2 = strchr(ptr1, '-'))) ptr2 = strchr(ptr1, '\0'); - } - - *isStringProp = 0; - switch (fpt->type) { - case atom: - fp->value = MakeAtom(ptr1, ptr2 - ptr1, TRUE); - *isStringProp = 1; - break; - case truncate_atom: - for (ptr3 = ptr1; *ptr3; ptr3++) - if (*ptr3 == '[') - break; - if (!*ptr3) ptr3 = ptr2; - fp->value = MakeAtom(ptr1, ptr3 - ptr1, TRUE); - *isStringProp = 1; - break; - case pixel_size: - fp->value = doround(vals->pixel_matrix[3]); - break; - case point_size: - fp->value = doround(vals->point_matrix[3] * 10.0); - break; - case resolution_x: - fp->value = vals->x; - break; - case resolution_y: - fp->value = vals->y; - break; - case average_width: - fp->value = vals->width; - break; - case fontname: - fp->value = MakeAtom(name, strlen(name), TRUE); - *isStringProp = 1; - break; - case raw_ascent: - fp->value = sourceFontInfo->fontAscent * sdy; - break; - case raw_descent: - fp->value = sourceFontInfo->fontDescent * sdy; - break; - case raw_pointsize: - fp->value = (long)(72270.0 / (double)vals->y + .5); - break; - case raw_pixelsize: - fp->value = 1000; - break; - case raw_average_width: - fp->value = sWidth; - break; - default: - break; - } - fp->name = fpt->atom; - } - n = NPROPS; - n += computeProps(sourceFontInfo->props, sourceFontInfo->isStringProp, - fp, isStringProp, sourceFontInfo->nprops, dx, dy, - sdx, sdy); - return n; -} - - -static int -compute_xform_matrix(FontScalablePtr vals, double dx, double dy, - double *xform, double *inv_xform, - double *xmult, double *ymult) -{ - double det; - double pixel = get_matrix_vertical_component(vals->pixel_matrix); - double pixelset = get_matrix_horizontal_component(vals->pixel_matrix); - - if (pixel < EPS || pixelset < EPS) return 0; - - /* Initialize the transformation matrix to the scaling factors */ - xform[0] = dx / pixelset; - xform[1] = xform[2] = 0.0; - xform[3] = dy / pixel; - -/* Inline matrix multiply -- somewhat ugly to minimize register usage */ -#define MULTIPLY_XFORM(a,b,c,d) \ -{ \ - register double aa = (a), bb = (b), cc = (c), dd = (d); \ - register double temp; \ - temp = aa * xform[0] + cc * xform[1]; \ - aa = aa * xform[2] + cc * xform[3]; \ - xform[1] = bb * xform[0] + dd * xform[1]; \ - xform[3] = bb * xform[2] + dd * xform[3]; \ - xform[0] = temp; \ - xform[2] = aa; \ -} - - /* Rescale the transformation matrix for size of source font */ - MULTIPLY_XFORM(vals->pixel_matrix[0], - vals->pixel_matrix[1], - vals->pixel_matrix[2], - vals->pixel_matrix[3]); - - *xmult = xform[0]; - *ymult = xform[3]; - - - if (inv_xform == NULL) return 1; - - /* Compute the determinant for use in inverting the matrix. */ - det = xform[0] * xform[3] - xform[1] * xform[2]; - - /* If the determinant is tiny or zero, give up */ - if (fabs(det) < EPS) return 0; - - /* Compute the inverse */ - inv_xform[0] = xform[3] / det; - inv_xform[1] = -xform[1] / det; - inv_xform[2] = -xform[2] / det; - inv_xform[3] = xform[0] / det; - - return 1; -} - -/* - * ScaleFont - * returns a pointer to the new scaled font, or NULL (due to AllocError). - */ -static FontPtr -ScaleFont(FontPtr opf, /* originating font */ - double widthMult, /* glyphs width scale factor */ - double heightMult, /* glyphs height scale factor */ - double sWidthMult, /* scalable glyphs width scale factor */ - double sHeightMult, /* scalable glyphs height scale factor */ - FontScalablePtr vals, - double *newWidthMult, /* return: X component of glyphs width - scale factor */ - double *newHeightMult, /* return: Y component of glyphs height - scale factor */ - long *sWidth) /* return: average 1000-pixel width */ -{ - FontPtr pf; - FontInfoPtr pfi, - opfi; - BitmapFontPtr bitmapFont, - obitmapFont; - CharInfoPtr pci, - opci; - int nchars = 0; /* how many characters in the font */ - int i; - int firstCol, lastCol, firstRow, lastRow; - double xform[4], inv_xform[4]; - double xmult, ymult; - int totalwidth = 0, totalchars = 0; -#define OLDINDEX(i) (((i)/(lastCol - firstCol + 1) + \ - firstRow - opf->info.firstRow) * \ - (opf->info.lastCol - opf->info.firstCol + 1) + \ - (i)%(lastCol - firstCol + 1) + \ - firstCol - opf->info.firstCol) - - *sWidth = 0; - - opfi = &opf->info; - obitmapFont = (BitmapFontPtr) opf->fontPrivate; - - bitmapFont = 0; - if (!(pf = CreateFontRec())) { - fprintf(stderr, "Error: Couldn't allocate FontRec (%ld)\n", - (unsigned long)sizeof(FontRec)); - goto bail; - } - pf->refcnt = 0; - pf->bit = opf->bit; - pf->byte = opf->byte; - pf->glyph = opf->glyph; - pf->scan = opf->scan; - - pf->get_glyphs = bitmapGetGlyphs; - pf->get_metrics = bitmapGetMetrics; - pf->unload_font = bitmapUnloadScalable; - pf->unload_glyphs = NULL; - - pfi = &pf->info; - *pfi = *opfi; - /* If charset subsetting specified in vals, determine what our range - needs to be for the output font */ - if (vals->nranges) - { - int i; - - pfi->allExist = 0; - firstCol = 255; - lastCol = 0; - firstRow = 255; - lastRow = 0; - - for (i = 0; i < vals->nranges; i++) - { - if (vals->ranges[i].min_char_high != vals->ranges[i].max_char_high) - { - firstCol = opfi->firstCol; - lastCol = opfi->lastCol; - } - if (firstCol > vals->ranges[i].min_char_low) - firstCol = vals->ranges[i].min_char_low; - if (lastCol < vals->ranges[i].max_char_low) - lastCol = vals->ranges[i].max_char_low; - if (firstRow > vals->ranges[i].min_char_high) - firstRow = vals->ranges[i].min_char_high; - if (lastRow < vals->ranges[i].max_char_high) - lastRow = vals->ranges[i].max_char_high; - } - - if (firstCol > lastCol || firstRow > lastRow) - goto bail; - - if (firstCol < opfi->firstCol) - firstCol = opfi->firstCol; - if (lastCol > opfi->lastCol) - lastCol = opfi->lastCol; - if (firstRow < opfi->firstRow) - firstRow = opfi->firstRow; - if (lastRow > opfi->lastRow) - lastRow = opfi->lastRow; - } - else - { - firstCol = opfi->firstCol; - lastCol = opfi->lastCol; - firstRow = opfi->firstRow; - lastRow = opfi->lastRow; - } - - bitmapFont = malloc(sizeof(BitmapFontRec)); - if (!bitmapFont) { - fprintf(stderr, "Error: Couldn't allocate bitmapFont (%ld)\n", - (unsigned long)sizeof(BitmapFontRec)); - goto bail; - } - nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1); - pfi->firstRow = firstRow; - pfi->lastRow = lastRow; - pfi->firstCol = firstCol; - pfi->lastCol = lastCol; - pf->fontPrivate = (pointer) bitmapFont; - bitmapFont->version_num = obitmapFont->version_num; - bitmapFont->num_chars = nchars; - bitmapFont->num_tables = obitmapFont->num_tables; - bitmapFont->metrics = 0; - bitmapFont->ink_metrics = 0; - bitmapFont->bitmaps = 0; - bitmapFont->encoding = 0; - bitmapFont->bitmapExtra = 0; - bitmapFont->pDefault = 0; - bitmapFont->metrics = malloc(nchars * sizeof(CharInfoRec)); - if (!bitmapFont->metrics) { - fprintf(stderr, "Error: Couldn't allocate metrics (%d*%ld)\n", - nchars, (unsigned long)sizeof(CharInfoRec)); - goto bail; - } - bitmapFont->encoding = calloc(NUM_SEGMENTS(nchars), sizeof(CharInfoPtr*)); - if (!bitmapFont->encoding) { - fprintf(stderr, "Error: Couldn't allocate encoding (%d*%ld)\n", - nchars, (unsigned long)sizeof(CharInfoPtr)); - goto bail; - } - -#undef MAXSHORT -#define MAXSHORT 32767 -#undef MINSHORT -#define MINSHORT -32768 - - pfi->anamorphic = FALSE; - if (heightMult != widthMult) - pfi->anamorphic = TRUE; - pfi->cachable = TRUE; - - if (!compute_xform_matrix(vals, widthMult, heightMult, xform, - inv_xform, &xmult, &ymult)) - goto bail; - - pfi->fontAscent = opfi->fontAscent * ymult; - pfi->fontDescent = opfi->fontDescent * ymult; - - pfi->minbounds.leftSideBearing = MAXSHORT; - pfi->minbounds.rightSideBearing = MAXSHORT; - pfi->minbounds.ascent = MAXSHORT; - pfi->minbounds.descent = MAXSHORT; - pfi->minbounds.characterWidth = MAXSHORT; - pfi->minbounds.attributes = MAXSHORT; - - pfi->maxbounds.leftSideBearing = MINSHORT; - pfi->maxbounds.rightSideBearing = MINSHORT; - pfi->maxbounds.ascent = MINSHORT; - pfi->maxbounds.descent = MINSHORT; - pfi->maxbounds.characterWidth = MINSHORT; - pfi->maxbounds.attributes = MINSHORT; - - /* Compute the transformation and inverse transformation matrices. - Can fail if the determinant is zero. */ - - pci = bitmapFont->metrics; - for (i = 0; i < nchars; i++) - { - if ((opci = ACCESSENCODING(obitmapFont->encoding,OLDINDEX(i)))) - { - double newlsb, newrsb, newdesc, newasc, point[2]; - -#define minchar(p) ((p).min_char_low + ((p).min_char_high << 8)) -#define maxchar(p) ((p).max_char_low + ((p).max_char_high << 8)) - - if (vals->nranges) - { - int row = i / (lastCol - firstCol + 1) + firstRow; - int col = i % (lastCol - firstCol + 1) + firstCol; - int ch = (row << 8) + col; - int j; - for (j = 0; j < vals->nranges; j++) - if (ch >= minchar(vals->ranges[j]) && - ch <= maxchar(vals->ranges[j])) - break; - if (j == vals->nranges) - { - continue; - } - } - - if (opci->metrics.leftSideBearing == 0 && - opci->metrics.rightSideBearing == 0 && - opci->metrics.ascent == 0 && - opci->metrics.descent == 0 && - opci->metrics.characterWidth == 0) - { - continue; - } - - if(!bitmapFont->encoding[SEGMENT_MAJOR(i)]) { - bitmapFont->encoding[SEGMENT_MAJOR(i)]= - calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr)); - if(!bitmapFont->encoding[SEGMENT_MAJOR(i)]) - goto bail; - } - ACCESSENCODINGL(bitmapFont->encoding, i) = pci; - - /* Compute new extents for this glyph */ - TRANSFORM_POINT(xform, - opci->metrics.leftSideBearing, - -opci->metrics.descent, - point); - newlsb = point[0]; - newrsb = newlsb; - newdesc = -point[1]; - newasc = -newdesc; - TRANSFORM_POINT(xform, - opci->metrics.leftSideBearing, - opci->metrics.ascent, - point); - CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); - TRANSFORM_POINT(xform, - opci->metrics.rightSideBearing, - -opci->metrics.descent, - point); - CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); - TRANSFORM_POINT(xform, - opci->metrics.rightSideBearing, - opci->metrics.ascent, - point); - CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); - - pci->metrics.leftSideBearing = (int)floor(newlsb); - pci->metrics.rightSideBearing = (int)floor(newrsb + .5); - pci->metrics.descent = (int)ceil(newdesc); - pci->metrics.ascent = (int)floor(newasc + .5); - /* Accumulate total width of characters before transformation, - to ascertain predominant direction of font. */ - totalwidth += opci->metrics.characterWidth; - pci->metrics.characterWidth = - doround((double)opci->metrics.characterWidth * xmult); - pci->metrics.attributes = - doround((double)opci->metrics.characterWidth * sWidthMult); - if (!pci->metrics.characterWidth) - { - /* Since transformation may shrink width, height, and - escapement to zero, make sure existing characters - are not mistaken for undefined characters. */ - - if (pci->metrics.rightSideBearing == - pci->metrics.leftSideBearing) - pci->metrics.rightSideBearing++; - if (pci->metrics.ascent == -pci->metrics.descent) - pci->metrics.ascent++; - } - - pci++; - } - } - - - /* - * For each character, set the per-character metrics, scale the glyph, and - * check per-font minbounds and maxbounds character information. - */ - - pci = bitmapFont->metrics; - for (i = 0; i < nchars; i++) - { - if ((pci = ACCESSENCODING(bitmapFont->encoding,i)) && - (opci = ACCESSENCODING(obitmapFont->encoding,OLDINDEX(i)))) - { - totalchars++; - *sWidth += abs((int)(INT16)pci->metrics.attributes); -#define MINMAX(field) \ - if (pfi->minbounds.field > pci->metrics.field) \ - pfi->minbounds.field = pci->metrics.field; \ - if (pfi->maxbounds.field < pci->metrics.field) \ - pfi->maxbounds.field = pci->metrics.field - - MINMAX(leftSideBearing); - MINMAX(rightSideBearing); - MINMAX(ascent); - MINMAX(descent); - MINMAX(characterWidth); - - /* Hack: Cast attributes into a signed quantity. Tread lightly - for now and don't go changing the global Xproto.h file */ - if ((INT16)pfi->minbounds.attributes > - (INT16)pci->metrics.attributes) - pfi->minbounds.attributes = pci->metrics.attributes; - if ((INT16)pfi->maxbounds.attributes < - (INT16)pci->metrics.attributes) - pfi->maxbounds.attributes = pci->metrics.attributes; -#undef MINMAX - } - } - pfi->ink_minbounds = pfi->minbounds; - pfi->ink_maxbounds = pfi->maxbounds; - if (totalchars) - { - *sWidth = (*sWidth * 10 + totalchars / 2) / totalchars; - if (totalwidth < 0) - { - /* Dominant direction is R->L */ - *sWidth = -*sWidth; - } - - if (pfi->minbounds.characterWidth == pfi->maxbounds.characterWidth) - vals->width = pfi->minbounds.characterWidth * 10; - else - vals->width = doround((double)*sWidth * vals->pixel_matrix[0] / - 1000.0); - } - else - { - vals->width = 0; - *sWidth = 0; - } - FontComputeInfoAccelerators (pfi); - - if (pfi->defaultCh != (unsigned short) NO_SUCH_CHAR) { - unsigned int r, - c, - cols; - - r = pfi->defaultCh >> 8; - c = pfi->defaultCh & 0xFF; - if (pfi->firstRow <= r && r <= pfi->lastRow && - pfi->firstCol <= c && c <= pfi->lastCol) { - cols = pfi->lastCol - pfi->firstCol + 1; - r = r - pfi->firstRow; - c = c - pfi->firstCol; - bitmapFont->pDefault = - ACCESSENCODING(bitmapFont->encoding, r * cols + c); - } - } - - *newWidthMult = xmult; - *newHeightMult = ymult; - return pf; -bail: - if (pf) - free(pf); - if (bitmapFont) { - free(bitmapFont->metrics); - free(bitmapFont->ink_metrics); - free(bitmapFont->bitmaps); - if(bitmapFont->encoding) - for(i=0; i<NUM_SEGMENTS(nchars); i++) - free(bitmapFont->encoding[i]); - free(bitmapFont->encoding); - } - return NULL; -} - -static void -ScaleBitmap(FontPtr pFont, CharInfoPtr opci, CharInfoPtr pci, - double *inv_xform, double widthMult, double heightMult) -{ - register char *bitmap, /* The bits */ - *newBitmap; - register int bpr, /* Padding information */ - newBpr; - int width, /* Extents information */ - height, - newWidth, - newHeight; - register int row, /* Loop variables */ - col; - INT32 deltaX, /* Increments for resampling loop */ - deltaY; - INT32 xValue, /* Subscripts for resampling loop */ - yValue; - double point[2]; - unsigned char *char_grayscale = 0; - INT32 *diffusion_workspace = NULL, *thisrow = NULL, - *nextrow = NULL, pixmult = 0; - int box_x = 0, box_y = 0; - - static unsigned char masklsb[] = - { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 }; - static unsigned char maskmsb[] = - { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 }; - unsigned char *mask = (pFont->bit == LSBFirst ? masklsb : maskmsb); - - - bitmap = opci->bits; - newBitmap = pci->bits; - width = GLYPHWIDTHPIXELS(opci); - height = GLYPHHEIGHTPIXELS(opci); - newWidth = GLYPHWIDTHPIXELS(pci); - newHeight = GLYPHHEIGHTPIXELS(pci); - if (!newWidth || !newHeight || !width || !height) - return; - - bpr = BYTES_PER_ROW(width, pFont->glyph); - newBpr = BYTES_PER_ROW(newWidth, pFont->glyph); - - if (widthMult > 0.0 && heightMult > 0.0 && - (widthMult < 1.0 || heightMult < 1.0)) - { - /* We are reducing in one or both dimensions. In an attempt to - reduce aliasing, we'll antialias by passing the original - glyph through a low-pass box filter (which results in a - grayscale image), then use error diffusion to create bitonal - output in the resampling loop. */ - - /* First compute the sizes of the box filter */ - widthMult = ceil(1.0 / widthMult); - heightMult = ceil(1.0 / heightMult); - box_x = width / 2; - box_y = height / 2; - if (widthMult < (double)box_x) box_x = (int)widthMult; - if (heightMult < (double)box_y) box_y = (int)heightMult; - /* The pixmult value (below) is used to darken the image before - we perform error diffusion: a necessary concession to the - fact that it's very difficult to generate readable halftoned - glyphs. The degree of darkening is proportional to the size - of the blurring filter, hence inversely proportional to the - darkness of the lightest gray that results from antialiasing. - The result is that characters that exercise this logic (those - generated by reducing from a larger source font) tend to err - on the side of being too bold instead of being too light to - be readable. */ - pixmult = box_x * box_y * 192; - - if (box_x > 1 || box_y > 1) - { - /* Looks like we need to anti-alias. Create a workspace to - contain the grayscale character plus an additional row and - column for scratch */ - char_grayscale = malloc((width + 1) * (height + 1)); - if (char_grayscale) - { - diffusion_workspace = calloc((newWidth + 2) * 2, sizeof(int)); - if (!diffusion_workspace) - { - fprintf(stderr, "Warning: Couldn't allocate diffusion" - " workspace (%ld)\n", - (newWidth + 2) * 2 * (unsigned long)sizeof(int)); - free(char_grayscale); - char_grayscale = (unsigned char *)0; - } - /* Initialize our error diffusion workspace for later use */ - thisrow = diffusion_workspace + 1; - nextrow = diffusion_workspace + newWidth + 3; - } else { - fprintf(stderr, "Warning: Couldn't allocate character grayscale (%d)\n", (width + 1) * (height + 1)); - } - } - } - - if (char_grayscale) - { - /* We will be doing antialiasing. First copy the bitmap into - our buffer, mapping input range [0,1] to output range - [0,255]. */ - register unsigned char *srcptr, *dstptr; - srcptr = (unsigned char *)bitmap; - dstptr = char_grayscale; - for (row = 0; row < height; row++) - { - for (col = 0; col < width; col++) - *dstptr++ = (srcptr[col >> 3] & mask[col & 0x7]) ? 255 : 0; - srcptr += bpr; /* On to next row of source */ - dstptr++; /* Skip scratch column in dest */ - } - if (box_x > 1) - { - /* Our box filter has a width > 1... let's filter the rows */ - - int right_width = box_x / 2; - int left_width = box_x - right_width - 1; - - for (row = 0; row < height; row++) - { - int sum = 0; - int left_size = 0, right_size = 0; - - srcptr = char_grayscale + (width + 1) * row; - dstptr = char_grayscale + (width + 1) * height; /* scratch */ - - /* We've computed the shape of our full box filter. Now - compute the right-hand part of the moving sum */ - for (right_size = 0; right_size < right_width; right_size++) - sum += srcptr[right_size]; - - /* Now start moving the sum, growing the box filter, and - dropping averages into our scratch buffer */ - for (left_size = 0; left_size < left_width; left_size++) - { - sum += srcptr[right_width]; - *dstptr++ = sum / (left_size + right_width + 1); - srcptr++; - } - - /* The box filter has reached full width... continue - computation of moving average until the right side - hits the wall. */ - for (col = left_size; col + right_size < width; col++) - { - sum += srcptr[right_width]; - *dstptr++ = sum / box_x; - sum -= srcptr[-left_width]; - srcptr++; - } - - /* Collapse the right side of the box filter */ - for (; right_size > 0; right_size--) - { - *dstptr++ = sum / (left_width + right_size); - sum -= srcptr[-left_width]; - srcptr++; - } - - /* Done with the row... copy dest back over source */ - memmove(char_grayscale + (width + 1) * row, - char_grayscale + (width + 1) * height, - width); - } - } - if (box_y > 1) - { - /* Our box filter has a height > 1... let's filter the columns */ - - int bottom_height = box_y / 2; - int top_height = box_y - bottom_height - 1; - - for (col = 0; col < width; col++) - { - int sum = 0; - int top_size = 0, bottom_size = 0; - - srcptr = char_grayscale + col; - dstptr = char_grayscale + width; /* scratch */ - - /* We've computed the shape of our full box filter. Now - compute the bottom part of the moving sum */ - for (bottom_size = 0; - bottom_size < bottom_height; - bottom_size++) - sum += srcptr[bottom_size * (width + 1)]; - - /* Now start moving the sum, growing the box filter, and - dropping averages into our scratch buffer */ - for (top_size = 0; top_size < top_height; top_size++) - { - sum += srcptr[bottom_height * (width + 1)]; - *dstptr = sum / (top_size + bottom_height + 1); - dstptr += width + 1; - srcptr += width + 1; - } - - /* The box filter has reached full height... continue - computation of moving average until the bottom - hits the wall. */ - for (row = top_size; row + bottom_size < height; row++) - { - sum += srcptr[bottom_height * (width + 1)]; - *dstptr = sum / box_y; - dstptr += width + 1; - sum -= srcptr[-top_height * (width + 1)]; - srcptr += width + 1; - } - - /* Collapse the bottom of the box filter */ - for (; bottom_size > 0; bottom_size--) - { - *dstptr = sum / (top_height + bottom_size); - dstptr += width + 1; - sum -= srcptr[-top_height * (width + 1)]; - srcptr += width + 1; - } - - /* Done with the column... copy dest back over source */ - - dstptr = char_grayscale + col; - srcptr = char_grayscale + width; /* scratch */ - for (row = 0; row < height; row++) - { - *dstptr = *srcptr; - dstptr += width + 1; - srcptr += width + 1; - } - } - } - - /* Increase the grayvalue to increase ink a bit */ - srcptr = char_grayscale; - for (row = 0; row < height; row++) - { - for (col = 0; col < width; col++) - { - register int pixvalue = (int)*srcptr * pixmult / 256; - if (pixvalue > 255) pixvalue = 255; - *srcptr = pixvalue; - srcptr++; - } - srcptr++; - } - } - - /* Compute the increment values for the resampling loop */ - TRANSFORM_POINT(inv_xform, 1, 0, point); - deltaX = (INT32)(point[0] * 65536.0); - deltaY = (INT32)(-point[1] * 65536.0); - - /* Resampling loop: resamples original glyph for generation of new - glyph in transformed coordinate system. */ - - for (row = 0; row < newHeight; row++) - { - /* Compute inverse transformation for start of this row */ - TRANSFORM_POINT(inv_xform, - (double)(pci->metrics.leftSideBearing) + .5, - (double)(pci->metrics.ascent - row) - .5, - point); - - /* Adjust for coordinate system to get resampling point */ - point[0] -= opci->metrics.leftSideBearing; - point[1] = opci->metrics.ascent - point[1]; - - /* Convert to integer coordinates */ - xValue = (INT32)(point[0] * 65536.0); - yValue = (INT32)(point[1] * 65536.0); - - if (char_grayscale) - { - INT32 *temp; - for (col = 0; col < newWidth; col++) - { - register int x = xValue >> 16, y = yValue >> 16; - int pixvalue, error; - - pixvalue = ((x >= 0 && x < width && y >= 0 && y < height) ? - char_grayscale[x + y * (width + 1)] : 0) + - thisrow[col] / 16; - if (pixvalue > 255) pixvalue = 255; - else if (pixvalue < 0) pixvalue = 0; - - /* Choose the bit value and set resulting error value */ - if (pixvalue >= 128) - { - newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7]; - error = pixvalue - 255; - } - else - error = -pixvalue; - - /* Diffuse the error */ - thisrow[col + 1] += error * 7; - nextrow[col - 1] += error * 3; - nextrow[col] += error * 5; - nextrow[col + 1] = error; - - xValue += deltaX; - yValue += deltaY; - } - - /* Add in error values that fell off either end */ - nextrow[0] += nextrow[-1]; - nextrow[newWidth - 2] += thisrow[newWidth]; - nextrow[newWidth - 1] += nextrow[newWidth]; - nextrow[newWidth] = 0; - - temp = nextrow; - nextrow = thisrow; - thisrow = temp; - nextrow[-1] = nextrow[0] = 0; - } - else - { - for (col = 0; col < newWidth; col++) - { - register int x = xValue >> 16, y = yValue >> 16; - - if (x >= 0 && x < width && y >= 0 && y < height) - { - /* Use point-sampling for rescaling. */ - - if (bitmap[(x >> 3) + y * bpr] & mask[x & 0x7]) - newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7]; - } - - xValue += deltaX; - yValue += deltaY; - } - } - } - - - if (char_grayscale) - { - free(char_grayscale); - free(diffusion_workspace); - } -} - -static FontPtr -BitmapScaleBitmaps(FontPtr pf, /* scaled font */ - FontPtr opf, /* originating font */ - double widthMult, /* glyphs width scale factor */ - double heightMult, /* glyphs height scale factor */ - FontScalablePtr vals) -{ - register int i; - int nchars = 0; - char *glyphBytes; - BitmapFontPtr bitmapFont, - obitmapFont; - CharInfoPtr pci, - opci; - FontInfoPtr pfi; - int glyph; - unsigned bytestoalloc = 0; - int firstCol, lastCol, firstRow, lastRow; - - double xform[4], inv_xform[4]; - double xmult, ymult; - - bitmapFont = (BitmapFontPtr) pf->fontPrivate; - obitmapFont = (BitmapFontPtr) opf->fontPrivate; - - if (!compute_xform_matrix(vals, widthMult, heightMult, xform, - inv_xform, &xmult, &ymult)) - goto bail; - - pfi = &pf->info; - firstCol = pfi->firstCol; - lastCol = pfi->lastCol; - firstRow = pfi->firstRow; - lastRow = pfi->lastRow; - - nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1); - glyph = pf->glyph; - for (i = 0; i < nchars; i++) - { - if ((pci = ACCESSENCODING(bitmapFont->encoding, i))) - bytestoalloc += BYTES_FOR_GLYPH(pci, glyph); - } - - /* Do we add the font malloc stuff for VALUE ADDED ? */ - /* Will need to remember to free in the Unload routine */ - - - bitmapFont->bitmaps = calloc(1, bytestoalloc); - if (!bitmapFont->bitmaps) { - fprintf(stderr, "Error: Couldn't allocate bitmaps (%d)\n", bytestoalloc); - goto bail; - } - - glyphBytes = bitmapFont->bitmaps; - for (i = 0; i < nchars; i++) - { - if ((pci = ACCESSENCODING(bitmapFont->encoding, i)) && - (opci = ACCESSENCODING(obitmapFont->encoding, OLDINDEX(i)))) - { - pci->bits = glyphBytes; - ScaleBitmap (pf, opci, pci, inv_xform, - widthMult, heightMult); - glyphBytes += BYTES_FOR_GLYPH(pci, glyph); - } - } - return pf; - -bail: - if (pf) - free(pf); - if (bitmapFont) { - free(bitmapFont->metrics); - free(bitmapFont->ink_metrics); - free(bitmapFont->bitmaps); - if(bitmapFont->encoding) - for(i=0; i<NUM_SEGMENTS(nchars); i++) - free(bitmapFont->encoding[i]); - free(bitmapFont->encoding); - } - return NULL; -} - -/* ARGSUSED */ -int -BitmapOpenScalable (FontPathElementPtr fpe, - FontPtr *pFont, - int flags, - FontEntryPtr entry, - char *fileName, /* unused */ - FontScalablePtr vals, - fsBitmapFormat format, - fsBitmapFormatMask fmask, - FontPtr non_cachable_font) /* We don't do licensing */ -{ - FontScalableRec best; - FontPtr font = NullFont; - double dx, sdx, - dy, sdy, - savedX, savedY; - FontPropPtr props; - char *isStringProp = NULL; - int propCount; - int status; - long sWidth; - - FontEntryPtr scaleFrom; - FontPathElementPtr scaleFPE = NULL; - FontPtr sourceFont; - char fontName[MAXFONTNAMELEN]; - - /* Can't deal with mix-endian fonts yet */ - - - /* Reject outrageously small font sizes to keep the math from - blowing up. */ - if (get_matrix_vertical_component(vals->pixel_matrix) < 1.0 || - get_matrix_horizontal_component(vals->pixel_matrix) < 1.0) - return BadFontName; - - scaleFrom = FindBestToScale(fpe, entry, vals, &best, &dx, &dy, &sdx, &sdy, - &scaleFPE); - - if (!scaleFrom) - return BadFontName; - - status = FontFileOpenBitmap(scaleFPE, &sourceFont, LoadAll, scaleFrom, - format, fmask); - - if (status != Successful) - return BadFontName; - - if (!vals->width) - vals->width = best.width * dx; - - /* Compute the scaled font */ - - savedX = dx; - savedY = dy; - font = ScaleFont(sourceFont, dx, dy, sdx, sdy, vals, &dx, &dy, &sWidth); - if (font) - font = BitmapScaleBitmaps(font, sourceFont, savedX, savedY, vals); - - if (!font) - { - if (!sourceFont->refcnt) - FontFileCloseFont((FontPathElementPtr) 0, sourceFont); - return AllocError; - } - - /* Prepare font properties for the new font */ - - strcpy (fontName, scaleFrom->name.name); - FontParseXLFDName (fontName, vals, FONT_XLFD_REPLACE_VALUE); - - propCount = ComputeScaledProperties(&sourceFont->info, fontName, vals, - dx, dy, sdx, sdy, sWidth, &props, - &isStringProp); - - if (!sourceFont->refcnt) - FontFileCloseFont((FontPathElementPtr) 0, sourceFont); - - if (propCount && (!props || !isStringProp)) - { - font->info.nprops = 0; - font->info.props = (FontPropPtr)0; - font->info.isStringProp = (char *)0; - bitmapUnloadScalable(font); - return AllocError; - } - - font->info.props = props; - font->info.nprops = propCount; - font->info.isStringProp = isStringProp; - - *pFont = font; - return Successful; -} - -int -BitmapGetInfoScalable (FontPathElementPtr fpe, - FontInfoPtr pFontInfo, - FontEntryPtr entry, - FontNamePtr fontName, - char *fileName, - FontScalablePtr vals) -{ - FontPtr pfont; - int flags = 0; - long format = 0; /* It doesn't matter what format for just info */ - long fmask = 0; - int ret; - - ret = BitmapOpenScalable(fpe, &pfont, flags, entry, fileName, vals, - format, fmask, NULL); - if (ret != Successful) - return ret; - *pFontInfo = pfont->info; - - pfont->info.nprops = 0; - pfont->info.props = NULL; - pfont->info.isStringProp = NULL; - - (*pfont->unload_font)(pfont); - return Successful; -} - -static void -bitmapUnloadScalable (FontPtr pFont) -{ - BitmapFontPtr bitmapFont; - FontInfoPtr pfi; - int i, nencoding; - - bitmapFont = (BitmapFontPtr) pFont->fontPrivate; - pfi = &pFont->info; - free (pfi->props); - free (pfi->isStringProp); - if(bitmapFont->encoding) { - nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * - (pFont->info.lastRow - pFont->info.firstRow + 1); - for(i=0; i<NUM_SEGMENTS(nencoding); i++) - free(bitmapFont->encoding[i]); - } - free (bitmapFont->encoding); - free (bitmapFont->bitmaps); - free (bitmapFont->ink_metrics); - free (bitmapFont->metrics); - free (pFont->fontPrivate); - DestroyFontRec (pFont); -} +/*
+
+Copyright 1991, 1994, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/*
+ * Translate monolithic #defines to modular definitions
+ */
+
+#ifdef PCFFORMAT
+#define XFONT_PCFFORMAT 1
+#endif
+
+#ifdef SNFFORMAT
+#define XFONT_SNFFORMAT 1
+#endif
+
+#ifdef BDFFORMAT
+#define XFONT_BDFFORMAT 1
+#endif
+
+#include <X11/fonts/fntfilst.h>
+#include <X11/fonts/bitmap.h>
+#include <X11/fonts/fontutil.h>
+#include <math.h>
+
+#ifndef MAX
+#define MAX(a,b) (((a)>(b)) ? a : b)
+#endif
+
+#ifdef _MSC_VER
+#define hypot _hypot
+#endif
+
+/* Should get this from elsewhere */
+extern unsigned long serverGeneration;
+
+static void bitmapUnloadScalable (FontPtr pFont);
+static void ScaleBitmap ( FontPtr pFont, CharInfoPtr opci,
+ CharInfoPtr pci, double *inv_xform,
+ double widthMult, double heightMult );
+static FontPtr BitmapScaleBitmaps(FontPtr pf, FontPtr opf,
+ double widthMult, double heightMult,
+ FontScalablePtr vals);
+
+enum scaleType {
+ atom, truncate_atom, pixel_size, point_size, resolution_x,
+ resolution_y, average_width, scaledX, scaledY, unscaled, fontname,
+ raw_ascent, raw_descent, raw_pixelsize, raw_pointsize,
+ raw_average_width, uncomputed
+};
+
+typedef struct _fontProp {
+ char *name;
+ Atom atom;
+ enum scaleType type;
+} fontProp;
+
+static FontEntryPtr FindBestToScale ( FontPathElementPtr fpe,
+ FontEntryPtr entry,
+ FontScalablePtr vals,
+ FontScalablePtr best,
+ double *dxp, double *dyp,
+ double *sdxp, double *sdyp,
+ FontPathElementPtr *fpep );
+
+static unsigned long bitscaleGeneration = 0; /* initialization flag */
+
+static fontProp fontNamePropTable[] = {
+ { "FOUNDRY", 0, atom },
+ { "FAMILY_NAME", 0, atom },
+ { "WEIGHT_NAME", 0, atom },
+ { "SLANT", 0, atom },
+ { "SETWIDTH_NAME", 0, atom },
+ { "ADD_STYLE_NAME", 0, atom },
+ { "PIXEL_SIZE", 0, pixel_size },
+ { "POINT_SIZE", 0, point_size },
+ { "RESOLUTION_X", 0, resolution_x },
+ { "RESOLUTION_Y", 0, resolution_y },
+ { "SPACING", 0, atom },
+ { "AVERAGE_WIDTH", 0, average_width },
+ { "CHARSET_REGISTRY", 0, atom },
+ { "CHARSET_ENCODING", 0, truncate_atom },
+ { "FONT", 0, fontname },
+ { "RAW_ASCENT", 0, raw_ascent },
+ { "RAW_DESCENT", 0, raw_descent },
+ { "RAW_PIXEL_SIZE", 0, raw_pixelsize },
+ { "RAW_POINT_SIZE", 0, raw_pointsize },
+ { "RAW_AVERAGE_WIDTH", 0, raw_average_width }
+};
+
+#define TRANSFORM_POINT(matrix, x, y, dest) \
+ ((dest)[0] = (matrix)[0] * (x) + (matrix)[2] * (y), \
+ (dest)[1] = (matrix)[1] * (x) + (matrix)[3] * (y))
+
+#define CHECK_EXTENT(lsb, rsb, desc, asc, data) \
+ ((lsb) > (data)[0] ? (lsb) = (data)[0] : 0 , \
+ (rsb) < (data)[0] ? (rsb) = (data)[0] : 0, \
+ (-desc) > (data)[1] ? (desc) = -(data)[1] : 0 , \
+ (asc) < (data)[1] ? (asc) = (data)[1] : 0)
+
+#define NPROPS (sizeof(fontNamePropTable) / sizeof(fontProp))
+
+/* Warning: order of the next two tables is critically interdependent.
+ Location of "unscaled" properties at the end of fontPropTable[]
+ is important. */
+
+static fontProp fontPropTable[] = {
+ { "MIN_SPACE", 0, scaledX },
+ { "NORM_SPACE", 0, scaledX },
+ { "MAX_SPACE", 0, scaledX },
+ { "END_SPACE", 0, scaledX },
+ { "AVG_CAPITAL_WIDTH", 0, scaledX },
+ { "AVG_LOWERCASE_WIDTH", 0, scaledX },
+ { "QUAD_WIDTH", 0, scaledX },
+ { "FIGURE_WIDTH", 0, scaledX },
+ { "SUPERSCRIPT_X", 0, scaledX },
+ { "SUPERSCRIPT_Y", 0, scaledY },
+ { "SUBSCRIPT_X", 0, scaledX },
+ { "SUBSCRIPT_Y", 0, scaledY },
+ { "SUPERSCRIPT_SIZE", 0, scaledY },
+ { "SUBSCRIPT_SIZE", 0, scaledY },
+ { "SMALL_CAP_SIZE", 0, scaledY },
+ { "UNDERLINE_POSITION", 0, scaledY },
+ { "UNDERLINE_THICKNESS", 0, scaledY },
+ { "STRIKEOUT_ASCENT", 0, scaledY },
+ { "STRIKEOUT_DESCENT", 0, scaledY },
+ { "CAP_HEIGHT", 0, scaledY },
+ { "X_HEIGHT", 0, scaledY },
+ { "ITALIC_ANGLE", 0, unscaled },
+ { "RELATIVE_SETWIDTH", 0, unscaled },
+ { "RELATIVE_WEIGHT", 0, unscaled },
+ { "WEIGHT", 0, unscaled },
+ { "DESTINATION", 0, unscaled },
+ { "PCL_FONT_NAME", 0, unscaled },
+ { "_ADOBE_POSTSCRIPT_FONTNAME", 0, unscaled }
+};
+
+static fontProp rawFontPropTable[] = {
+ { "RAW_MIN_SPACE", 0, },
+ { "RAW_NORM_SPACE", 0, },
+ { "RAW_MAX_SPACE", 0, },
+ { "RAW_END_SPACE", 0, },
+ { "RAW_AVG_CAPITAL_WIDTH", 0, },
+ { "RAW_AVG_LOWERCASE_WIDTH", 0, },
+ { "RAW_QUAD_WIDTH", 0, },
+ { "RAW_FIGURE_WIDTH", 0, },
+ { "RAW_SUPERSCRIPT_X", 0, },
+ { "RAW_SUPERSCRIPT_Y", 0, },
+ { "RAW_SUBSCRIPT_X", 0, },
+ { "RAW_SUBSCRIPT_Y", 0, },
+ { "RAW_SUPERSCRIPT_SIZE", 0, },
+ { "RAW_SUBSCRIPT_SIZE", 0, },
+ { "RAW_SMALL_CAP_SIZE", 0, },
+ { "RAW_UNDERLINE_POSITION", 0, },
+ { "RAW_UNDERLINE_THICKNESS", 0, },
+ { "RAW_STRIKEOUT_ASCENT", 0, },
+ { "RAW_STRIKEOUT_DESCENT", 0, },
+ { "RAW_CAP_HEIGHT", 0, },
+ { "RAW_X_HEIGHT", 0, }
+};
+
+static void
+initFontPropTable(void)
+{
+ int i;
+ fontProp *t;
+
+ i = sizeof(fontNamePropTable) / sizeof(fontProp);
+ for (t = fontNamePropTable; i; i--, t++)
+ t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE);
+
+ i = sizeof(fontPropTable) / sizeof(fontProp);
+ for (t = fontPropTable; i; i--, t++)
+ t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE);
+
+ i = sizeof(rawFontPropTable) / sizeof(fontProp);
+ for (t = rawFontPropTable; i; i--, t++)
+ t->atom = MakeAtom(t->name, (unsigned) strlen(t->name), TRUE);
+}
+
+#if 0
+static FontEntryPtr
+GetScalableEntry (FontPathElementPtr fpe, FontNamePtr name)
+{
+ FontDirectoryPtr dir;
+
+ dir = (FontDirectoryPtr) fpe->private;
+ return FontFileFindNameInDir (&dir->scalable, name);
+}
+#endif
+
+static double
+get_matrix_horizontal_component(double *matrix)
+{
+ return hypot(matrix[0], matrix[1]);
+}
+
+static double
+get_matrix_vertical_component(double *matrix)
+{
+ return hypot(matrix[2], matrix[3]);
+}
+
+
+static Bool
+ComputeScaleFactors(FontScalablePtr from, FontScalablePtr to,
+ double *dx, double *dy, double *sdx, double *sdy,
+ double *rescale_x)
+{
+ double srcpixelset, destpixelset, srcpixel, destpixel;
+
+ srcpixelset = get_matrix_horizontal_component(from->pixel_matrix);
+ destpixelset = get_matrix_horizontal_component(to->pixel_matrix);
+ srcpixel = get_matrix_vertical_component(from->pixel_matrix);
+ destpixel = get_matrix_vertical_component(to->pixel_matrix);
+
+ if (srcpixelset >= EPS)
+ {
+ *dx = destpixelset / srcpixelset;
+ *sdx = 1000.0 / srcpixelset;
+ }
+ else
+ *sdx = *dx = 0;
+
+ *rescale_x = 1.0;
+
+ /* If client specified a width, it overrides setsize; in this
+ context, we interpret width as applying to the font before any
+ rotation, even though that's not what is ultimately returned in
+ the width field. */
+ if (from->width > 0 && to->width > 0 && fabs(*dx) > EPS)
+ {
+ double rescale = (double)to->width / (double)from->width;
+
+ /* If the client specified a transformation matrix, the rescaling
+ for width does *not* override the setsize. Instead, just check
+ for consistency between the setsize from the matrix and the
+ setsize that would result from rescaling according to the width.
+ This assumes (perhaps naively) that the width is correctly
+ reported in the name. As an interesting side effect, this test
+ may result in choosing a different source bitmap (one that
+ scales consistently between the setsize *and* the width) than it
+ would choose if a width were not specified. Sort of a hidden
+ multiple-master functionality. */
+ if ((to->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY ||
+ (to->values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY)
+ {
+ /* Reject if resulting width difference is >= 1 pixel */
+ if (fabs(rescale * from->width - *dx * from->width) >= 10)
+ return FALSE;
+ }
+ else
+ {
+ *rescale_x = rescale/(*dx);
+ *dx = rescale;
+ }
+ }
+
+ if (srcpixel >= EPS)
+ {
+ *dy = destpixel / srcpixel;
+ *sdy = 1000.0 / srcpixel;
+ }
+ else
+ *sdy = *dy = 0;
+
+ return TRUE;
+}
+
+/* favor enlargement over reduction because of aliasing resulting
+ from reduction */
+#define SCORE(m,s) \
+if (m >= 1.0) { \
+ if (m == 1.0) \
+ score += (16 * s); \
+ else if (m == 2.0) \
+ score += (4 * s); \
+ else \
+ score += (int)(((double)(3 * s)) / m); \
+} else { \
+ score += (int)(((double)(2 * s)) * m); \
+}
+
+/* don't need to favor enlargement when looking for bitmap that can
+ be used unscalable */
+#define SCORE2(m,s) \
+if (m >= 1.0) \
+ score += (int)(((double)(8 * s)) / m); \
+else \
+ score += (int)(((double)(8 * s)) * m);
+
+static FontEntryPtr
+FindBestToScale(FontPathElementPtr fpe, FontEntryPtr entry,
+ FontScalablePtr vals, FontScalablePtr best,
+ double *dxp, double *dyp,
+ double *sdxp, double *sdyp,
+ FontPathElementPtr *fpep)
+{
+ FontScalableRec temp;
+ int source, i;
+ int best_score, best_unscaled_score,
+ score;
+ double dx = 0.0, sdx = 0.0, dx_amount = 0.0,
+ dy = 0.0, sdy = 0.0, dy_amount = 0.0,
+ best_dx = 0.0, best_sdx = 0.0, best_dx_amount = 0.0,
+ best_dy = 0.0, best_sdy = 0.0, best_dy_amount = 0.0,
+ best_unscaled_sdx = 0.0, best_unscaled_sdy = 0.0,
+ rescale_x = 0.0, best_rescale_x = 0.0,
+ best_unscaled_rescale_x = 0.0;
+ FontEntryPtr zero;
+ FontNameRec zeroName;
+ char zeroChars[MAXFONTNAMELEN];
+ FontDirectoryPtr dir;
+ FontScaledPtr scaled;
+ FontScalableExtraPtr extra;
+ FontScaledPtr best_scaled, best_unscaled;
+ FontPathElementPtr best_fpe = NULL, best_unscaled_fpe = NULL;
+ FontEntryPtr bitmap = NULL;
+ FontEntryPtr result;
+ int aliascount = 20;
+ FontPathElementPtr bitmap_fpe = NULL;
+ FontNameRec xlfdName;
+
+ /* find the best match */
+ rescale_x = 1.0;
+ best_scaled = 0;
+ best_score = 0;
+ best_unscaled = 0;
+ best_unscaled_score = -1;
+ best_dx_amount = best_dy_amount = HUGE_VAL;
+ memcpy (zeroChars, entry->name.name, entry->name.length);
+ zeroChars[entry->name.length] = '\0';
+ zeroName.name = zeroChars;
+ FontParseXLFDName (zeroChars, &temp, FONT_XLFD_REPLACE_ZERO);
+ zeroName.length = strlen (zeroChars);
+ zeroName.ndashes = entry->name.ndashes;
+ xlfdName.name = vals->xlfdName;
+ xlfdName.length = strlen(xlfdName.name);
+ xlfdName.ndashes = FontFileCountDashes(xlfdName.name, xlfdName.length);
+ restart_bestscale_loop: ;
+ /*
+ * Look through all the registered bitmap sources for
+ * the same zero name as ours; entries along that one
+ * can be scaled as desired.
+ */
+ for (source = 0; source < FontFileBitmapSources.count; source++)
+ {
+ /* There might already be a bitmap that satisfies the request
+ but didn't have a zero name that was found by the scalable
+ font matching logic. Keep track if there is. */
+ if (bitmap == NULL && vals->xlfdName != NULL)
+ {
+ bitmap_fpe = FontFileBitmapSources.fpe[source];
+ dir = (FontDirectoryPtr) bitmap_fpe->private;
+ bitmap = FontFileFindNameInDir (&dir->nonScalable, &xlfdName);
+ if (bitmap && bitmap->type != FONT_ENTRY_BITMAP)
+ {
+ if (bitmap->type == FONT_ENTRY_ALIAS && aliascount > 0)
+ {
+ aliascount--;
+ xlfdName.name = bitmap->u.alias.resolved;
+ xlfdName.length = strlen(xlfdName.name);
+ xlfdName.ndashes = FontFileCountDashes(xlfdName.name,
+ xlfdName.length);
+ bitmap = NULL;
+ goto restart_bestscale_loop;
+ }
+ else
+ bitmap = NULL;
+ }
+ }
+
+ if (FontFileBitmapSources.fpe[source] == fpe)
+ zero = entry;
+ else
+ {
+ dir = (FontDirectoryPtr) FontFileBitmapSources.fpe[source]->private;
+ zero = FontFileFindNameInDir (&dir->scalable, &zeroName);
+ if (!zero)
+ continue;
+ }
+ extra = zero->u.scalable.extra;
+ for (i = 0; i < extra->numScaled; i++)
+ {
+ scaled = &extra->scaled[i];
+ if (!scaled->bitmap)
+ continue;
+ if (!ComputeScaleFactors(&scaled->vals, vals, &dx, &dy, &sdx, &sdy,
+ &rescale_x))
+ continue;
+ score = 0;
+ dx_amount = dx;
+ dy_amount = dy;
+ SCORE(dy_amount, 10);
+ SCORE(dx_amount, 1);
+ if ((score > best_score) ||
+ ((score == best_score) &&
+ ((dy_amount < best_dy_amount) ||
+ ((dy_amount == best_dy_amount) &&
+ (dx_amount < best_dx_amount)))))
+ {
+ best_fpe = FontFileBitmapSources.fpe[source];
+ best_scaled = scaled;
+ best_score = score;
+ best_dx = dx;
+ best_dy = dy;
+ best_sdx = sdx;
+ best_sdy = sdy;
+ best_dx_amount = dx_amount;
+ best_dy_amount = dy_amount;
+ best_rescale_x = rescale_x;
+ }
+ /* Is this font a candidate for use without ugly rescaling? */
+ if (fabs(dx) > EPS && fabs(dy) > EPS &&
+ fabs(vals->pixel_matrix[0] * rescale_x -
+ scaled->vals.pixel_matrix[0]) < 1 &&
+ fabs(vals->pixel_matrix[1] * rescale_x -
+ scaled->vals.pixel_matrix[1]) < EPS &&
+ fabs(vals->pixel_matrix[2] -
+ scaled->vals.pixel_matrix[2]) < EPS &&
+ fabs(vals->pixel_matrix[3] -
+ scaled->vals.pixel_matrix[3]) < 1)
+ {
+ /* Yes. The pixel sizes are close on the diagonal and
+ extremely close off the diagonal. */
+ score = 0;
+ SCORE2(vals->pixel_matrix[3] /
+ scaled->vals.pixel_matrix[3], 10);
+ SCORE2(vals->pixel_matrix[0] * rescale_x /
+ scaled->vals.pixel_matrix[0], 1);
+ if (score > best_unscaled_score)
+ {
+ best_unscaled_fpe = FontFileBitmapSources.fpe[source];
+ best_unscaled = scaled;
+ best_unscaled_sdx = sdx / dx;
+ best_unscaled_sdy = sdy / dy;
+ best_unscaled_score = score;
+ best_unscaled_rescale_x = rescale_x;
+ }
+ }
+ }
+ }
+ if (best_unscaled)
+ {
+ *best = best_unscaled->vals;
+ *fpep = best_unscaled_fpe;
+ *dxp = 1.0;
+ *dyp = 1.0;
+ *sdxp = best_unscaled_sdx;
+ *sdyp = best_unscaled_sdy;
+ rescale_x = best_unscaled_rescale_x;
+ result = best_unscaled->bitmap;
+ }
+ else if (best_scaled)
+ {
+ *best = best_scaled->vals;
+ *fpep = best_fpe;
+ *dxp = best_dx;
+ *dyp = best_dy;
+ *sdxp = best_sdx;
+ *sdyp = best_sdy;
+ rescale_x = best_rescale_x;
+ result = best_scaled->bitmap;
+ }
+ else
+ result = NULL;
+
+ if (bitmap != NULL && (result == NULL || *dxp != 1.0 || *dyp != 1.0))
+ {
+ *fpep = bitmap_fpe;
+ FontParseXLFDName (bitmap->name.name, best, FONT_XLFD_REPLACE_NONE);
+ if (ComputeScaleFactors(best, best, dxp, dyp, sdxp, sdyp, &rescale_x))
+ result = bitmap;
+ else
+ result = NULL;
+ }
+
+ if (result && rescale_x != 1.0)
+ {
+ /* We have rescaled horizontally due to an XLFD width field. Change
+ the matrix appropriately */
+ vals->pixel_matrix[0] *= rescale_x;
+ vals->pixel_matrix[1] *= rescale_x;
+ vals->values_supplied = vals->values_supplied & ~POINTSIZE_MASK;
+ /* Recompute and reround the FontScalablePtr values after
+ rescaling for the new width. */
+ FontFileCompleteXLFD(vals, vals);
+ }
+
+ return result;
+}
+
+static long
+doround(double x)
+{
+ return (x >= 0) ? (long)(x + .5) : (long)(x - .5);
+}
+
+static int
+computeProps(FontPropPtr pf, char *wasStringProp,
+ FontPropPtr npf, char *isStringProp,
+ unsigned int nprops, double xfactor, double yfactor,
+ double sXfactor, double sYfactor)
+{
+ int n;
+ int count;
+ fontProp *t;
+ double rawfactor = 0.0;
+
+ for (count = 0; nprops > 0; nprops--, pf++, wasStringProp++) {
+ n = sizeof(fontPropTable) / sizeof(fontProp);
+ for (t = fontPropTable; n && (t->atom != pf->name); n--, t++);
+ if (!n)
+ continue;
+
+ switch (t->type) {
+ case scaledX:
+ npf->value = doround(xfactor * (double)pf->value);
+ rawfactor = sXfactor;
+ break;
+ case scaledY:
+ npf->value = doround(yfactor * (double)pf->value);
+ rawfactor = sYfactor;
+ break;
+ case unscaled:
+ npf->value = pf->value;
+ npf->name = pf->name;
+ npf++;
+ count++;
+ *isStringProp++ = *wasStringProp;
+ break;
+ default:
+ break;
+ }
+ if (t->type != unscaled)
+ {
+ npf->name = pf->name;
+ npf++;
+ count++;
+ npf->value = doround(rawfactor * (double)pf->value);
+ npf->name = rawFontPropTable[t - fontPropTable].atom;
+ npf++;
+ count++;
+ *isStringProp++ = *wasStringProp;
+ *isStringProp++ = *wasStringProp;
+ }
+ }
+ return count;
+}
+
+
+static int
+ComputeScaledProperties(FontInfoPtr sourceFontInfo, /* the font to be scaled */
+ char *name, /* name of resulting font */
+ FontScalablePtr vals,
+ double dx, double dy, /* scale factors in x and y */
+ double sdx, double sdy, /* directions */
+ long sWidth, /* 1000-pixel average width */
+ FontPropPtr *pProps, /* returns properties;
+ preallocated */
+ char **pIsStringProp) /* return booleans;
+ preallocated */
+{
+ int n;
+ char *ptr1 = NULL, *ptr2 = NULL;
+ char *ptr3;
+ FontPropPtr fp;
+ fontProp *fpt;
+ char *isStringProp;
+ int nProps;
+
+ if (bitscaleGeneration != serverGeneration) {
+ initFontPropTable();
+ bitscaleGeneration = serverGeneration;
+ }
+ nProps = NPROPS + 1 + sizeof(fontPropTable) / sizeof(fontProp) +
+ sizeof(rawFontPropTable) / sizeof(fontProp);
+ fp = malloc(sizeof(FontPropRec) * nProps);
+ *pProps = fp;
+ if (!fp) {
+ fprintf(stderr, "Error: Couldn't allocate font properties (%ld*%d)\n",
+ (unsigned long)sizeof(FontPropRec), nProps);
+ return 1;
+ }
+ isStringProp = malloc (nProps);
+ *pIsStringProp = isStringProp;
+ if (!isStringProp)
+ {
+ fprintf(stderr, "Error: Couldn't allocate isStringProp (%d)\n", nProps);
+ free (fp);
+ return 1;
+ }
+ ptr2 = name;
+ for (fpt = fontNamePropTable, n = NPROPS;
+ n;
+ fp++, fpt++, n--, isStringProp++)
+ {
+
+ if (*ptr2)
+ {
+ ptr1 = ptr2 + 1;
+ if (!(ptr2 = strchr(ptr1, '-'))) ptr2 = strchr(ptr1, '\0');
+ }
+
+ *isStringProp = 0;
+ switch (fpt->type) {
+ case atom:
+ fp->value = MakeAtom(ptr1, ptr2 - ptr1, TRUE);
+ *isStringProp = 1;
+ break;
+ case truncate_atom:
+ for (ptr3 = ptr1; *ptr3; ptr3++)
+ if (*ptr3 == '[')
+ break;
+ if (!*ptr3) ptr3 = ptr2;
+ fp->value = MakeAtom(ptr1, ptr3 - ptr1, TRUE);
+ *isStringProp = 1;
+ break;
+ case pixel_size:
+ fp->value = doround(vals->pixel_matrix[3]);
+ break;
+ case point_size:
+ fp->value = doround(vals->point_matrix[3] * 10.0);
+ break;
+ case resolution_x:
+ fp->value = vals->x;
+ break;
+ case resolution_y:
+ fp->value = vals->y;
+ break;
+ case average_width:
+ fp->value = vals->width;
+ break;
+ case fontname:
+ fp->value = MakeAtom(name, strlen(name), TRUE);
+ *isStringProp = 1;
+ break;
+ case raw_ascent:
+ fp->value = sourceFontInfo->fontAscent * sdy;
+ break;
+ case raw_descent:
+ fp->value = sourceFontInfo->fontDescent * sdy;
+ break;
+ case raw_pointsize:
+ fp->value = (long)(72270.0 / (double)vals->y + .5);
+ break;
+ case raw_pixelsize:
+ fp->value = 1000;
+ break;
+ case raw_average_width:
+ fp->value = sWidth;
+ break;
+ default:
+ break;
+ }
+ fp->name = fpt->atom;
+ }
+ n = NPROPS;
+ n += computeProps(sourceFontInfo->props, sourceFontInfo->isStringProp,
+ fp, isStringProp, sourceFontInfo->nprops, dx, dy,
+ sdx, sdy);
+ return n;
+}
+
+
+static int
+compute_xform_matrix(FontScalablePtr vals, double dx, double dy,
+ double *xform, double *inv_xform,
+ double *xmult, double *ymult)
+{
+ double det;
+ double pixel = get_matrix_vertical_component(vals->pixel_matrix);
+ double pixelset = get_matrix_horizontal_component(vals->pixel_matrix);
+
+ if (pixel < EPS || pixelset < EPS) return 0;
+
+ /* Initialize the transformation matrix to the scaling factors */
+ xform[0] = dx / pixelset;
+ xform[1] = xform[2] = 0.0;
+ xform[3] = dy / pixel;
+
+/* Inline matrix multiply -- somewhat ugly to minimize register usage */
+#define MULTIPLY_XFORM(a,b,c,d) \
+{ \
+ register double aa = (a), bb = (b), cc = (c), dd = (d); \
+ register double temp; \
+ temp = aa * xform[0] + cc * xform[1]; \
+ aa = aa * xform[2] + cc * xform[3]; \
+ xform[1] = bb * xform[0] + dd * xform[1]; \
+ xform[3] = bb * xform[2] + dd * xform[3]; \
+ xform[0] = temp; \
+ xform[2] = aa; \
+}
+
+ /* Rescale the transformation matrix for size of source font */
+ MULTIPLY_XFORM(vals->pixel_matrix[0],
+ vals->pixel_matrix[1],
+ vals->pixel_matrix[2],
+ vals->pixel_matrix[3]);
+
+ *xmult = xform[0];
+ *ymult = xform[3];
+
+
+ if (inv_xform == NULL) return 1;
+
+ /* Compute the determinant for use in inverting the matrix. */
+ det = xform[0] * xform[3] - xform[1] * xform[2];
+
+ /* If the determinant is tiny or zero, give up */
+ if (fabs(det) < EPS) return 0;
+
+ /* Compute the inverse */
+ inv_xform[0] = xform[3] / det;
+ inv_xform[1] = -xform[1] / det;
+ inv_xform[2] = -xform[2] / det;
+ inv_xform[3] = xform[0] / det;
+
+ return 1;
+}
+
+/*
+ * ScaleFont
+ * returns a pointer to the new scaled font, or NULL (due to AllocError).
+ */
+static FontPtr
+ScaleFont(FontPtr opf, /* originating font */
+ double widthMult, /* glyphs width scale factor */
+ double heightMult, /* glyphs height scale factor */
+ double sWidthMult, /* scalable glyphs width scale factor */
+ double sHeightMult, /* scalable glyphs height scale factor */
+ FontScalablePtr vals,
+ double *newWidthMult, /* return: X component of glyphs width
+ scale factor */
+ double *newHeightMult, /* return: Y component of glyphs height
+ scale factor */
+ long *sWidth) /* return: average 1000-pixel width */
+{
+ FontPtr pf;
+ FontInfoPtr pfi,
+ opfi;
+ BitmapFontPtr bitmapFont,
+ obitmapFont;
+ CharInfoPtr pci,
+ opci;
+ int nchars = 0; /* how many characters in the font */
+ int i;
+ int firstCol, lastCol, firstRow, lastRow;
+ double xform[4], inv_xform[4];
+ double xmult, ymult;
+ int totalwidth = 0, totalchars = 0;
+#define OLDINDEX(i) (((i)/(lastCol - firstCol + 1) + \
+ firstRow - opf->info.firstRow) * \
+ (opf->info.lastCol - opf->info.firstCol + 1) + \
+ (i)%(lastCol - firstCol + 1) + \
+ firstCol - opf->info.firstCol)
+
+ *sWidth = 0;
+
+ opfi = &opf->info;
+ obitmapFont = (BitmapFontPtr) opf->fontPrivate;
+
+ bitmapFont = 0;
+ if (!(pf = CreateFontRec())) {
+ fprintf(stderr, "Error: Couldn't allocate FontRec (%ld)\n",
+ (unsigned long)sizeof(FontRec));
+ goto bail;
+ }
+ pf->refcnt = 0;
+ pf->bit = opf->bit;
+ pf->byte = opf->byte;
+ pf->glyph = opf->glyph;
+ pf->scan = opf->scan;
+
+ pf->get_glyphs = bitmapGetGlyphs;
+ pf->get_metrics = bitmapGetMetrics;
+ pf->unload_font = bitmapUnloadScalable;
+ pf->unload_glyphs = NULL;
+
+ pfi = &pf->info;
+ *pfi = *opfi;
+ /* If charset subsetting specified in vals, determine what our range
+ needs to be for the output font */
+ if (vals->nranges)
+ {
+ int i;
+
+ pfi->allExist = 0;
+ firstCol = 255;
+ lastCol = 0;
+ firstRow = 255;
+ lastRow = 0;
+
+ for (i = 0; i < vals->nranges; i++)
+ {
+ if (vals->ranges[i].min_char_high != vals->ranges[i].max_char_high)
+ {
+ firstCol = opfi->firstCol;
+ lastCol = opfi->lastCol;
+ }
+ if (firstCol > vals->ranges[i].min_char_low)
+ firstCol = vals->ranges[i].min_char_low;
+ if (lastCol < vals->ranges[i].max_char_low)
+ lastCol = vals->ranges[i].max_char_low;
+ if (firstRow > vals->ranges[i].min_char_high)
+ firstRow = vals->ranges[i].min_char_high;
+ if (lastRow < vals->ranges[i].max_char_high)
+ lastRow = vals->ranges[i].max_char_high;
+ }
+
+ if (firstCol > lastCol || firstRow > lastRow)
+ goto bail;
+
+ if (firstCol < opfi->firstCol)
+ firstCol = opfi->firstCol;
+ if (lastCol > opfi->lastCol)
+ lastCol = opfi->lastCol;
+ if (firstRow < opfi->firstRow)
+ firstRow = opfi->firstRow;
+ if (lastRow > opfi->lastRow)
+ lastRow = opfi->lastRow;
+ }
+ else
+ {
+ firstCol = opfi->firstCol;
+ lastCol = opfi->lastCol;
+ firstRow = opfi->firstRow;
+ lastRow = opfi->lastRow;
+ }
+
+ bitmapFont = malloc(sizeof(BitmapFontRec));
+ if (!bitmapFont) {
+ fprintf(stderr, "Error: Couldn't allocate bitmapFont (%ld)\n",
+ (unsigned long)sizeof(BitmapFontRec));
+ goto bail;
+ }
+ nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1);
+ pfi->firstRow = firstRow;
+ pfi->lastRow = lastRow;
+ pfi->firstCol = firstCol;
+ pfi->lastCol = lastCol;
+ pf->fontPrivate = (pointer) bitmapFont;
+ bitmapFont->version_num = obitmapFont->version_num;
+ bitmapFont->num_chars = nchars;
+ bitmapFont->num_tables = obitmapFont->num_tables;
+ bitmapFont->metrics = 0;
+ bitmapFont->ink_metrics = 0;
+ bitmapFont->bitmaps = 0;
+ bitmapFont->encoding = 0;
+ bitmapFont->bitmapExtra = 0;
+ bitmapFont->pDefault = 0;
+ bitmapFont->metrics = malloc(nchars * sizeof(CharInfoRec));
+ if (!bitmapFont->metrics) {
+ fprintf(stderr, "Error: Couldn't allocate metrics (%d*%ld)\n",
+ nchars, (unsigned long)sizeof(CharInfoRec));
+ goto bail;
+ }
+ bitmapFont->encoding = calloc(NUM_SEGMENTS(nchars), sizeof(CharInfoPtr*));
+ if (!bitmapFont->encoding) {
+ fprintf(stderr, "Error: Couldn't allocate encoding (%d*%ld)\n",
+ nchars, (unsigned long)sizeof(CharInfoPtr));
+ goto bail;
+ }
+
+#undef MAXSHORT
+#define MAXSHORT 32767
+#undef MINSHORT
+#define MINSHORT -32768
+
+ pfi->anamorphic = FALSE;
+ if (heightMult != widthMult)
+ pfi->anamorphic = TRUE;
+ pfi->cachable = TRUE;
+
+ if (!compute_xform_matrix(vals, widthMult, heightMult, xform,
+ inv_xform, &xmult, &ymult))
+ goto bail;
+
+ pfi->fontAscent = opfi->fontAscent * ymult;
+ pfi->fontDescent = opfi->fontDescent * ymult;
+
+ pfi->minbounds.leftSideBearing = MAXSHORT;
+ pfi->minbounds.rightSideBearing = MAXSHORT;
+ pfi->minbounds.ascent = MAXSHORT;
+ pfi->minbounds.descent = MAXSHORT;
+ pfi->minbounds.characterWidth = MAXSHORT;
+ pfi->minbounds.attributes = MAXSHORT;
+
+ pfi->maxbounds.leftSideBearing = MINSHORT;
+ pfi->maxbounds.rightSideBearing = MINSHORT;
+ pfi->maxbounds.ascent = MINSHORT;
+ pfi->maxbounds.descent = MINSHORT;
+ pfi->maxbounds.characterWidth = MINSHORT;
+ pfi->maxbounds.attributes = MINSHORT;
+
+ /* Compute the transformation and inverse transformation matrices.
+ Can fail if the determinant is zero. */
+
+ pci = bitmapFont->metrics;
+ for (i = 0; i < nchars; i++)
+ {
+ if ((opci = ACCESSENCODING(obitmapFont->encoding,OLDINDEX(i))))
+ {
+ double newlsb, newrsb, newdesc, newasc, point[2];
+
+#define minchar(p) ((p).min_char_low + ((p).min_char_high << 8))
+#define maxchar(p) ((p).max_char_low + ((p).max_char_high << 8))
+
+ if (vals->nranges)
+ {
+ int row = i / (lastCol - firstCol + 1) + firstRow;
+ int col = i % (lastCol - firstCol + 1) + firstCol;
+ int ch = (row << 8) + col;
+ int j;
+ for (j = 0; j < vals->nranges; j++)
+ if (ch >= minchar(vals->ranges[j]) &&
+ ch <= maxchar(vals->ranges[j]))
+ break;
+ if (j == vals->nranges)
+ {
+ continue;
+ }
+ }
+
+ if (opci->metrics.leftSideBearing == 0 &&
+ opci->metrics.rightSideBearing == 0 &&
+ opci->metrics.ascent == 0 &&
+ opci->metrics.descent == 0 &&
+ opci->metrics.characterWidth == 0)
+ {
+ continue;
+ }
+
+ if(!bitmapFont->encoding[SEGMENT_MAJOR(i)]) {
+ bitmapFont->encoding[SEGMENT_MAJOR(i)]=
+ calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr));
+ if(!bitmapFont->encoding[SEGMENT_MAJOR(i)])
+ goto bail;
+ }
+ ACCESSENCODINGL(bitmapFont->encoding, i) = pci;
+
+ /* Compute new extents for this glyph */
+ TRANSFORM_POINT(xform,
+ opci->metrics.leftSideBearing,
+ -opci->metrics.descent,
+ point);
+ newlsb = point[0];
+ newrsb = newlsb;
+ newdesc = -point[1];
+ newasc = -newdesc;
+ TRANSFORM_POINT(xform,
+ opci->metrics.leftSideBearing,
+ opci->metrics.ascent,
+ point);
+ CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
+ TRANSFORM_POINT(xform,
+ opci->metrics.rightSideBearing,
+ -opci->metrics.descent,
+ point);
+ CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
+ TRANSFORM_POINT(xform,
+ opci->metrics.rightSideBearing,
+ opci->metrics.ascent,
+ point);
+ CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
+
+ pci->metrics.leftSideBearing = (int)floor(newlsb);
+ pci->metrics.rightSideBearing = (int)floor(newrsb + .5);
+ pci->metrics.descent = (int)ceil(newdesc);
+ pci->metrics.ascent = (int)floor(newasc + .5);
+ /* Accumulate total width of characters before transformation,
+ to ascertain predominant direction of font. */
+ totalwidth += opci->metrics.characterWidth;
+ pci->metrics.characterWidth =
+ doround((double)opci->metrics.characterWidth * xmult);
+ pci->metrics.attributes =
+ doround((double)opci->metrics.characterWidth * sWidthMult);
+ if (!pci->metrics.characterWidth)
+ {
+ /* Since transformation may shrink width, height, and
+ escapement to zero, make sure existing characters
+ are not mistaken for undefined characters. */
+
+ if (pci->metrics.rightSideBearing ==
+ pci->metrics.leftSideBearing)
+ pci->metrics.rightSideBearing++;
+ if (pci->metrics.ascent == -pci->metrics.descent)
+ pci->metrics.ascent++;
+ }
+
+ pci++;
+ }
+ }
+
+
+ /*
+ * For each character, set the per-character metrics, scale the glyph, and
+ * check per-font minbounds and maxbounds character information.
+ */
+
+ pci = bitmapFont->metrics;
+ for (i = 0; i < nchars; i++)
+ {
+ if ((pci = ACCESSENCODING(bitmapFont->encoding,i)) &&
+ (opci = ACCESSENCODING(obitmapFont->encoding,OLDINDEX(i))))
+ {
+ totalchars++;
+ *sWidth += abs((int)(INT16)pci->metrics.attributes);
+#define MINMAX(field) \
+ if (pfi->minbounds.field > pci->metrics.field) \
+ pfi->minbounds.field = pci->metrics.field; \
+ if (pfi->maxbounds.field < pci->metrics.field) \
+ pfi->maxbounds.field = pci->metrics.field
+
+ MINMAX(leftSideBearing);
+ MINMAX(rightSideBearing);
+ MINMAX(ascent);
+ MINMAX(descent);
+ MINMAX(characterWidth);
+
+ /* Hack: Cast attributes into a signed quantity. Tread lightly
+ for now and don't go changing the global Xproto.h file */
+ if ((INT16)pfi->minbounds.attributes >
+ (INT16)pci->metrics.attributes)
+ pfi->minbounds.attributes = pci->metrics.attributes;
+ if ((INT16)pfi->maxbounds.attributes <
+ (INT16)pci->metrics.attributes)
+ pfi->maxbounds.attributes = pci->metrics.attributes;
+#undef MINMAX
+ }
+ }
+ pfi->ink_minbounds = pfi->minbounds;
+ pfi->ink_maxbounds = pfi->maxbounds;
+ if (totalchars)
+ {
+ *sWidth = (*sWidth * 10 + totalchars / 2) / totalchars;
+ if (totalwidth < 0)
+ {
+ /* Dominant direction is R->L */
+ *sWidth = -*sWidth;
+ }
+
+ if (pfi->minbounds.characterWidth == pfi->maxbounds.characterWidth)
+ vals->width = pfi->minbounds.characterWidth * 10;
+ else
+ vals->width = doround((double)*sWidth * vals->pixel_matrix[0] /
+ 1000.0);
+ }
+ else
+ {
+ vals->width = 0;
+ *sWidth = 0;
+ }
+ FontComputeInfoAccelerators (pfi);
+
+ if (pfi->defaultCh != (unsigned short) NO_SUCH_CHAR) {
+ unsigned int r,
+ c,
+ cols;
+
+ r = pfi->defaultCh >> 8;
+ c = pfi->defaultCh & 0xFF;
+ if (pfi->firstRow <= r && r <= pfi->lastRow &&
+ pfi->firstCol <= c && c <= pfi->lastCol) {
+ cols = pfi->lastCol - pfi->firstCol + 1;
+ r = r - pfi->firstRow;
+ c = c - pfi->firstCol;
+ bitmapFont->pDefault =
+ ACCESSENCODING(bitmapFont->encoding, r * cols + c);
+ }
+ }
+
+ *newWidthMult = xmult;
+ *newHeightMult = ymult;
+ return pf;
+bail:
+ if (pf)
+ free(pf);
+ if (bitmapFont) {
+ free(bitmapFont->metrics);
+ free(bitmapFont->ink_metrics);
+ free(bitmapFont->bitmaps);
+ if(bitmapFont->encoding)
+ for(i=0; i<NUM_SEGMENTS(nchars); i++)
+ free(bitmapFont->encoding[i]);
+ free(bitmapFont->encoding);
+ }
+ return NULL;
+}
+
+static void
+ScaleBitmap(FontPtr pFont, CharInfoPtr opci, CharInfoPtr pci,
+ double *inv_xform, double widthMult, double heightMult)
+{
+ register char *bitmap, /* The bits */
+ *newBitmap;
+ register int bpr, /* Padding information */
+ newBpr;
+ int width, /* Extents information */
+ height,
+ newWidth,
+ newHeight;
+ register int row, /* Loop variables */
+ col;
+ INT32 deltaX, /* Increments for resampling loop */
+ deltaY;
+ INT32 xValue, /* Subscripts for resampling loop */
+ yValue;
+ double point[2];
+ unsigned char *char_grayscale = 0;
+ INT32 *diffusion_workspace = NULL, *thisrow = NULL,
+ *nextrow = NULL, pixmult = 0;
+ int box_x = 0, box_y = 0;
+
+ static unsigned char masklsb[] =
+ { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };
+ static unsigned char maskmsb[] =
+ { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 };
+ unsigned char *mask = (pFont->bit == LSBFirst ? masklsb : maskmsb);
+
+
+ bitmap = opci->bits;
+ newBitmap = pci->bits;
+ width = GLYPHWIDTHPIXELS(opci);
+ height = GLYPHHEIGHTPIXELS(opci);
+ newWidth = GLYPHWIDTHPIXELS(pci);
+ newHeight = GLYPHHEIGHTPIXELS(pci);
+ if (!newWidth || !newHeight || !width || !height)
+ return;
+
+ bpr = BYTES_PER_ROW(width, pFont->glyph);
+ newBpr = BYTES_PER_ROW(newWidth, pFont->glyph);
+
+ if (widthMult > 0.0 && heightMult > 0.0 &&
+ (widthMult < 1.0 || heightMult < 1.0))
+ {
+ /* We are reducing in one or both dimensions. In an attempt to
+ reduce aliasing, we'll antialias by passing the original
+ glyph through a low-pass box filter (which results in a
+ grayscale image), then use error diffusion to create bitonal
+ output in the resampling loop. */
+
+ /* First compute the sizes of the box filter */
+ widthMult = ceil(1.0 / widthMult);
+ heightMult = ceil(1.0 / heightMult);
+ box_x = width / 2;
+ box_y = height / 2;
+ if (widthMult < (double)box_x) box_x = (int)widthMult;
+ if (heightMult < (double)box_y) box_y = (int)heightMult;
+ /* The pixmult value (below) is used to darken the image before
+ we perform error diffusion: a necessary concession to the
+ fact that it's very difficult to generate readable halftoned
+ glyphs. The degree of darkening is proportional to the size
+ of the blurring filter, hence inversely proportional to the
+ darkness of the lightest gray that results from antialiasing.
+ The result is that characters that exercise this logic (those
+ generated by reducing from a larger source font) tend to err
+ on the side of being too bold instead of being too light to
+ be readable. */
+ pixmult = box_x * box_y * 192;
+
+ if (box_x > 1 || box_y > 1)
+ {
+ /* Looks like we need to anti-alias. Create a workspace to
+ contain the grayscale character plus an additional row and
+ column for scratch */
+ char_grayscale = malloc((width + 1) * (height + 1));
+ if (char_grayscale)
+ {
+ diffusion_workspace = calloc((newWidth + 2) * 2, sizeof(int));
+ if (!diffusion_workspace)
+ {
+ fprintf(stderr, "Warning: Couldn't allocate diffusion"
+ " workspace (%ld)\n",
+ (newWidth + 2) * 2 * (unsigned long)sizeof(int));
+ free(char_grayscale);
+ char_grayscale = (unsigned char *)0;
+ }
+ /* Initialize our error diffusion workspace for later use */
+ thisrow = diffusion_workspace + 1;
+ nextrow = diffusion_workspace + newWidth + 3;
+ } else {
+ fprintf(stderr, "Warning: Couldn't allocate character grayscale (%d)\n", (width + 1) * (height + 1));
+ }
+ }
+ }
+
+ if (char_grayscale)
+ {
+ /* We will be doing antialiasing. First copy the bitmap into
+ our buffer, mapping input range [0,1] to output range
+ [0,255]. */
+ register unsigned char *srcptr, *dstptr;
+ srcptr = (unsigned char *)bitmap;
+ dstptr = char_grayscale;
+ for (row = 0; row < height; row++)
+ {
+ for (col = 0; col < width; col++)
+ *dstptr++ = (srcptr[col >> 3] & mask[col & 0x7]) ? 255 : 0;
+ srcptr += bpr; /* On to next row of source */
+ dstptr++; /* Skip scratch column in dest */
+ }
+ if (box_x > 1)
+ {
+ /* Our box filter has a width > 1... let's filter the rows */
+
+ int right_width = box_x / 2;
+ int left_width = box_x - right_width - 1;
+
+ for (row = 0; row < height; row++)
+ {
+ int sum = 0;
+ int left_size = 0, right_size = 0;
+
+ srcptr = char_grayscale + (width + 1) * row;
+ dstptr = char_grayscale + (width + 1) * height; /* scratch */
+
+ /* We've computed the shape of our full box filter. Now
+ compute the right-hand part of the moving sum */
+ for (right_size = 0; right_size < right_width; right_size++)
+ sum += srcptr[right_size];
+
+ /* Now start moving the sum, growing the box filter, and
+ dropping averages into our scratch buffer */
+ for (left_size = 0; left_size < left_width; left_size++)
+ {
+ sum += srcptr[right_width];
+ *dstptr++ = sum / (left_size + right_width + 1);
+ srcptr++;
+ }
+
+ /* The box filter has reached full width... continue
+ computation of moving average until the right side
+ hits the wall. */
+ for (col = left_size; col + right_size < width; col++)
+ {
+ sum += srcptr[right_width];
+ *dstptr++ = sum / box_x;
+ sum -= srcptr[-left_width];
+ srcptr++;
+ }
+
+ /* Collapse the right side of the box filter */
+ for (; right_size > 0; right_size--)
+ {
+ *dstptr++ = sum / (left_width + right_size);
+ sum -= srcptr[-left_width];
+ srcptr++;
+ }
+
+ /* Done with the row... copy dest back over source */
+ memmove(char_grayscale + (width + 1) * row,
+ char_grayscale + (width + 1) * height,
+ width);
+ }
+ }
+ if (box_y > 1)
+ {
+ /* Our box filter has a height > 1... let's filter the columns */
+
+ int bottom_height = box_y / 2;
+ int top_height = box_y - bottom_height - 1;
+
+ for (col = 0; col < width; col++)
+ {
+ int sum = 0;
+ int top_size = 0, bottom_size = 0;
+
+ srcptr = char_grayscale + col;
+ dstptr = char_grayscale + width; /* scratch */
+
+ /* We've computed the shape of our full box filter. Now
+ compute the bottom part of the moving sum */
+ for (bottom_size = 0;
+ bottom_size < bottom_height;
+ bottom_size++)
+ sum += srcptr[bottom_size * (width + 1)];
+
+ /* Now start moving the sum, growing the box filter, and
+ dropping averages into our scratch buffer */
+ for (top_size = 0; top_size < top_height; top_size++)
+ {
+ sum += srcptr[bottom_height * (width + 1)];
+ *dstptr = sum / (top_size + bottom_height + 1);
+ dstptr += width + 1;
+ srcptr += width + 1;
+ }
+
+ /* The box filter has reached full height... continue
+ computation of moving average until the bottom
+ hits the wall. */
+ for (row = top_size; row + bottom_size < height; row++)
+ {
+ sum += srcptr[bottom_height * (width + 1)];
+ *dstptr = sum / box_y;
+ dstptr += width + 1;
+ sum -= srcptr[-top_height * (width + 1)];
+ srcptr += width + 1;
+ }
+
+ /* Collapse the bottom of the box filter */
+ for (; bottom_size > 0; bottom_size--)
+ {
+ *dstptr = sum / (top_height + bottom_size);
+ dstptr += width + 1;
+ sum -= srcptr[-top_height * (width + 1)];
+ srcptr += width + 1;
+ }
+
+ /* Done with the column... copy dest back over source */
+
+ dstptr = char_grayscale + col;
+ srcptr = char_grayscale + width; /* scratch */
+ for (row = 0; row < height; row++)
+ {
+ *dstptr = *srcptr;
+ dstptr += width + 1;
+ srcptr += width + 1;
+ }
+ }
+ }
+
+ /* Increase the grayvalue to increase ink a bit */
+ srcptr = char_grayscale;
+ for (row = 0; row < height; row++)
+ {
+ for (col = 0; col < width; col++)
+ {
+ register int pixvalue = (int)*srcptr * pixmult / 256;
+ if (pixvalue > 255) pixvalue = 255;
+ *srcptr = pixvalue;
+ srcptr++;
+ }
+ srcptr++;
+ }
+ }
+
+ /* Compute the increment values for the resampling loop */
+ TRANSFORM_POINT(inv_xform, 1, 0, point);
+ deltaX = (INT32)(point[0] * 65536.0);
+ deltaY = (INT32)(-point[1] * 65536.0);
+
+ /* Resampling loop: resamples original glyph for generation of new
+ glyph in transformed coordinate system. */
+
+ for (row = 0; row < newHeight; row++)
+ {
+ /* Compute inverse transformation for start of this row */
+ TRANSFORM_POINT(inv_xform,
+ (double)(pci->metrics.leftSideBearing) + .5,
+ (double)(pci->metrics.ascent - row) - .5,
+ point);
+
+ /* Adjust for coordinate system to get resampling point */
+ point[0] -= opci->metrics.leftSideBearing;
+ point[1] = opci->metrics.ascent - point[1];
+
+ /* Convert to integer coordinates */
+ xValue = (INT32)(point[0] * 65536.0);
+ yValue = (INT32)(point[1] * 65536.0);
+
+ if (char_grayscale)
+ {
+ INT32 *temp;
+ for (col = 0; col < newWidth; col++)
+ {
+ register int x = xValue >> 16, y = yValue >> 16;
+ int pixvalue, error;
+
+ pixvalue = ((x >= 0 && x < width && y >= 0 && y < height) ?
+ char_grayscale[x + y * (width + 1)] : 0) +
+ thisrow[col] / 16;
+ if (pixvalue > 255) pixvalue = 255;
+ else if (pixvalue < 0) pixvalue = 0;
+
+ /* Choose the bit value and set resulting error value */
+ if (pixvalue >= 128)
+ {
+ newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7];
+ error = pixvalue - 255;
+ }
+ else
+ error = -pixvalue;
+
+ /* Diffuse the error */
+ thisrow[col + 1] += error * 7;
+ nextrow[col - 1] += error * 3;
+ nextrow[col] += error * 5;
+ nextrow[col + 1] = error;
+
+ xValue += deltaX;
+ yValue += deltaY;
+ }
+
+ /* Add in error values that fell off either end */
+ nextrow[0] += nextrow[-1];
+ nextrow[newWidth - 2] += thisrow[newWidth];
+ nextrow[newWidth - 1] += nextrow[newWidth];
+ nextrow[newWidth] = 0;
+
+ temp = nextrow;
+ nextrow = thisrow;
+ thisrow = temp;
+ nextrow[-1] = nextrow[0] = 0;
+ }
+ else
+ {
+ for (col = 0; col < newWidth; col++)
+ {
+ register int x = xValue >> 16, y = yValue >> 16;
+
+ if (x >= 0 && x < width && y >= 0 && y < height)
+ {
+ /* Use point-sampling for rescaling. */
+
+ if (bitmap[(x >> 3) + y * bpr] & mask[x & 0x7])
+ newBitmap[(col >> 3) + row * newBpr] |= mask[col & 0x7];
+ }
+
+ xValue += deltaX;
+ yValue += deltaY;
+ }
+ }
+ }
+
+
+ if (char_grayscale)
+ {
+ free(char_grayscale);
+ free(diffusion_workspace);
+ }
+}
+
+static FontPtr
+BitmapScaleBitmaps(FontPtr pf, /* scaled font */
+ FontPtr opf, /* originating font */
+ double widthMult, /* glyphs width scale factor */
+ double heightMult, /* glyphs height scale factor */
+ FontScalablePtr vals)
+{
+ register int i;
+ int nchars = 0;
+ char *glyphBytes;
+ BitmapFontPtr bitmapFont,
+ obitmapFont;
+ CharInfoPtr pci,
+ opci;
+ FontInfoPtr pfi;
+ int glyph;
+ unsigned bytestoalloc = 0;
+ int firstCol, lastCol, firstRow, lastRow;
+
+ double xform[4], inv_xform[4];
+ double xmult, ymult;
+
+ bitmapFont = (BitmapFontPtr) pf->fontPrivate;
+ obitmapFont = (BitmapFontPtr) opf->fontPrivate;
+
+ if (!compute_xform_matrix(vals, widthMult, heightMult, xform,
+ inv_xform, &xmult, &ymult))
+ goto bail;
+
+ pfi = &pf->info;
+ firstCol = pfi->firstCol;
+ lastCol = pfi->lastCol;
+ firstRow = pfi->firstRow;
+ lastRow = pfi->lastRow;
+
+ nchars = (lastRow - firstRow + 1) * (lastCol - firstCol + 1);
+ glyph = pf->glyph;
+ for (i = 0; i < nchars; i++)
+ {
+ if ((pci = ACCESSENCODING(bitmapFont->encoding, i)))
+ bytestoalloc += BYTES_FOR_GLYPH(pci, glyph);
+ }
+
+ /* Do we add the font malloc stuff for VALUE ADDED ? */
+ /* Will need to remember to free in the Unload routine */
+
+
+ bitmapFont->bitmaps = calloc(1, bytestoalloc);
+ if (!bitmapFont->bitmaps) {
+ fprintf(stderr, "Error: Couldn't allocate bitmaps (%d)\n", bytestoalloc);
+ goto bail;
+ }
+
+ glyphBytes = bitmapFont->bitmaps;
+ for (i = 0; i < nchars; i++)
+ {
+ if ((pci = ACCESSENCODING(bitmapFont->encoding, i)) &&
+ (opci = ACCESSENCODING(obitmapFont->encoding, OLDINDEX(i))))
+ {
+ pci->bits = glyphBytes;
+ ScaleBitmap (pf, opci, pci, inv_xform,
+ widthMult, heightMult);
+ glyphBytes += BYTES_FOR_GLYPH(pci, glyph);
+ }
+ }
+ return pf;
+
+bail:
+ if (pf)
+ free(pf);
+ if (bitmapFont) {
+ free(bitmapFont->metrics);
+ free(bitmapFont->ink_metrics);
+ free(bitmapFont->bitmaps);
+ if(bitmapFont->encoding)
+ for(i=0; i<NUM_SEGMENTS(nchars); i++)
+ free(bitmapFont->encoding[i]);
+ free(bitmapFont->encoding);
+ }
+ return NULL;
+}
+
+/* ARGSUSED */
+int
+BitmapOpenScalable (FontPathElementPtr fpe,
+ FontPtr *pFont,
+ int flags,
+ FontEntryPtr entry,
+ char *fileName, /* unused */
+ FontScalablePtr vals,
+ fsBitmapFormat format,
+ fsBitmapFormatMask fmask,
+ FontPtr non_cachable_font) /* We don't do licensing */
+{
+ FontScalableRec best;
+ FontPtr font = NullFont;
+ double dx, sdx,
+ dy, sdy,
+ savedX, savedY;
+ FontPropPtr props;
+ char *isStringProp = NULL;
+ int propCount;
+ int status;
+ long sWidth;
+
+ FontEntryPtr scaleFrom;
+ FontPathElementPtr scaleFPE = NULL;
+ FontPtr sourceFont;
+ char fontName[MAXFONTNAMELEN];
+
+ /* Can't deal with mix-endian fonts yet */
+
+
+ /* Reject outrageously small font sizes to keep the math from
+ blowing up. */
+ if (get_matrix_vertical_component(vals->pixel_matrix) < 1.0 ||
+ get_matrix_horizontal_component(vals->pixel_matrix) < 1.0)
+ return BadFontName;
+
+ scaleFrom = FindBestToScale(fpe, entry, vals, &best, &dx, &dy, &sdx, &sdy,
+ &scaleFPE);
+
+ if (!scaleFrom)
+ return BadFontName;
+
+ status = FontFileOpenBitmap(scaleFPE, &sourceFont, LoadAll, scaleFrom,
+ format, fmask);
+
+ if (status != Successful)
+ return BadFontName;
+
+ if (!vals->width)
+ vals->width = best.width * dx;
+
+ /* Compute the scaled font */
+
+ savedX = dx;
+ savedY = dy;
+ font = ScaleFont(sourceFont, dx, dy, sdx, sdy, vals, &dx, &dy, &sWidth);
+ if (font)
+ font = BitmapScaleBitmaps(font, sourceFont, savedX, savedY, vals);
+
+ if (!font)
+ {
+ if (!sourceFont->refcnt)
+ FontFileCloseFont((FontPathElementPtr) 0, sourceFont);
+ return AllocError;
+ }
+
+ /* Prepare font properties for the new font */
+
+ strcpy (fontName, scaleFrom->name.name);
+ FontParseXLFDName (fontName, vals, FONT_XLFD_REPLACE_VALUE);
+
+ propCount = ComputeScaledProperties(&sourceFont->info, fontName, vals,
+ dx, dy, sdx, sdy, sWidth, &props,
+ &isStringProp);
+
+ if (!sourceFont->refcnt)
+ FontFileCloseFont((FontPathElementPtr) 0, sourceFont);
+
+ if (propCount && (!props || !isStringProp))
+ {
+ font->info.nprops = 0;
+ font->info.props = (FontPropPtr)0;
+ font->info.isStringProp = (char *)0;
+ bitmapUnloadScalable(font);
+ return AllocError;
+ }
+
+ font->info.props = props;
+ font->info.nprops = propCount;
+ font->info.isStringProp = isStringProp;
+
+ *pFont = font;
+ return Successful;
+}
+
+int
+BitmapGetInfoScalable (FontPathElementPtr fpe,
+ FontInfoPtr pFontInfo,
+ FontEntryPtr entry,
+ FontNamePtr fontName,
+ char *fileName,
+ FontScalablePtr vals)
+{
+ FontPtr pfont;
+ int flags = 0;
+ long format = 0; /* It doesn't matter what format for just info */
+ long fmask = 0;
+ int ret;
+
+ ret = BitmapOpenScalable(fpe, &pfont, flags, entry, fileName, vals,
+ format, fmask, NULL);
+ if (ret != Successful)
+ return ret;
+ *pFontInfo = pfont->info;
+
+ pfont->info.nprops = 0;
+ pfont->info.props = NULL;
+ pfont->info.isStringProp = NULL;
+
+ (*pfont->unload_font)(pfont);
+ return Successful;
+}
+
+static void
+bitmapUnloadScalable (FontPtr pFont)
+{
+ BitmapFontPtr bitmapFont;
+ FontInfoPtr pfi;
+ int i, nencoding;
+
+ bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
+ pfi = &pFont->info;
+ free (pfi->props);
+ free (pfi->isStringProp);
+ if(bitmapFont->encoding) {
+ nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
+ (pFont->info.lastRow - pFont->info.firstRow + 1);
+ for(i=0; i<NUM_SEGMENTS(nencoding); i++)
+ free(bitmapFont->encoding[i]);
+ }
+ free (bitmapFont->encoding);
+ free (bitmapFont->bitmaps);
+ free (bitmapFont->ink_metrics);
+ free (bitmapFont->metrics);
+ free (pFont->fontPrivate);
+ DestroyFontRec (pFont);
+}
diff --git a/libXfont/src/bitmap/fontink.c b/libXfont/src/bitmap/fontink.c index ad7091fa6..551b81b28 100644 --- a/libXfont/src/bitmap/fontink.c +++ b/libXfont/src/bitmap/fontink.c @@ -1,216 +1,216 @@ -/* - -Copyright 1990, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <X11/fonts/fntfilst.h> -#include <X11/fonts/bitmap.h> -#include <X11/fonts/bdfint.h> - -static unsigned char ink_mask_msb[8] = { - 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, -}; - -static unsigned char ink_mask_lsb[8] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, -}; - -void -FontCharInkMetrics(FontPtr pFont, CharInfoPtr pCI, xCharInfo *pInk) -{ - int leftBearing, - ascent, - descent; - register int vpos, - hpos, - bpos = 0; - int bitmapByteWidth, - bitmapByteWidthPadded; - int bitmapBitWidth; - int span; - register unsigned char *p; - unsigned char *ink_mask = 0; - register int bmax; - register unsigned char charbits; - - if (pFont->bit == MSBFirst) - ink_mask = ink_mask_msb; - else if (pFont->bit == LSBFirst) - ink_mask = ink_mask_lsb; - pInk->characterWidth = pCI->metrics.characterWidth; - pInk->attributes = pCI->metrics.attributes; - - leftBearing = pCI->metrics.leftSideBearing; - ascent = pCI->metrics.ascent; - descent = pCI->metrics.descent; - bitmapBitWidth = GLYPHWIDTHPIXELS(pCI); - bitmapByteWidth = GLYPHWIDTHBYTES(pCI); - bitmapByteWidthPadded = BYTES_PER_ROW(bitmapBitWidth, pFont->glyph); - span = bitmapByteWidthPadded - bitmapByteWidth; - - p = (unsigned char *) pCI->bits; - for (vpos = descent + ascent; --vpos >= 0;) { - for (hpos = bitmapByteWidth; --hpos >= 0;) { - if (*p++ != 0) - goto found_ascent; - } - p += span; - } - /* - * special case -- font with no bits gets all zeros - */ - pInk->leftSideBearing = leftBearing; - pInk->rightSideBearing = leftBearing; - pInk->ascent = 0; - pInk->descent = 0; - return; -found_ascent: - pInk->ascent = vpos - descent + 1; - - p = ((unsigned char *) pCI->bits) + bitmapByteWidthPadded * - (descent + ascent - 1) + bitmapByteWidth; - - for (vpos = descent + ascent; --vpos >= 0;) { - for (hpos = bitmapByteWidth; --hpos >= 0;) { - if (*--p != 0) - goto found_descent; - } - p -= span; - } -found_descent: - pInk->descent = vpos - ascent + 1; - - bmax = 8; - for (hpos = 0; hpos < bitmapByteWidth; hpos++) { - charbits = 0; - p = (unsigned char *) pCI->bits + hpos; - for (vpos = descent + ascent; --vpos >= 0; p += bitmapByteWidthPadded) - charbits |= *p; - if (charbits) { - if (hpos == bitmapByteWidth - 1) - bmax = bitmapBitWidth - (hpos << 3); - p = ink_mask; - for (bpos = bmax; --bpos >= 0;) { - if (charbits & *p++) - goto found_left; - } - } - } -found_left: - pInk->leftSideBearing = leftBearing + (hpos << 3) + bmax - bpos - 1; - - bmax = bitmapBitWidth - ((bitmapByteWidth - 1) << 3); - for (hpos = bitmapByteWidth; --hpos >= 0;) { - charbits = 0; - p = (unsigned char *) pCI->bits + hpos; - for (vpos = descent + ascent; --vpos >= 0; p += bitmapByteWidthPadded) - charbits |= *p; - if (charbits) { - p = ink_mask + bmax; - for (bpos = bmax; --bpos >= 0;) { - if (charbits & *--p) - goto found_right; - } - } - bmax = 8; - } -found_right: - pInk->rightSideBearing = leftBearing + (hpos << 3) + bpos + 1; -} - -#define ISBITONMSB(x, line) ((line)[(x)/8] & (1 << (7-((x)%8)))) -#define SETBITMSB(x, line) ((line)[(x)/8] |= (1 << (7-((x)%8)))) -#define ISBITONLSB(x, line) ((line)[(x)/8] & (1 << ((x)%8))) -#define SETBITLSB(x, line) ((line)[(x)/8] |= (1 << ((x)%8))) - -#define Min(a,b) ((a)<(b)?(a):(b)) -#define Max(a,b) ((a)>(b)?(a):(b)) - -void -FontCharReshape(FontPtr pFont, CharInfoPtr pSrc, CharInfoPtr pDst) -{ - int x, - y; - unsigned char *in_line, - *out_line; - unsigned char *oldglyph, - *newglyph; - int inwidth; - int outwidth, - outheight; - int out_bytes, - in_bytes; - int y_min, - y_max, - x_min, - x_max; - - newglyph = (unsigned char *) pDst->bits; - outwidth = pDst->metrics.rightSideBearing - pDst->metrics.leftSideBearing; - outheight = pDst->metrics.descent + pDst->metrics.ascent; - out_bytes = BYTES_PER_ROW(outwidth, pFont->glyph); - - oldglyph = (unsigned char *) pSrc->bits; - inwidth = pSrc->metrics.rightSideBearing - pSrc->metrics.leftSideBearing; - in_bytes = BYTES_PER_ROW(inwidth, pFont->glyph); - - bzero(newglyph, out_bytes * outheight); - in_line = oldglyph; - out_line = newglyph; - y_min = Max(-pSrc->metrics.ascent, -pDst->metrics.ascent); - y_max = Min(pSrc->metrics.descent, pDst->metrics.descent); - x_min = Max(pSrc->metrics.leftSideBearing, pDst->metrics.leftSideBearing); - x_max = Min(pSrc->metrics.rightSideBearing, pDst->metrics.rightSideBearing); - in_line += (y_min + pSrc->metrics.ascent) * in_bytes; - out_line += (y_min + pDst->metrics.ascent) * out_bytes; - if (pFont->bit == MSBFirst) { - for (y = y_min; y < y_max; y++) { - for (x = x_min; x < x_max; x++) { - if (ISBITONMSB(x - pSrc->metrics.leftSideBearing, in_line)) - SETBITMSB(x - pDst->metrics.leftSideBearing, out_line); - } - in_line += in_bytes; - out_line += out_bytes; - } - } else { - for (y = y_min; y < y_max; y++) { - for (x = x_min; x < x_max; x++) { - if (ISBITONLSB(x - pSrc->metrics.leftSideBearing, in_line)) - SETBITLSB(x - pDst->metrics.leftSideBearing, out_line); - } - in_line += in_bytes; - out_line += out_bytes; - } - } -} +/*
+
+Copyright 1990, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <X11/fonts/fntfilst.h>
+#include <X11/fonts/bitmap.h>
+#include <X11/fonts/bdfint.h>
+
+static unsigned char ink_mask_msb[8] = {
+ 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
+};
+
+static unsigned char ink_mask_lsb[8] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+};
+
+void
+FontCharInkMetrics(FontPtr pFont, CharInfoPtr pCI, xCharInfo *pInk)
+{
+ int leftBearing,
+ ascent,
+ descent;
+ register int vpos,
+ hpos,
+ bpos = 0;
+ int bitmapByteWidth,
+ bitmapByteWidthPadded;
+ int bitmapBitWidth;
+ int span;
+ register unsigned char *p;
+ unsigned char *ink_mask = 0;
+ register int bmax;
+ register unsigned char charbits;
+
+ if (pFont->bit == MSBFirst)
+ ink_mask = ink_mask_msb;
+ else if (pFont->bit == LSBFirst)
+ ink_mask = ink_mask_lsb;
+ pInk->characterWidth = pCI->metrics.characterWidth;
+ pInk->attributes = pCI->metrics.attributes;
+
+ leftBearing = pCI->metrics.leftSideBearing;
+ ascent = pCI->metrics.ascent;
+ descent = pCI->metrics.descent;
+ bitmapBitWidth = GLYPHWIDTHPIXELS(pCI);
+ bitmapByteWidth = GLYPHWIDTHBYTES(pCI);
+ bitmapByteWidthPadded = BYTES_PER_ROW(bitmapBitWidth, pFont->glyph);
+ span = bitmapByteWidthPadded - bitmapByteWidth;
+
+ p = (unsigned char *) pCI->bits;
+ for (vpos = descent + ascent; --vpos >= 0;) {
+ for (hpos = bitmapByteWidth; --hpos >= 0;) {
+ if (*p++ != 0)
+ goto found_ascent;
+ }
+ p += span;
+ }
+ /*
+ * special case -- font with no bits gets all zeros
+ */
+ pInk->leftSideBearing = leftBearing;
+ pInk->rightSideBearing = leftBearing;
+ pInk->ascent = 0;
+ pInk->descent = 0;
+ return;
+found_ascent:
+ pInk->ascent = vpos - descent + 1;
+
+ p = ((unsigned char *) pCI->bits) + bitmapByteWidthPadded *
+ (descent + ascent - 1) + bitmapByteWidth;
+
+ for (vpos = descent + ascent; --vpos >= 0;) {
+ for (hpos = bitmapByteWidth; --hpos >= 0;) {
+ if (*--p != 0)
+ goto found_descent;
+ }
+ p -= span;
+ }
+found_descent:
+ pInk->descent = vpos - ascent + 1;
+
+ bmax = 8;
+ for (hpos = 0; hpos < bitmapByteWidth; hpos++) {
+ charbits = 0;
+ p = (unsigned char *) pCI->bits + hpos;
+ for (vpos = descent + ascent; --vpos >= 0; p += bitmapByteWidthPadded)
+ charbits |= *p;
+ if (charbits) {
+ if (hpos == bitmapByteWidth - 1)
+ bmax = bitmapBitWidth - (hpos << 3);
+ p = ink_mask;
+ for (bpos = bmax; --bpos >= 0;) {
+ if (charbits & *p++)
+ goto found_left;
+ }
+ }
+ }
+found_left:
+ pInk->leftSideBearing = leftBearing + (hpos << 3) + bmax - bpos - 1;
+
+ bmax = bitmapBitWidth - ((bitmapByteWidth - 1) << 3);
+ for (hpos = bitmapByteWidth; --hpos >= 0;) {
+ charbits = 0;
+ p = (unsigned char *) pCI->bits + hpos;
+ for (vpos = descent + ascent; --vpos >= 0; p += bitmapByteWidthPadded)
+ charbits |= *p;
+ if (charbits) {
+ p = ink_mask + bmax;
+ for (bpos = bmax; --bpos >= 0;) {
+ if (charbits & *--p)
+ goto found_right;
+ }
+ }
+ bmax = 8;
+ }
+found_right:
+ pInk->rightSideBearing = leftBearing + (hpos << 3) + bpos + 1;
+}
+
+#define ISBITONMSB(x, line) ((line)[(x)/8] & (1 << (7-((x)%8))))
+#define SETBITMSB(x, line) ((line)[(x)/8] |= (1 << (7-((x)%8))))
+#define ISBITONLSB(x, line) ((line)[(x)/8] & (1 << ((x)%8)))
+#define SETBITLSB(x, line) ((line)[(x)/8] |= (1 << ((x)%8)))
+
+#define Min(a,b) ((a)<(b)?(a):(b))
+#define Max(a,b) ((a)>(b)?(a):(b))
+
+void
+FontCharReshape(FontPtr pFont, CharInfoPtr pSrc, CharInfoPtr pDst)
+{
+ int x,
+ y;
+ unsigned char *in_line,
+ *out_line;
+ unsigned char *oldglyph,
+ *newglyph;
+ int inwidth;
+ int outwidth,
+ outheight;
+ int out_bytes,
+ in_bytes;
+ int y_min,
+ y_max,
+ x_min,
+ x_max;
+
+ newglyph = (unsigned char *) pDst->bits;
+ outwidth = pDst->metrics.rightSideBearing - pDst->metrics.leftSideBearing;
+ outheight = pDst->metrics.descent + pDst->metrics.ascent;
+ out_bytes = BYTES_PER_ROW(outwidth, pFont->glyph);
+
+ oldglyph = (unsigned char *) pSrc->bits;
+ inwidth = pSrc->metrics.rightSideBearing - pSrc->metrics.leftSideBearing;
+ in_bytes = BYTES_PER_ROW(inwidth, pFont->glyph);
+
+ bzero(newglyph, out_bytes * outheight);
+ in_line = oldglyph;
+ out_line = newglyph;
+ y_min = Max(-pSrc->metrics.ascent, -pDst->metrics.ascent);
+ y_max = Min(pSrc->metrics.descent, pDst->metrics.descent);
+ x_min = Max(pSrc->metrics.leftSideBearing, pDst->metrics.leftSideBearing);
+ x_max = Min(pSrc->metrics.rightSideBearing, pDst->metrics.rightSideBearing);
+ in_line += (y_min + pSrc->metrics.ascent) * in_bytes;
+ out_line += (y_min + pDst->metrics.ascent) * out_bytes;
+ if (pFont->bit == MSBFirst) {
+ for (y = y_min; y < y_max; y++) {
+ for (x = x_min; x < x_max; x++) {
+ if (ISBITONMSB(x - pSrc->metrics.leftSideBearing, in_line))
+ SETBITMSB(x - pDst->metrics.leftSideBearing, out_line);
+ }
+ in_line += in_bytes;
+ out_line += out_bytes;
+ }
+ } else {
+ for (y = y_min; y < y_max; y++) {
+ for (x = x_min; x < x_max; x++) {
+ if (ISBITONLSB(x - pSrc->metrics.leftSideBearing, in_line))
+ SETBITLSB(x - pDst->metrics.leftSideBearing, out_line);
+ }
+ in_line += in_bytes;
+ out_line += out_bytes;
+ }
+ }
+}
diff --git a/libXfont/src/bitmap/makefile b/libXfont/src/bitmap/makefile new file mode 100644 index 000000000..f7ea10fdc --- /dev/null +++ b/libXfont/src/bitmap/makefile @@ -0,0 +1,16 @@ +LIBRARY = libbitmap + +CSRCS = \ + bdfread.c \ + bdfutils.c \ + bitmap.c \ + bitmapfunc.c \ + bitmaputil.c \ + bitscale.c \ + fontink.c \ + pcfread.c \ + pcfwrite.c \ + snfread.c + +INCLUDES := ../.. $(INCLUDES) + diff --git a/libXfont/src/bitmap/pcfread.c b/libXfont/src/bitmap/pcfread.c index 32f9856fa..759319e94 100644 --- a/libXfont/src/bitmap/pcfread.c +++ b/libXfont/src/bitmap/pcfread.c @@ -1,780 +1,780 @@ -/* - -Copyright 1990, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <X11/fonts/fntfilst.h> -#include <X11/fonts/bitmap.h> -#include <X11/fonts/pcf.h> - -#ifndef MAX -#define MAX(a,b) (((a)>(b)) ? a : b) -#endif - -#include <stdarg.h> -#include <stdint.h> - -void -pcfError(const char* message, ...) -{ - va_list args; - - va_start(args, message); - - fprintf(stderr, "PCF Error: "); - vfprintf(stderr, message, args); - va_end(args); -} - -/* Read PCF font files */ - -static void pcfUnloadFont ( FontPtr pFont ); -static int position; - - -#define IS_EOF(file) ((file)->eof == BUFFILEEOF) - -#define FONT_FILE_GETC_ERR(f) (tmp = FontFileGetc(f), BAIL_ON_EOF) - -static int -pcfGetLSB32(FontFilePtr file) -{ - int c; - - c = FontFileGetc(file); - c |= FontFileGetc(file) << 8; - c |= FontFileGetc(file) << 16; - c |= FontFileGetc(file) << 24; - position += 4; - return c; -} - -static int -pcfGetINT32(FontFilePtr file, CARD32 format) -{ - int c; - - if (PCF_BYTE_ORDER(format) == MSBFirst) { - c = FontFileGetc(file) << 24; - c |= FontFileGetc(file) << 16; - c |= FontFileGetc(file) << 8; - c |= FontFileGetc(file); - } else { - c = FontFileGetc(file); - c |= FontFileGetc(file) << 8; - c |= FontFileGetc(file) << 16; - c |= FontFileGetc(file) << 24; - } - position += 4; - return c; -} - -static int -pcfGetINT16(FontFilePtr file, CARD32 format) -{ - int c; - - if (PCF_BYTE_ORDER(format) == MSBFirst) { - c = FontFileGetc(file) << 8; - c |= FontFileGetc(file); - } else { - c = FontFileGetc(file); - c |= FontFileGetc(file) << 8; - } - position += 2; - return c; -} - -#define pcfGetINT8(file, format) (position++, FontFileGetc(file)) - -static PCFTablePtr -pcfReadTOC(FontFilePtr file, int *countp) -{ - CARD32 version; - PCFTablePtr tables; - int count; - int i; - - position = 0; - version = pcfGetLSB32(file); - if (version != PCF_FILE_VERSION) - return (PCFTablePtr) NULL; - count = pcfGetLSB32(file); - if (IS_EOF(file)) return (PCFTablePtr) NULL; - if (count < 0 || count > INT32_MAX / sizeof(PCFTableRec)) { - pcfError("pcfReadTOC(): invalid file format\n"); - return NULL; - } - tables = malloc(count * sizeof(PCFTableRec)); - if (!tables) { - pcfError("pcfReadTOC(): Couldn't allocate tables (%d*%d)\n", count, sizeof(PCFTableRec)); - return (PCFTablePtr) NULL; - } - for (i = 0; i < count; i++) { - tables[i].type = pcfGetLSB32(file); - tables[i].format = pcfGetLSB32(file); - tables[i].size = pcfGetLSB32(file); - tables[i].offset = pcfGetLSB32(file); - if (IS_EOF(file)) goto Bail; - } - - *countp = count; - return tables; - - Bail: - free(tables); - return (PCFTablePtr) NULL; -} - -/* - * PCF supports two formats for metrics, both the regular - * jumbo size, and 'lite' metrics, which are useful - * for most fonts which have even vaguely reasonable - * metrics - */ - -static Bool -pcfGetMetric(FontFilePtr file, CARD32 format, xCharInfo *metric) -{ - metric->leftSideBearing = pcfGetINT16(file, format); - metric->rightSideBearing = pcfGetINT16(file, format); - metric->characterWidth = pcfGetINT16(file, format); - metric->ascent = pcfGetINT16(file, format); - metric->descent = pcfGetINT16(file, format); - metric->attributes = pcfGetINT16(file, format); - if (IS_EOF(file)) return FALSE; - - return TRUE; -} - -static Bool -pcfGetCompressedMetric(FontFilePtr file, CARD32 format, xCharInfo *metric) -{ - metric->leftSideBearing = pcfGetINT8(file, format) - 0x80; - metric->rightSideBearing = pcfGetINT8(file, format) - 0x80; - metric->characterWidth = pcfGetINT8(file, format) - 0x80; - metric->ascent = pcfGetINT8(file, format) - 0x80; - metric->descent = pcfGetINT8(file, format) - 0x80; - metric->attributes = 0; - if (IS_EOF(file)) return FALSE; - - return TRUE; -} - -/* - * Position the file to the begining of the specified table - * in the font file - */ -static Bool -pcfSeekToType(FontFilePtr file, PCFTablePtr tables, int ntables, - CARD32 type, CARD32 *formatp, CARD32 *sizep) -{ - int i; - - for (i = 0; i < ntables; i++) - if (tables[i].type == type) { - if (position > tables[i].offset) - return FALSE; - if (!FontFileSkip(file, tables[i].offset - position)) - return FALSE; - position = tables[i].offset; - *sizep = tables[i].size; - *formatp = tables[i].format; - return TRUE; - } - return FALSE; -} - -static Bool -pcfHasType (PCFTablePtr tables, int ntables, CARD32 type) -{ - int i; - - for (i = 0; i < ntables; i++) - if (tables[i].type == type) - return TRUE; - return FALSE; -} - -/* - * pcfGetProperties - * - * Reads the font properties from the font file, filling in the FontInfo rec - * supplied. Used by by both ReadFont and ReadFontInfo routines. - */ - -static Bool -pcfGetProperties(FontInfoPtr pFontInfo, FontFilePtr file, - PCFTablePtr tables, int ntables) -{ - FontPropPtr props = 0; - int nprops; - char *isStringProp = 0; - CARD32 format; - int i; - CARD32 size; - int string_size; - char *strings; - - /* font properties */ - - if (!pcfSeekToType(file, tables, ntables, PCF_PROPERTIES, &format, &size)) - goto Bail; - format = pcfGetLSB32(file); - if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) - goto Bail; - nprops = pcfGetINT32(file, format); - if (nprops <= 0 || nprops > INT32_MAX / sizeof(FontPropRec)) { - pcfError("pcfGetProperties(): invalid nprops value (%d)\n", nprops); - goto Bail; - } - if (IS_EOF(file)) goto Bail; - props = malloc(nprops * sizeof(FontPropRec)); - if (!props) { - pcfError("pcfGetProperties(): Couldn't allocate props (%d*%d)\n", nprops, sizeof(FontPropRec)); - goto Bail; - } - isStringProp = malloc(nprops * sizeof(char)); - if (!isStringProp) { - pcfError("pcfGetProperties(): Couldn't allocate isStringProp (%d*%d)\n", nprops, sizeof(char)); - goto Bail; - } - for (i = 0; i < nprops; i++) { - props[i].name = pcfGetINT32(file, format); - isStringProp[i] = pcfGetINT8(file, format); - props[i].value = pcfGetINT32(file, format); - if (props[i].name < 0 - || (isStringProp[i] != 0 && isStringProp[i] != 1) - || (isStringProp[i] && props[i].value < 0)) { - pcfError("pcfGetProperties(): invalid file format %d %d %d\n", - props[i].name, isStringProp[i], props[i].value); - goto Bail; - } - if (IS_EOF(file)) goto Bail; - } - /* pad the property array */ - /* - * clever here - nprops is the same as the number of odd-units read, as - * only isStringProp are odd length - */ - if (nprops & 3) - { - i = 4 - (nprops & 3); - (void)FontFileSkip(file, i); - position += i; - } - if (IS_EOF(file)) goto Bail; - string_size = pcfGetINT32(file, format); - if (string_size < 0) goto Bail; - if (IS_EOF(file)) goto Bail; - strings = malloc(string_size); - if (!strings) { - pcfError("pcfGetProperties(): Couldn't allocate strings (%d)\n", string_size); - goto Bail; - } - FontFileRead(file, strings, string_size); - if (IS_EOF(file)) goto Bail; - position += string_size; - for (i = 0; i < nprops; i++) { - props[i].name = MakeAtom(strings + props[i].name, - strlen(strings + props[i].name), TRUE); - if (isStringProp[i]) { - props[i].value = MakeAtom(strings + props[i].value, - strlen(strings + props[i].value), TRUE); - } - } - free(strings); - pFontInfo->isStringProp = isStringProp; - pFontInfo->props = props; - pFontInfo->nprops = nprops; - return TRUE; -Bail: - free(isStringProp); - free(props); - return FALSE; -} - - -/* - * pcfReadAccel - * - * Fill in the accelerator information from the font file; used - * to read both BDF_ACCELERATORS and old style ACCELERATORS - */ - -static Bool -pcfGetAccel(FontInfoPtr pFontInfo, FontFilePtr file, - PCFTablePtr tables, int ntables, CARD32 type) -{ - CARD32 format; - CARD32 size; - - if (!pcfSeekToType(file, tables, ntables, type, &format, &size) || - IS_EOF(file)) - goto Bail; - format = pcfGetLSB32(file); - if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && - !PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) - { - goto Bail; - } - pFontInfo->noOverlap = pcfGetINT8(file, format); - pFontInfo->constantMetrics = pcfGetINT8(file, format); - pFontInfo->terminalFont = pcfGetINT8(file, format); - pFontInfo->constantWidth = pcfGetINT8(file, format); - pFontInfo->inkInside = pcfGetINT8(file, format); - pFontInfo->inkMetrics = pcfGetINT8(file, format); - pFontInfo->drawDirection = pcfGetINT8(file, format); - pFontInfo->anamorphic = FALSE; - pFontInfo->cachable = TRUE; - /* natural alignment */ pcfGetINT8(file, format); - pFontInfo->fontAscent = pcfGetINT32(file, format); - pFontInfo->fontDescent = pcfGetINT32(file, format); - pFontInfo->maxOverlap = pcfGetINT32(file, format); - if (IS_EOF(file)) goto Bail; - if (!pcfGetMetric(file, format, &pFontInfo->minbounds)) - goto Bail; - if (!pcfGetMetric(file, format, &pFontInfo->maxbounds)) - goto Bail; - if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) { - if (!pcfGetMetric(file, format, &pFontInfo->ink_minbounds)) - goto Bail; - if (!pcfGetMetric(file, format, &pFontInfo->ink_maxbounds)) - goto Bail; - } else { - pFontInfo->ink_minbounds = pFontInfo->minbounds; - pFontInfo->ink_maxbounds = pFontInfo->maxbounds; - } - return TRUE; -Bail: - return FALSE; -} - -int -pcfReadFont(FontPtr pFont, FontFilePtr file, - int bit, int byte, int glyph, int scan) -{ - CARD32 format; - CARD32 size; - BitmapFontPtr bitmapFont = 0; - int i; - PCFTablePtr tables = 0; - int ntables; - int nmetrics; - int nbitmaps; - int sizebitmaps; - int nink_metrics; - CharInfoPtr metrics = 0; - xCharInfo *ink_metrics = 0; - char *bitmaps = 0; - CharInfoPtr **encoding = 0; - int nencoding = 0; - int encodingOffset; - CARD32 bitmapSizes[GLYPHPADOPTIONS]; - CARD32 *offsets = 0; - Bool hasBDFAccelerators; - - pFont->info.nprops = 0; - pFont->info.props = 0; - if (!(tables = pcfReadTOC(file, &ntables))) - goto Bail; - - /* properties */ - - if (!pcfGetProperties(&pFont->info, file, tables, ntables)) - goto Bail; - - /* Use the old accelerators if no BDF accelerators are in the file */ - - hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS); - if (!hasBDFAccelerators) - if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_ACCELERATORS)) - goto Bail; - - /* metrics */ - - if (!pcfSeekToType(file, tables, ntables, PCF_METRICS, &format, &size)) { - goto Bail; - } - format = pcfGetLSB32(file); - if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && - !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) { - goto Bail; - } - if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) - nmetrics = pcfGetINT32(file, format); - else - nmetrics = pcfGetINT16(file, format); - if (IS_EOF(file)) goto Bail; - if (nmetrics < 0 || nmetrics > INT32_MAX / sizeof(CharInfoRec)) { - pcfError("pcfReadFont(): invalid file format\n"); - goto Bail; - } - metrics = malloc(nmetrics * sizeof(CharInfoRec)); - if (!metrics) { - pcfError("pcfReadFont(): Couldn't allocate metrics (%d*%d)\n", nmetrics, sizeof(CharInfoRec)); - goto Bail; - } - for (i = 0; i < nmetrics; i++) - if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) { - if (!pcfGetMetric(file, format, &(metrics + i)->metrics)) - goto Bail; - } else { - if (!pcfGetCompressedMetric(file, format, &(metrics + i)->metrics)) - goto Bail; - } - - /* bitmaps */ - - if (!pcfSeekToType(file, tables, ntables, PCF_BITMAPS, &format, &size)) - goto Bail; - format = pcfGetLSB32(file); - if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) - goto Bail; - - nbitmaps = pcfGetINT32(file, format); - if (nbitmaps != nmetrics || IS_EOF(file)) - goto Bail; - /* nmetrics is already ok, so nbitmap also is */ - offsets = malloc(nbitmaps * sizeof(CARD32)); - if (!offsets) { - pcfError("pcfReadFont(): Couldn't allocate offsets (%d*%d)\n", nbitmaps, sizeof(CARD32)); - goto Bail; - } - for (i = 0; i < nbitmaps; i++) { - offsets[i] = pcfGetINT32(file, format); - if (IS_EOF(file)) goto Bail; - } - - for (i = 0; i < GLYPHPADOPTIONS; i++) { - bitmapSizes[i] = pcfGetINT32(file, format); - if (IS_EOF(file)) goto Bail; - if (bitmapSizes[i] < 0) goto Bail; - } - - sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX(format)]; - /* guard against completely empty font */ - bitmaps = malloc(sizebitmaps ? sizebitmaps : 1); - if (!bitmaps) { - pcfError("pcfReadFont(): Couldn't allocate bitmaps (%d)\n", sizebitmaps ? sizebitmaps : 1); - goto Bail; - } - FontFileRead(file, bitmaps, sizebitmaps); - if (IS_EOF(file)) goto Bail; - position += sizebitmaps; - - if (PCF_BIT_ORDER(format) != bit) - BitOrderInvert((unsigned char *)bitmaps, sizebitmaps); - if ((PCF_BYTE_ORDER(format) == PCF_BIT_ORDER(format)) != (bit == byte)) { - switch (bit == byte ? PCF_SCAN_UNIT(format) : scan) { - case 1: - break; - case 2: - TwoByteSwap((unsigned char *)bitmaps, sizebitmaps); - break; - case 4: - FourByteSwap((unsigned char *)bitmaps, sizebitmaps); - break; - } - } - if (PCF_GLYPH_PAD(format) != glyph) { - char *padbitmaps; - int sizepadbitmaps; - int old, - new; - xCharInfo *metric; - - sizepadbitmaps = bitmapSizes[PCF_SIZE_TO_INDEX(glyph)]; - padbitmaps = malloc(sizepadbitmaps); - if (!padbitmaps) { - pcfError("pcfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps); - goto Bail; - } - new = 0; - for (i = 0; i < nbitmaps; i++) { - old = offsets[i]; - metric = &metrics[i].metrics; - offsets[i] = new; - new += RepadBitmap(bitmaps + old, padbitmaps + new, - PCF_GLYPH_PAD(format), glyph, - metric->rightSideBearing - metric->leftSideBearing, - metric->ascent + metric->descent); - } - free(bitmaps); - bitmaps = padbitmaps; - } - for (i = 0; i < nbitmaps; i++) - metrics[i].bits = bitmaps + offsets[i]; - - free(offsets); - offsets = NULL; - - /* ink metrics ? */ - - ink_metrics = NULL; - if (pcfSeekToType(file, tables, ntables, PCF_INK_METRICS, &format, &size)) { - format = pcfGetLSB32(file); - if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) && - !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) { - goto Bail; - } - if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) - nink_metrics = pcfGetINT32(file, format); - else - nink_metrics = pcfGetINT16(file, format); - if (IS_EOF(file)) goto Bail; - if (nink_metrics != nmetrics) - goto Bail; - /* nmetrics already checked */ - ink_metrics = malloc(nink_metrics * sizeof(xCharInfo)); - if (!ink_metrics) { - pcfError("pcfReadFont(): Couldn't allocate ink_metrics (%d*%d)\n", nink_metrics, sizeof(xCharInfo)); - goto Bail; - } - for (i = 0; i < nink_metrics; i++) - if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) { - if (!pcfGetMetric(file, format, ink_metrics + i)) - goto Bail; - } else { - if (!pcfGetCompressedMetric(file, format, ink_metrics + i)) - goto Bail; - } - } - - /* encoding */ - - if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size)) - goto Bail; - format = pcfGetLSB32(file); - if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) - goto Bail; - - pFont->info.firstCol = pcfGetINT16(file, format); - pFont->info.lastCol = pcfGetINT16(file, format); - pFont->info.firstRow = pcfGetINT16(file, format); - pFont->info.lastRow = pcfGetINT16(file, format); - pFont->info.defaultCh = pcfGetINT16(file, format); - if (IS_EOF(file)) goto Bail; - if (pFont->info.firstCol > pFont->info.lastCol || - pFont->info.firstRow > pFont->info.lastRow || - pFont->info.lastCol-pFont->info.firstCol > 255) goto Bail; - - nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * - (pFont->info.lastRow - pFont->info.firstRow + 1); - - encoding = calloc(NUM_SEGMENTS(nencoding), sizeof(CharInfoPtr*)); - if (!encoding) { - pcfError("pcfReadFont(): Couldn't allocate encoding (%d*%d)\n", nencoding, sizeof(CharInfoPtr)); - goto Bail; - } - - pFont->info.allExist = TRUE; - for (i = 0; i < nencoding; i++) { - encodingOffset = pcfGetINT16(file, format); - if (IS_EOF(file)) goto Bail; - if (encodingOffset == 0xFFFF) { - pFont->info.allExist = FALSE; - } else { - if(!encoding[SEGMENT_MAJOR(i)]) { - encoding[SEGMENT_MAJOR(i)]= - calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr)); - if(!encoding[SEGMENT_MAJOR(i)]) - goto Bail; - } - ACCESSENCODINGL(encoding, i) = metrics + encodingOffset; - } - } - - /* BDF style accelerators (i.e. bounds based on encoded glyphs) */ - - if (hasBDFAccelerators) - if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_BDF_ACCELERATORS)) - goto Bail; - - bitmapFont = malloc(sizeof *bitmapFont); - if (!bitmapFont) { - pcfError("pcfReadFont(): Couldn't allocate bitmapFont (%d)\n", sizeof *bitmapFont); - goto Bail; - } - - bitmapFont->version_num = PCF_FILE_VERSION; - bitmapFont->num_chars = nmetrics; - bitmapFont->num_tables = ntables; - bitmapFont->metrics = metrics; - bitmapFont->ink_metrics = ink_metrics; - bitmapFont->bitmaps = bitmaps; - bitmapFont->encoding = encoding; - bitmapFont->pDefault = (CharInfoPtr) 0; - if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) { - unsigned int r, - c, - cols; - - r = pFont->info.defaultCh >> 8; - c = pFont->info.defaultCh & 0xFF; - if (pFont->info.firstRow <= r && r <= pFont->info.lastRow && - pFont->info.firstCol <= c && c <= pFont->info.lastCol) { - cols = pFont->info.lastCol - pFont->info.firstCol + 1; - r = r - pFont->info.firstRow; - c = c - pFont->info.firstCol; - bitmapFont->pDefault = ACCESSENCODING(encoding, r * cols + c); - } - } - bitmapFont->bitmapExtra = (BitmapExtraPtr) 0; - pFont->fontPrivate = (pointer) bitmapFont; - pFont->get_glyphs = bitmapGetGlyphs; - pFont->get_metrics = bitmapGetMetrics; - pFont->unload_font = pcfUnloadFont; - pFont->unload_glyphs = NULL; - pFont->bit = bit; - pFont->byte = byte; - pFont->glyph = glyph; - pFont->scan = scan; - free(tables); - return Successful; -Bail: - free(ink_metrics); - if(encoding) { - for(i=0; i<NUM_SEGMENTS(nencoding); i++) - free(encoding[i]); - } - free(encoding); - free(bitmaps); - free(metrics); - free(pFont->info.props); - pFont->info.nprops = 0; - pFont->info.props = 0; - free (pFont->info.isStringProp); - free(bitmapFont); - free(tables); - free(offsets); - return AllocError; -} - -int -pcfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file) -{ - PCFTablePtr tables; - int ntables; - CARD32 format; - CARD32 size; - int nencoding; - Bool hasBDFAccelerators; - - pFontInfo->isStringProp = NULL; - pFontInfo->props = NULL; - pFontInfo->nprops = 0; - - if (!(tables = pcfReadTOC(file, &ntables))) - goto Bail; - - /* properties */ - - if (!pcfGetProperties(pFontInfo, file, tables, ntables)) - goto Bail; - - /* Use the old accelerators if no BDF accelerators are in the file */ - - hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS); - if (!hasBDFAccelerators) - if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_ACCELERATORS)) - goto Bail; - - /* encoding */ - - if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size)) - goto Bail; - format = pcfGetLSB32(file); - if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) - goto Bail; - - pFontInfo->firstCol = pcfGetINT16(file, format); - pFontInfo->lastCol = pcfGetINT16(file, format); - pFontInfo->firstRow = pcfGetINT16(file, format); - pFontInfo->lastRow = pcfGetINT16(file, format); - pFontInfo->defaultCh = pcfGetINT16(file, format); - if (IS_EOF(file)) goto Bail; - if (pFontInfo->firstCol > pFontInfo->lastCol || - pFontInfo->firstRow > pFontInfo->lastRow || - pFontInfo->lastCol-pFontInfo->firstCol > 255) goto Bail; - - nencoding = (pFontInfo->lastCol - pFontInfo->firstCol + 1) * - (pFontInfo->lastRow - pFontInfo->firstRow + 1); - - pFontInfo->allExist = TRUE; - while (nencoding--) { - if (pcfGetINT16(file, format) == 0xFFFF) - pFontInfo->allExist = FALSE; - if (IS_EOF(file)) goto Bail; - } - if (IS_EOF(file)) goto Bail; - - /* BDF style accelerators (i.e. bounds based on encoded glyphs) */ - - if (hasBDFAccelerators) - if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_BDF_ACCELERATORS)) - goto Bail; - - free(tables); - return Successful; -Bail: - pFontInfo->nprops = 0; - free (pFontInfo->props); - free (pFontInfo->isStringProp); - free(tables); - return AllocError; -} - -static void -pcfUnloadFont(FontPtr pFont) -{ - BitmapFontPtr bitmapFont; - int i,nencoding; - - bitmapFont = (BitmapFontPtr) pFont->fontPrivate; - free(bitmapFont->ink_metrics); - if(bitmapFont->encoding) { - nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) * - (pFont->info.lastRow - pFont->info.firstRow + 1); - for(i=0; i<NUM_SEGMENTS(nencoding); i++) - free(bitmapFont->encoding[i]); - } - free(bitmapFont->encoding); - free(bitmapFont->bitmaps); - free(bitmapFont->metrics); - free(pFont->info.isStringProp); - free(pFont->info.props); - free(bitmapFont); - DestroyFontRec(pFont); -} +/*
+
+Copyright 1990, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <X11/fonts/fntfilst.h>
+#include <X11/fonts/bitmap.h>
+#include <X11/fonts/pcf.h>
+
+#ifndef MAX
+#define MAX(a,b) (((a)>(b)) ? a : b)
+#endif
+
+#include <stdarg.h>
+#include <stdint.h>
+
+void
+pcfError(const char* message, ...)
+{
+ va_list args;
+
+ va_start(args, message);
+
+ fprintf(stderr, "PCF Error: ");
+ vfprintf(stderr, message, args);
+ va_end(args);
+}
+
+/* Read PCF font files */
+
+static void pcfUnloadFont ( FontPtr pFont );
+static int position;
+
+
+#define IS_EOF(file) ((file)->eof == BUFFILEEOF)
+
+#define FONT_FILE_GETC_ERR(f) (tmp = FontFileGetc(f), BAIL_ON_EOF)
+
+static int
+pcfGetLSB32(FontFilePtr file)
+{
+ int c;
+
+ c = FontFileGetc(file);
+ c |= FontFileGetc(file) << 8;
+ c |= FontFileGetc(file) << 16;
+ c |= FontFileGetc(file) << 24;
+ position += 4;
+ return c;
+}
+
+static int
+pcfGetINT32(FontFilePtr file, CARD32 format)
+{
+ int c;
+
+ if (PCF_BYTE_ORDER(format) == MSBFirst) {
+ c = FontFileGetc(file) << 24;
+ c |= FontFileGetc(file) << 16;
+ c |= FontFileGetc(file) << 8;
+ c |= FontFileGetc(file);
+ } else {
+ c = FontFileGetc(file);
+ c |= FontFileGetc(file) << 8;
+ c |= FontFileGetc(file) << 16;
+ c |= FontFileGetc(file) << 24;
+ }
+ position += 4;
+ return c;
+}
+
+static int
+pcfGetINT16(FontFilePtr file, CARD32 format)
+{
+ int c;
+
+ if (PCF_BYTE_ORDER(format) == MSBFirst) {
+ c = FontFileGetc(file) << 8;
+ c |= FontFileGetc(file);
+ } else {
+ c = FontFileGetc(file);
+ c |= FontFileGetc(file) << 8;
+ }
+ position += 2;
+ return c;
+}
+
+#define pcfGetINT8(file, format) (position++, FontFileGetc(file))
+
+static PCFTablePtr
+pcfReadTOC(FontFilePtr file, int *countp)
+{
+ CARD32 version;
+ PCFTablePtr tables;
+ int count;
+ int i;
+
+ position = 0;
+ version = pcfGetLSB32(file);
+ if (version != PCF_FILE_VERSION)
+ return (PCFTablePtr) NULL;
+ count = pcfGetLSB32(file);
+ if (IS_EOF(file)) return (PCFTablePtr) NULL;
+ if (count < 0 || count > INT32_MAX / sizeof(PCFTableRec)) {
+ pcfError("pcfReadTOC(): invalid file format\n");
+ return NULL;
+ }
+ tables = malloc(count * sizeof(PCFTableRec));
+ if (!tables) {
+ pcfError("pcfReadTOC(): Couldn't allocate tables (%d*%d)\n", count, sizeof(PCFTableRec));
+ return (PCFTablePtr) NULL;
+ }
+ for (i = 0; i < count; i++) {
+ tables[i].type = pcfGetLSB32(file);
+ tables[i].format = pcfGetLSB32(file);
+ tables[i].size = pcfGetLSB32(file);
+ tables[i].offset = pcfGetLSB32(file);
+ if (IS_EOF(file)) goto Bail;
+ }
+
+ *countp = count;
+ return tables;
+
+ Bail:
+ free(tables);
+ return (PCFTablePtr) NULL;
+}
+
+/*
+ * PCF supports two formats for metrics, both the regular
+ * jumbo size, and 'lite' metrics, which are useful
+ * for most fonts which have even vaguely reasonable
+ * metrics
+ */
+
+static Bool
+pcfGetMetric(FontFilePtr file, CARD32 format, xCharInfo *metric)
+{
+ metric->leftSideBearing = pcfGetINT16(file, format);
+ metric->rightSideBearing = pcfGetINT16(file, format);
+ metric->characterWidth = pcfGetINT16(file, format);
+ metric->ascent = pcfGetINT16(file, format);
+ metric->descent = pcfGetINT16(file, format);
+ metric->attributes = pcfGetINT16(file, format);
+ if (IS_EOF(file)) return FALSE;
+
+ return TRUE;
+}
+
+static Bool
+pcfGetCompressedMetric(FontFilePtr file, CARD32 format, xCharInfo *metric)
+{
+ metric->leftSideBearing = pcfGetINT8(file, format) - 0x80;
+ metric->rightSideBearing = pcfGetINT8(file, format) - 0x80;
+ metric->characterWidth = pcfGetINT8(file, format) - 0x80;
+ metric->ascent = pcfGetINT8(file, format) - 0x80;
+ metric->descent = pcfGetINT8(file, format) - 0x80;
+ metric->attributes = 0;
+ if (IS_EOF(file)) return FALSE;
+
+ return TRUE;
+}
+
+/*
+ * Position the file to the begining of the specified table
+ * in the font file
+ */
+static Bool
+pcfSeekToType(FontFilePtr file, PCFTablePtr tables, int ntables,
+ CARD32 type, CARD32 *formatp, CARD32 *sizep)
+{
+ int i;
+
+ for (i = 0; i < ntables; i++)
+ if (tables[i].type == type) {
+ if (position > tables[i].offset)
+ return FALSE;
+ if (!FontFileSkip(file, tables[i].offset - position))
+ return FALSE;
+ position = tables[i].offset;
+ *sizep = tables[i].size;
+ *formatp = tables[i].format;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static Bool
+pcfHasType (PCFTablePtr tables, int ntables, CARD32 type)
+{
+ int i;
+
+ for (i = 0; i < ntables; i++)
+ if (tables[i].type == type)
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * pcfGetProperties
+ *
+ * Reads the font properties from the font file, filling in the FontInfo rec
+ * supplied. Used by by both ReadFont and ReadFontInfo routines.
+ */
+
+static Bool
+pcfGetProperties(FontInfoPtr pFontInfo, FontFilePtr file,
+ PCFTablePtr tables, int ntables)
+{
+ FontPropPtr props = 0;
+ int nprops;
+ char *isStringProp = 0;
+ CARD32 format;
+ int i;
+ CARD32 size;
+ int string_size;
+ char *strings;
+
+ /* font properties */
+
+ if (!pcfSeekToType(file, tables, ntables, PCF_PROPERTIES, &format, &size))
+ goto Bail;
+ format = pcfGetLSB32(file);
+ if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
+ goto Bail;
+ nprops = pcfGetINT32(file, format);
+ if (nprops <= 0 || nprops > INT32_MAX / sizeof(FontPropRec)) {
+ pcfError("pcfGetProperties(): invalid nprops value (%d)\n", nprops);
+ goto Bail;
+ }
+ if (IS_EOF(file)) goto Bail;
+ props = malloc(nprops * sizeof(FontPropRec));
+ if (!props) {
+ pcfError("pcfGetProperties(): Couldn't allocate props (%d*%d)\n", nprops, sizeof(FontPropRec));
+ goto Bail;
+ }
+ isStringProp = malloc(nprops * sizeof(char));
+ if (!isStringProp) {
+ pcfError("pcfGetProperties(): Couldn't allocate isStringProp (%d*%d)\n", nprops, sizeof(char));
+ goto Bail;
+ }
+ for (i = 0; i < nprops; i++) {
+ props[i].name = pcfGetINT32(file, format);
+ isStringProp[i] = pcfGetINT8(file, format);
+ props[i].value = pcfGetINT32(file, format);
+ if (props[i].name < 0
+ || (isStringProp[i] != 0 && isStringProp[i] != 1)
+ || (isStringProp[i] && props[i].value < 0)) {
+ pcfError("pcfGetProperties(): invalid file format %d %d %d\n",
+ props[i].name, isStringProp[i], props[i].value);
+ goto Bail;
+ }
+ if (IS_EOF(file)) goto Bail;
+ }
+ /* pad the property array */
+ /*
+ * clever here - nprops is the same as the number of odd-units read, as
+ * only isStringProp are odd length
+ */
+ if (nprops & 3)
+ {
+ i = 4 - (nprops & 3);
+ (void)FontFileSkip(file, i);
+ position += i;
+ }
+ if (IS_EOF(file)) goto Bail;
+ string_size = pcfGetINT32(file, format);
+ if (string_size < 0) goto Bail;
+ if (IS_EOF(file)) goto Bail;
+ strings = malloc(string_size);
+ if (!strings) {
+ pcfError("pcfGetProperties(): Couldn't allocate strings (%d)\n", string_size);
+ goto Bail;
+ }
+ FontFileRead(file, strings, string_size);
+ if (IS_EOF(file)) goto Bail;
+ position += string_size;
+ for (i = 0; i < nprops; i++) {
+ props[i].name = MakeAtom(strings + props[i].name,
+ strlen(strings + props[i].name), TRUE);
+ if (isStringProp[i]) {
+ props[i].value = MakeAtom(strings + props[i].value,
+ strlen(strings + props[i].value), TRUE);
+ }
+ }
+ free(strings);
+ pFontInfo->isStringProp = isStringProp;
+ pFontInfo->props = props;
+ pFontInfo->nprops = nprops;
+ return TRUE;
+Bail:
+ free(isStringProp);
+ free(props);
+ return FALSE;
+}
+
+
+/*
+ * pcfReadAccel
+ *
+ * Fill in the accelerator information from the font file; used
+ * to read both BDF_ACCELERATORS and old style ACCELERATORS
+ */
+
+static Bool
+pcfGetAccel(FontInfoPtr pFontInfo, FontFilePtr file,
+ PCFTablePtr tables, int ntables, CARD32 type)
+{
+ CARD32 format;
+ CARD32 size;
+
+ if (!pcfSeekToType(file, tables, ntables, type, &format, &size) ||
+ IS_EOF(file))
+ goto Bail;
+ format = pcfGetLSB32(file);
+ if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
+ !PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS))
+ {
+ goto Bail;
+ }
+ pFontInfo->noOverlap = pcfGetINT8(file, format);
+ pFontInfo->constantMetrics = pcfGetINT8(file, format);
+ pFontInfo->terminalFont = pcfGetINT8(file, format);
+ pFontInfo->constantWidth = pcfGetINT8(file, format);
+ pFontInfo->inkInside = pcfGetINT8(file, format);
+ pFontInfo->inkMetrics = pcfGetINT8(file, format);
+ pFontInfo->drawDirection = pcfGetINT8(file, format);
+ pFontInfo->anamorphic = FALSE;
+ pFontInfo->cachable = TRUE;
+ /* natural alignment */ pcfGetINT8(file, format);
+ pFontInfo->fontAscent = pcfGetINT32(file, format);
+ pFontInfo->fontDescent = pcfGetINT32(file, format);
+ pFontInfo->maxOverlap = pcfGetINT32(file, format);
+ if (IS_EOF(file)) goto Bail;
+ if (!pcfGetMetric(file, format, &pFontInfo->minbounds))
+ goto Bail;
+ if (!pcfGetMetric(file, format, &pFontInfo->maxbounds))
+ goto Bail;
+ if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) {
+ if (!pcfGetMetric(file, format, &pFontInfo->ink_minbounds))
+ goto Bail;
+ if (!pcfGetMetric(file, format, &pFontInfo->ink_maxbounds))
+ goto Bail;
+ } else {
+ pFontInfo->ink_minbounds = pFontInfo->minbounds;
+ pFontInfo->ink_maxbounds = pFontInfo->maxbounds;
+ }
+ return TRUE;
+Bail:
+ return FALSE;
+}
+
+int
+pcfReadFont(FontPtr pFont, FontFilePtr file,
+ int bit, int byte, int glyph, int scan)
+{
+ CARD32 format;
+ CARD32 size;
+ BitmapFontPtr bitmapFont = 0;
+ int i;
+ PCFTablePtr tables = 0;
+ int ntables;
+ int nmetrics;
+ int nbitmaps;
+ int sizebitmaps;
+ int nink_metrics;
+ CharInfoPtr metrics = 0;
+ xCharInfo *ink_metrics = 0;
+ char *bitmaps = 0;
+ CharInfoPtr **encoding = 0;
+ int nencoding = 0;
+ int encodingOffset;
+ CARD32 bitmapSizes[GLYPHPADOPTIONS];
+ CARD32 *offsets = 0;
+ Bool hasBDFAccelerators;
+
+ pFont->info.nprops = 0;
+ pFont->info.props = 0;
+ if (!(tables = pcfReadTOC(file, &ntables)))
+ goto Bail;
+
+ /* properties */
+
+ if (!pcfGetProperties(&pFont->info, file, tables, ntables))
+ goto Bail;
+
+ /* Use the old accelerators if no BDF accelerators are in the file */
+
+ hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS);
+ if (!hasBDFAccelerators)
+ if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_ACCELERATORS))
+ goto Bail;
+
+ /* metrics */
+
+ if (!pcfSeekToType(file, tables, ntables, PCF_METRICS, &format, &size)) {
+ goto Bail;
+ }
+ format = pcfGetLSB32(file);
+ if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
+ !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) {
+ goto Bail;
+ }
+ if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
+ nmetrics = pcfGetINT32(file, format);
+ else
+ nmetrics = pcfGetINT16(file, format);
+ if (IS_EOF(file)) goto Bail;
+ if (nmetrics < 0 || nmetrics > INT32_MAX / sizeof(CharInfoRec)) {
+ pcfError("pcfReadFont(): invalid file format\n");
+ goto Bail;
+ }
+ metrics = malloc(nmetrics * sizeof(CharInfoRec));
+ if (!metrics) {
+ pcfError("pcfReadFont(): Couldn't allocate metrics (%d*%d)\n", nmetrics, sizeof(CharInfoRec));
+ goto Bail;
+ }
+ for (i = 0; i < nmetrics; i++)
+ if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) {
+ if (!pcfGetMetric(file, format, &(metrics + i)->metrics))
+ goto Bail;
+ } else {
+ if (!pcfGetCompressedMetric(file, format, &(metrics + i)->metrics))
+ goto Bail;
+ }
+
+ /* bitmaps */
+
+ if (!pcfSeekToType(file, tables, ntables, PCF_BITMAPS, &format, &size))
+ goto Bail;
+ format = pcfGetLSB32(file);
+ if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
+ goto Bail;
+
+ nbitmaps = pcfGetINT32(file, format);
+ if (nbitmaps != nmetrics || IS_EOF(file))
+ goto Bail;
+ /* nmetrics is already ok, so nbitmap also is */
+ offsets = malloc(nbitmaps * sizeof(CARD32));
+ if (!offsets) {
+ pcfError("pcfReadFont(): Couldn't allocate offsets (%d*%d)\n", nbitmaps, sizeof(CARD32));
+ goto Bail;
+ }
+ for (i = 0; i < nbitmaps; i++) {
+ offsets[i] = pcfGetINT32(file, format);
+ if (IS_EOF(file)) goto Bail;
+ }
+
+ for (i = 0; i < GLYPHPADOPTIONS; i++) {
+ bitmapSizes[i] = pcfGetINT32(file, format);
+ if (IS_EOF(file)) goto Bail;
+ if (bitmapSizes[i] < 0) goto Bail;
+ }
+
+ sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX(format)];
+ /* guard against completely empty font */
+ bitmaps = malloc(sizebitmaps ? sizebitmaps : 1);
+ if (!bitmaps) {
+ pcfError("pcfReadFont(): Couldn't allocate bitmaps (%d)\n", sizebitmaps ? sizebitmaps : 1);
+ goto Bail;
+ }
+ FontFileRead(file, bitmaps, sizebitmaps);
+ if (IS_EOF(file)) goto Bail;
+ position += sizebitmaps;
+
+ if (PCF_BIT_ORDER(format) != bit)
+ BitOrderInvert((unsigned char *)bitmaps, sizebitmaps);
+ if ((PCF_BYTE_ORDER(format) == PCF_BIT_ORDER(format)) != (bit == byte)) {
+ switch (bit == byte ? PCF_SCAN_UNIT(format) : scan) {
+ case 1:
+ break;
+ case 2:
+ TwoByteSwap((unsigned char *)bitmaps, sizebitmaps);
+ break;
+ case 4:
+ FourByteSwap((unsigned char *)bitmaps, sizebitmaps);
+ break;
+ }
+ }
+ if (PCF_GLYPH_PAD(format) != glyph) {
+ char *padbitmaps;
+ int sizepadbitmaps;
+ int old,
+ new;
+ xCharInfo *metric;
+
+ sizepadbitmaps = bitmapSizes[PCF_SIZE_TO_INDEX(glyph)];
+ padbitmaps = malloc(sizepadbitmaps);
+ if (!padbitmaps) {
+ pcfError("pcfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps);
+ goto Bail;
+ }
+ new = 0;
+ for (i = 0; i < nbitmaps; i++) {
+ old = offsets[i];
+ metric = &metrics[i].metrics;
+ offsets[i] = new;
+ new += RepadBitmap(bitmaps + old, padbitmaps + new,
+ PCF_GLYPH_PAD(format), glyph,
+ metric->rightSideBearing - metric->leftSideBearing,
+ metric->ascent + metric->descent);
+ }
+ free(bitmaps);
+ bitmaps = padbitmaps;
+ }
+ for (i = 0; i < nbitmaps; i++)
+ metrics[i].bits = bitmaps + offsets[i];
+
+ free(offsets);
+ offsets = NULL;
+
+ /* ink metrics ? */
+
+ ink_metrics = NULL;
+ if (pcfSeekToType(file, tables, ntables, PCF_INK_METRICS, &format, &size)) {
+ format = pcfGetLSB32(file);
+ if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
+ !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) {
+ goto Bail;
+ }
+ if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
+ nink_metrics = pcfGetINT32(file, format);
+ else
+ nink_metrics = pcfGetINT16(file, format);
+ if (IS_EOF(file)) goto Bail;
+ if (nink_metrics != nmetrics)
+ goto Bail;
+ /* nmetrics already checked */
+ ink_metrics = malloc(nink_metrics * sizeof(xCharInfo));
+ if (!ink_metrics) {
+ pcfError("pcfReadFont(): Couldn't allocate ink_metrics (%d*%d)\n", nink_metrics, sizeof(xCharInfo));
+ goto Bail;
+ }
+ for (i = 0; i < nink_metrics; i++)
+ if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) {
+ if (!pcfGetMetric(file, format, ink_metrics + i))
+ goto Bail;
+ } else {
+ if (!pcfGetCompressedMetric(file, format, ink_metrics + i))
+ goto Bail;
+ }
+ }
+
+ /* encoding */
+
+ if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size))
+ goto Bail;
+ format = pcfGetLSB32(file);
+ if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
+ goto Bail;
+
+ pFont->info.firstCol = pcfGetINT16(file, format);
+ pFont->info.lastCol = pcfGetINT16(file, format);
+ pFont->info.firstRow = pcfGetINT16(file, format);
+ pFont->info.lastRow = pcfGetINT16(file, format);
+ pFont->info.defaultCh = pcfGetINT16(file, format);
+ if (IS_EOF(file)) goto Bail;
+ if (pFont->info.firstCol > pFont->info.lastCol ||
+ pFont->info.firstRow > pFont->info.lastRow ||
+ pFont->info.lastCol-pFont->info.firstCol > 255) goto Bail;
+
+ nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
+ (pFont->info.lastRow - pFont->info.firstRow + 1);
+
+ encoding = calloc(NUM_SEGMENTS(nencoding), sizeof(CharInfoPtr*));
+ if (!encoding) {
+ pcfError("pcfReadFont(): Couldn't allocate encoding (%d*%d)\n", nencoding, sizeof(CharInfoPtr));
+ goto Bail;
+ }
+
+ pFont->info.allExist = TRUE;
+ for (i = 0; i < nencoding; i++) {
+ encodingOffset = pcfGetINT16(file, format);
+ if (IS_EOF(file)) goto Bail;
+ if (encodingOffset == 0xFFFF) {
+ pFont->info.allExist = FALSE;
+ } else {
+ if(!encoding[SEGMENT_MAJOR(i)]) {
+ encoding[SEGMENT_MAJOR(i)]=
+ calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr));
+ if(!encoding[SEGMENT_MAJOR(i)])
+ goto Bail;
+ }
+ ACCESSENCODINGL(encoding, i) = metrics + encodingOffset;
+ }
+ }
+
+ /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
+
+ if (hasBDFAccelerators)
+ if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_BDF_ACCELERATORS))
+ goto Bail;
+
+ bitmapFont = malloc(sizeof *bitmapFont);
+ if (!bitmapFont) {
+ pcfError("pcfReadFont(): Couldn't allocate bitmapFont (%d)\n", sizeof *bitmapFont);
+ goto Bail;
+ }
+
+ bitmapFont->version_num = PCF_FILE_VERSION;
+ bitmapFont->num_chars = nmetrics;
+ bitmapFont->num_tables = ntables;
+ bitmapFont->metrics = metrics;
+ bitmapFont->ink_metrics = ink_metrics;
+ bitmapFont->bitmaps = bitmaps;
+ bitmapFont->encoding = encoding;
+ bitmapFont->pDefault = (CharInfoPtr) 0;
+ if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) {
+ unsigned int r,
+ c,
+ cols;
+
+ r = pFont->info.defaultCh >> 8;
+ c = pFont->info.defaultCh & 0xFF;
+ if (pFont->info.firstRow <= r && r <= pFont->info.lastRow &&
+ pFont->info.firstCol <= c && c <= pFont->info.lastCol) {
+ cols = pFont->info.lastCol - pFont->info.firstCol + 1;
+ r = r - pFont->info.firstRow;
+ c = c - pFont->info.firstCol;
+ bitmapFont->pDefault = ACCESSENCODING(encoding, r * cols + c);
+ }
+ }
+ bitmapFont->bitmapExtra = (BitmapExtraPtr) 0;
+ pFont->fontPrivate = (pointer) bitmapFont;
+ pFont->get_glyphs = bitmapGetGlyphs;
+ pFont->get_metrics = bitmapGetMetrics;
+ pFont->unload_font = pcfUnloadFont;
+ pFont->unload_glyphs = NULL;
+ pFont->bit = bit;
+ pFont->byte = byte;
+ pFont->glyph = glyph;
+ pFont->scan = scan;
+ free(tables);
+ return Successful;
+Bail:
+ free(ink_metrics);
+ if(encoding) {
+ for(i=0; i<NUM_SEGMENTS(nencoding); i++)
+ free(encoding[i]);
+ }
+ free(encoding);
+ free(bitmaps);
+ free(metrics);
+ free(pFont->info.props);
+ pFont->info.nprops = 0;
+ pFont->info.props = 0;
+ free (pFont->info.isStringProp);
+ free(bitmapFont);
+ free(tables);
+ free(offsets);
+ return AllocError;
+}
+
+int
+pcfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file)
+{
+ PCFTablePtr tables;
+ int ntables;
+ CARD32 format;
+ CARD32 size;
+ int nencoding;
+ Bool hasBDFAccelerators;
+
+ pFontInfo->isStringProp = NULL;
+ pFontInfo->props = NULL;
+ pFontInfo->nprops = 0;
+
+ if (!(tables = pcfReadTOC(file, &ntables)))
+ goto Bail;
+
+ /* properties */
+
+ if (!pcfGetProperties(pFontInfo, file, tables, ntables))
+ goto Bail;
+
+ /* Use the old accelerators if no BDF accelerators are in the file */
+
+ hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS);
+ if (!hasBDFAccelerators)
+ if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_ACCELERATORS))
+ goto Bail;
+
+ /* encoding */
+
+ if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size))
+ goto Bail;
+ format = pcfGetLSB32(file);
+ if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
+ goto Bail;
+
+ pFontInfo->firstCol = pcfGetINT16(file, format);
+ pFontInfo->lastCol = pcfGetINT16(file, format);
+ pFontInfo->firstRow = pcfGetINT16(file, format);
+ pFontInfo->lastRow = pcfGetINT16(file, format);
+ pFontInfo->defaultCh = pcfGetINT16(file, format);
+ if (IS_EOF(file)) goto Bail;
+ if (pFontInfo->firstCol > pFontInfo->lastCol ||
+ pFontInfo->firstRow > pFontInfo->lastRow ||
+ pFontInfo->lastCol-pFontInfo->firstCol > 255) goto Bail;
+
+ nencoding = (pFontInfo->lastCol - pFontInfo->firstCol + 1) *
+ (pFontInfo->lastRow - pFontInfo->firstRow + 1);
+
+ pFontInfo->allExist = TRUE;
+ while (nencoding--) {
+ if (pcfGetINT16(file, format) == 0xFFFF)
+ pFontInfo->allExist = FALSE;
+ if (IS_EOF(file)) goto Bail;
+ }
+ if (IS_EOF(file)) goto Bail;
+
+ /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
+
+ if (hasBDFAccelerators)
+ if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_BDF_ACCELERATORS))
+ goto Bail;
+
+ free(tables);
+ return Successful;
+Bail:
+ pFontInfo->nprops = 0;
+ free (pFontInfo->props);
+ free (pFontInfo->isStringProp);
+ free(tables);
+ return AllocError;
+}
+
+static void
+pcfUnloadFont(FontPtr pFont)
+{
+ BitmapFontPtr bitmapFont;
+ int i,nencoding;
+
+ bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
+ free(bitmapFont->ink_metrics);
+ if(bitmapFont->encoding) {
+ nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
+ (pFont->info.lastRow - pFont->info.firstRow + 1);
+ for(i=0; i<NUM_SEGMENTS(nencoding); i++)
+ free(bitmapFont->encoding[i]);
+ }
+ free(bitmapFont->encoding);
+ free(bitmapFont->bitmaps);
+ free(bitmapFont->metrics);
+ free(pFont->info.isStringProp);
+ free(pFont->info.props);
+ free(bitmapFont);
+ DestroyFontRec(pFont);
+}
diff --git a/libXfont/src/bitmap/pcfwrite.c b/libXfont/src/bitmap/pcfwrite.c index 3ac07b359..4c0771e2a 100644 --- a/libXfont/src/bitmap/pcfwrite.c +++ b/libXfont/src/bitmap/pcfwrite.c @@ -1,466 +1,466 @@ -/* - -Copyright 1990, 1994, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <X11/fonts/fntfilst.h> -#include <X11/fonts/bitmap.h> -#include <X11/fonts/pcf.h> - -/* Write PCF font files */ - -static CARD32 current_position; - -static int -pcfWrite(FontFilePtr file, char *b, int c) -{ - current_position += c; - return FontFileWrite(file, b, c); -} - -static int -pcfPutLSB32(FontFilePtr file, int c) -{ - current_position += 4; - (void) FontFilePutc(c, file); - (void) FontFilePutc(c >> 8, file); - (void) FontFilePutc(c >> 16, file); - return FontFilePutc(c >> 24, file); -} - -static int -pcfPutINT32(FontFilePtr file, CARD32 format, int c) -{ - current_position += 4; - if (PCF_BYTE_ORDER(format) == MSBFirst) { - (void) FontFilePutc(c >> 24, file); - (void) FontFilePutc(c >> 16, file); - (void) FontFilePutc(c >> 8, file); - return FontFilePutc(c, file); - } else { - (void) FontFilePutc(c, file); - (void) FontFilePutc(c >> 8, file); - (void) FontFilePutc(c >> 16, file); - return FontFilePutc(c >> 24, file); - } -} - -static int -pcfPutINT16(FontFilePtr file, CARD32 format, int c) -{ - current_position += 2; - if (PCF_BYTE_ORDER(format) == MSBFirst) { - (void) FontFilePutc(c >> 8, file); - return FontFilePutc(c, file); - } else { - (void) FontFilePutc(c, file); - return FontFilePutc(c >> 8, file); - } -} - -/*ARGSUSED*/ -static int -pcfPutINT8(FontFilePtr file, CARD32 format, int c) -{ - current_position += 1; - return FontFilePutc(c, file); -} - -static void -pcfWriteTOC(FontFilePtr file, PCFTablePtr table, int count) -{ - CARD32 version; - int i; - - version = PCF_FILE_VERSION; - pcfPutLSB32(file, version); - pcfPutLSB32(file, count); - for (i = 0; i < count; i++) { - pcfPutLSB32(file, table->type); - pcfPutLSB32(file, table->format); - pcfPutLSB32(file, table->size); - pcfPutLSB32(file, table->offset); - table++; - } -} - -static void -pcfPutCompressedMetric(FontFilePtr file, CARD32 format, xCharInfo *metric) -{ - pcfPutINT8(file, format, metric->leftSideBearing + 0x80); - pcfPutINT8(file, format, metric->rightSideBearing + 0x80); - pcfPutINT8(file, format, metric->characterWidth + 0x80); - pcfPutINT8(file, format, metric->ascent + 0x80); - pcfPutINT8(file, format, metric->descent + 0x80); -} - -static void -pcfPutMetric(FontFilePtr file, CARD32 format, xCharInfo *metric) -{ - pcfPutINT16(file, format, metric->leftSideBearing); - pcfPutINT16(file, format, metric->rightSideBearing); - pcfPutINT16(file, format, metric->characterWidth); - pcfPutINT16(file, format, metric->ascent); - pcfPutINT16(file, format, metric->descent); - pcfPutINT16(file, format, metric->attributes); -} - -static void -pcfPutBitmap(FontFilePtr file, CARD32 format, CharInfoPtr pCI) -{ - int count; - unsigned char *bits; - - count = BYTES_FOR_GLYPH(pCI, PCF_GLYPH_PAD(format)); - bits = (unsigned char *) pCI->bits; - current_position += count; - while (count--) - FontFilePutc(*bits++, file); -} - -static void -pcfPutAccel(FontFilePtr file, CARD32 format, FontInfoPtr pFontInfo) -{ - pcfPutINT8(file, format, pFontInfo->noOverlap); - pcfPutINT8(file, format, pFontInfo->constantMetrics); - pcfPutINT8(file, format, pFontInfo->terminalFont); - pcfPutINT8(file, format, pFontInfo->constantWidth); - pcfPutINT8(file, format, pFontInfo->inkInside); - pcfPutINT8(file, format, pFontInfo->inkMetrics); - pcfPutINT8(file, format, pFontInfo->drawDirection); - pcfPutINT8(file, format, 0); - pcfPutINT32(file, format, pFontInfo->fontAscent); - pcfPutINT32(file, format, pFontInfo->fontDescent); - pcfPutINT32(file, format, pFontInfo->maxOverlap); - pcfPutMetric(file, format, &pFontInfo->minbounds); - pcfPutMetric(file, format, &pFontInfo->maxbounds); - if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) { - pcfPutMetric(file, format, &pFontInfo->ink_minbounds); - pcfPutMetric(file, format, &pFontInfo->ink_maxbounds); - } -} - -#define S32 4 -#define S16 2 -#define S8 1 - -#define Pad(s) (RoundUp(s) - (s)) -#define RoundUp(s) (((s) + 3) & ~3) - -#define Compressable(i) (-128 <= (i) && (i) <= 127) - -#define CanCompressMetric(m) (Compressable((m)->leftSideBearing) && \ - Compressable((m)->rightSideBearing) && \ - Compressable((m)->characterWidth) && \ - Compressable((m)->ascent) && \ - Compressable((m)->descent) && \ - (m)->attributes == 0) - -#define CanCompressMetrics(min,max) (CanCompressMetric(min) && CanCompressMetric(max)) - -static char * -pcfNameForAtom(Atom a) -{ - return NameForAtom(a); -} - -int -pcfWriteFont(FontPtr pFont, FontFilePtr file) -{ - PCFTableRec tables[32], - *table; - CARD32 mask, - bit; - int ntables; - int size; - CARD32 format; - int i; - int cur_table; - int prop_string_size; - int glyph_string_size; - xCharInfo *minbounds, - *maxbounds; - xCharInfo *ink_minbounds, - *ink_maxbounds; - BitmapFontPtr bitmapFont; - int nencodings = 0; - int header_size; - FontPropPtr offsetProps; - int prop_pad = 0; - char *atom_name; - int glyph; - CARD32 offset; - - bitmapFont = (BitmapFontPtr) pFont->fontPrivate; - if (bitmapFont->bitmapExtra) { - minbounds = &bitmapFont->bitmapExtra->info.minbounds; - maxbounds = &bitmapFont->bitmapExtra->info.maxbounds; - ink_minbounds = &bitmapFont->bitmapExtra->info.ink_minbounds; - ink_maxbounds = &bitmapFont->bitmapExtra->info.ink_maxbounds; - } else { - minbounds = &pFont->info.minbounds; - maxbounds = &pFont->info.maxbounds; - ink_minbounds = &pFont->info.ink_minbounds; - ink_maxbounds = &pFont->info.ink_maxbounds; - } - offsetProps = malloc(pFont->info.nprops * sizeof(FontPropRec)); - if (!offsetProps) { - pcfError("pcfWriteFont(): Couldn't allocate offsetProps (%d*%d)", pFont->info.nprops, sizeof(FontPropRec)); - return AllocError; - } - prop_string_size = 0; - for (i = 0; i < pFont->info.nprops; i++) { - offsetProps[i].name = prop_string_size; - prop_string_size += strlen(pcfNameForAtom(pFont->info.props[i].name)) + 1; - if (pFont->info.isStringProp[i]) { - offsetProps[i].value = prop_string_size; - prop_string_size += strlen(pcfNameForAtom(pFont->info.props[i].value)) + 1; - } else - offsetProps[i].value = pFont->info.props[i].value; - } - format = PCF_FORMAT(pFont->bit, pFont->byte, pFont->glyph, pFont->scan); - mask = 0xFFFFFFF; - ntables = 0; - table = tables; - while (mask) { - bit = lowbit(mask); - mask &= ~bit; - table->type = bit; - switch (bit) { - case PCF_PROPERTIES: - table->format = PCF_DEFAULT_FORMAT | format; - size = S32 + S32 + (S32 + S8 + S32) * pFont->info.nprops; - prop_pad = Pad(size); - table->size = RoundUp(size) + S32 + - RoundUp(prop_string_size); - table++; - break; - case PCF_ACCELERATORS: - if (bitmapFont->bitmapExtra->info.inkMetrics) - table->format = PCF_ACCEL_W_INKBOUNDS | format; - else - table->format = PCF_DEFAULT_FORMAT | format; - table->size = 100; - table++; - break; - case PCF_METRICS: - if (CanCompressMetrics(minbounds, maxbounds)) { - table->format = PCF_COMPRESSED_METRICS | format; - size = S32 + S16 + bitmapFont->num_chars * (5 * S8); - table->size = RoundUp(size); - } else { - table->format = PCF_DEFAULT_FORMAT | format; - table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16); - } - table++; - break; - case PCF_BITMAPS: - table->format = PCF_DEFAULT_FORMAT | format; - size = S32 + S32 + bitmapFont->num_chars * S32 + - GLYPHPADOPTIONS * S32 + - bitmapFont->bitmapExtra->bitmapsSizes[PCF_GLYPH_PAD_INDEX(format)]; - table->size = RoundUp(size); - table++; - break; - case PCF_INK_METRICS: - if (bitmapFont->ink_metrics) { - if (CanCompressMetrics(ink_minbounds, ink_maxbounds)) { - table->format = PCF_COMPRESSED_METRICS | format; - size = S32 + S16 + bitmapFont->num_chars * (5 * S8); - table->size = RoundUp(size); - } else { - table->format = PCF_DEFAULT_FORMAT | format; - table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16); - } - table++; - } - break; - case PCF_BDF_ENCODINGS: - table->format = PCF_DEFAULT_FORMAT | format; - nencodings = (pFont->info.lastRow - pFont->info.firstRow + 1) * - (pFont->info.lastCol - pFont->info.firstCol + 1); - size = S32 + 5 * S16 + nencodings * S16; - table->size = RoundUp(size); - table++; - break; - case PCF_SWIDTHS: - table->format = PCF_DEFAULT_FORMAT | format; - table->size = S32 + S32 + bitmapFont->num_chars * S32; - table++; - break; - case PCF_GLYPH_NAMES: - table->format = PCF_DEFAULT_FORMAT | format; - glyph_string_size = 0; - for (i = 0; i < bitmapFont->num_chars; i++) - glyph_string_size += strlen(pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i])) + 1; - table->size = S32 + S32 + bitmapFont->num_chars * S32 + - S32 + RoundUp(glyph_string_size); - table++; - break; - case PCF_BDF_ACCELERATORS: - if (pFont->info.inkMetrics) - table->format = PCF_ACCEL_W_INKBOUNDS | format; - else - table->format = PCF_DEFAULT_FORMAT | format; - table->size = 100; - table++; - break; - } - } - ntables = table - tables; - offset = 0; - header_size = S32 + S32 + ntables * (4 * S32); - offset = header_size; - for (cur_table = 0, table = tables; - cur_table < ntables; - cur_table++, table++) { - table->offset = offset; - offset += table->size; - } - current_position = 0; - pcfWriteTOC(file, tables, ntables); - for (cur_table = 0, table = tables; - cur_table < ntables; - cur_table++, table++) { - if (current_position > table->offset) { - printf("can't go backwards... %d > %d\n", - (int)current_position, (int)table->offset); - free(offsetProps); - return BadFontName; - } - while (current_position < table->offset) - pcfPutINT8(file, format, '\0'); - pcfPutLSB32(file, table->format); - switch (table->type) { - case PCF_PROPERTIES: - pcfPutINT32(file, format, pFont->info.nprops); - for (i = 0; i < pFont->info.nprops; i++) { - pcfPutINT32(file, format, offsetProps[i].name); - pcfPutINT8(file, format, pFont->info.isStringProp[i]); - pcfPutINT32(file, format, offsetProps[i].value); - } - for (i = 0; i < prop_pad; i++) - pcfPutINT8(file, format, 0); - pcfPutINT32(file, format, prop_string_size); - for (i = 0; i < pFont->info.nprops; i++) { - atom_name = pcfNameForAtom(pFont->info.props[i].name); - pcfWrite(file, atom_name, strlen(atom_name) + 1); - if (pFont->info.isStringProp[i]) { - atom_name = pcfNameForAtom(pFont->info.props[i].value); - pcfWrite(file, atom_name, strlen(atom_name) + 1); - } - } - break; - case PCF_ACCELERATORS: - pcfPutAccel(file, table->format, &bitmapFont->bitmapExtra->info); - break; - case PCF_METRICS: - if (PCF_FORMAT_MATCH(table->format, PCF_COMPRESSED_METRICS)) { - pcfPutINT16(file, format, bitmapFont->num_chars); - for (i = 0; i < bitmapFont->num_chars; i++) - pcfPutCompressedMetric(file, format, &bitmapFont->metrics[i].metrics); - } else { - pcfPutINT32(file, format, bitmapFont->num_chars); - for (i = 0; i < bitmapFont->num_chars; i++) - pcfPutMetric(file, format, &bitmapFont->metrics[i].metrics); - } - break; - case PCF_BITMAPS: - pcfPutINT32(file, format, bitmapFont->num_chars); - glyph = PCF_GLYPH_PAD(format); - offset = 0; - for (i = 0; i < bitmapFont->num_chars; i++) { - pcfPutINT32(file, format, offset); - offset += BYTES_FOR_GLYPH(&bitmapFont->metrics[i], glyph); - } - for (i = 0; i < GLYPHPADOPTIONS; i++) { - pcfPutINT32(file, format, - bitmapFont->bitmapExtra->bitmapsSizes[i]); - } - for (i = 0; i < bitmapFont->num_chars; i++) - pcfPutBitmap(file, format, &bitmapFont->metrics[i]); - break; - case PCF_INK_METRICS: - if (PCF_FORMAT_MATCH(table->format, PCF_COMPRESSED_METRICS)) { - pcfPutINT16(file, format, bitmapFont->num_chars); - for (i = 0; i < bitmapFont->num_chars; i++) - pcfPutCompressedMetric(file, format, &bitmapFont->ink_metrics[i]); - } else { - pcfPutINT32(file, format, bitmapFont->num_chars); - for (i = 0; i < bitmapFont->num_chars; i++) - pcfPutMetric(file, format, &bitmapFont->ink_metrics[i]); - } - break; - case PCF_BDF_ENCODINGS: - pcfPutINT16(file, format, pFont->info.firstCol); - pcfPutINT16(file, format, pFont->info.lastCol); - pcfPutINT16(file, format, pFont->info.firstRow); - pcfPutINT16(file, format, pFont->info.lastRow); - pcfPutINT16(file, format, pFont->info.defaultCh); - for (i = 0; i < nencodings; i++) { - if (ACCESSENCODING(bitmapFont->encoding,i)) - pcfPutINT16(file, format, - ACCESSENCODING(bitmapFont->encoding, i) - - bitmapFont->metrics); - else - pcfPutINT16(file, format, 0xFFFF); - } - break; - case PCF_SWIDTHS: - pcfPutINT32(file, format, bitmapFont->num_chars); - for (i = 0; i < bitmapFont->num_chars; i++) - pcfPutINT32(file, format, bitmapFont->bitmapExtra->sWidths[i]); - break; - case PCF_GLYPH_NAMES: - pcfPutINT32(file, format, bitmapFont->num_chars); - offset = 0; - for (i = 0; i < bitmapFont->num_chars; i++) { - pcfPutINT32(file, format, offset); - offset += strlen(pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i])) + 1; - } - pcfPutINT32(file, format, offset); - for (i = 0; i < bitmapFont->num_chars; i++) { - atom_name = pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i]); - pcfWrite(file, atom_name, strlen(atom_name) + 1); - } - break; - case PCF_BDF_ACCELERATORS: - pcfPutAccel(file, table->format, &pFont->info); - break; - } - } - - free(offsetProps); - return Successful; -} +/*
+
+Copyright 1990, 1994, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <X11/fonts/fntfilst.h>
+#include <X11/fonts/bitmap.h>
+#include <X11/fonts/pcf.h>
+
+/* Write PCF font files */
+
+static CARD32 current_position;
+
+static int
+pcfWrite(FontFilePtr file, char *b, int c)
+{
+ current_position += c;
+ return FontFileWrite(file, b, c);
+}
+
+static int
+pcfPutLSB32(FontFilePtr file, int c)
+{
+ current_position += 4;
+ (void) FontFilePutc(c, file);
+ (void) FontFilePutc(c >> 8, file);
+ (void) FontFilePutc(c >> 16, file);
+ return FontFilePutc(c >> 24, file);
+}
+
+static int
+pcfPutINT32(FontFilePtr file, CARD32 format, int c)
+{
+ current_position += 4;
+ if (PCF_BYTE_ORDER(format) == MSBFirst) {
+ (void) FontFilePutc(c >> 24, file);
+ (void) FontFilePutc(c >> 16, file);
+ (void) FontFilePutc(c >> 8, file);
+ return FontFilePutc(c, file);
+ } else {
+ (void) FontFilePutc(c, file);
+ (void) FontFilePutc(c >> 8, file);
+ (void) FontFilePutc(c >> 16, file);
+ return FontFilePutc(c >> 24, file);
+ }
+}
+
+static int
+pcfPutINT16(FontFilePtr file, CARD32 format, int c)
+{
+ current_position += 2;
+ if (PCF_BYTE_ORDER(format) == MSBFirst) {
+ (void) FontFilePutc(c >> 8, file);
+ return FontFilePutc(c, file);
+ } else {
+ (void) FontFilePutc(c, file);
+ return FontFilePutc(c >> 8, file);
+ }
+}
+
+/*ARGSUSED*/
+static int
+pcfPutINT8(FontFilePtr file, CARD32 format, int c)
+{
+ current_position += 1;
+ return FontFilePutc(c, file);
+}
+
+static void
+pcfWriteTOC(FontFilePtr file, PCFTablePtr table, int count)
+{
+ CARD32 version;
+ int i;
+
+ version = PCF_FILE_VERSION;
+ pcfPutLSB32(file, version);
+ pcfPutLSB32(file, count);
+ for (i = 0; i < count; i++) {
+ pcfPutLSB32(file, table->type);
+ pcfPutLSB32(file, table->format);
+ pcfPutLSB32(file, table->size);
+ pcfPutLSB32(file, table->offset);
+ table++;
+ }
+}
+
+static void
+pcfPutCompressedMetric(FontFilePtr file, CARD32 format, xCharInfo *metric)
+{
+ pcfPutINT8(file, format, metric->leftSideBearing + 0x80);
+ pcfPutINT8(file, format, metric->rightSideBearing + 0x80);
+ pcfPutINT8(file, format, metric->characterWidth + 0x80);
+ pcfPutINT8(file, format, metric->ascent + 0x80);
+ pcfPutINT8(file, format, metric->descent + 0x80);
+}
+
+static void
+pcfPutMetric(FontFilePtr file, CARD32 format, xCharInfo *metric)
+{
+ pcfPutINT16(file, format, metric->leftSideBearing);
+ pcfPutINT16(file, format, metric->rightSideBearing);
+ pcfPutINT16(file, format, metric->characterWidth);
+ pcfPutINT16(file, format, metric->ascent);
+ pcfPutINT16(file, format, metric->descent);
+ pcfPutINT16(file, format, metric->attributes);
+}
+
+static void
+pcfPutBitmap(FontFilePtr file, CARD32 format, CharInfoPtr pCI)
+{
+ int count;
+ unsigned char *bits;
+
+ count = BYTES_FOR_GLYPH(pCI, PCF_GLYPH_PAD(format));
+ bits = (unsigned char *) pCI->bits;
+ current_position += count;
+ while (count--)
+ FontFilePutc(*bits++, file);
+}
+
+static void
+pcfPutAccel(FontFilePtr file, CARD32 format, FontInfoPtr pFontInfo)
+{
+ pcfPutINT8(file, format, pFontInfo->noOverlap);
+ pcfPutINT8(file, format, pFontInfo->constantMetrics);
+ pcfPutINT8(file, format, pFontInfo->terminalFont);
+ pcfPutINT8(file, format, pFontInfo->constantWidth);
+ pcfPutINT8(file, format, pFontInfo->inkInside);
+ pcfPutINT8(file, format, pFontInfo->inkMetrics);
+ pcfPutINT8(file, format, pFontInfo->drawDirection);
+ pcfPutINT8(file, format, 0);
+ pcfPutINT32(file, format, pFontInfo->fontAscent);
+ pcfPutINT32(file, format, pFontInfo->fontDescent);
+ pcfPutINT32(file, format, pFontInfo->maxOverlap);
+ pcfPutMetric(file, format, &pFontInfo->minbounds);
+ pcfPutMetric(file, format, &pFontInfo->maxbounds);
+ if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) {
+ pcfPutMetric(file, format, &pFontInfo->ink_minbounds);
+ pcfPutMetric(file, format, &pFontInfo->ink_maxbounds);
+ }
+}
+
+#define S32 4
+#define S16 2
+#define S8 1
+
+#define Pad(s) (RoundUp(s) - (s))
+#define RoundUp(s) (((s) + 3) & ~3)
+
+#define Compressable(i) (-128 <= (i) && (i) <= 127)
+
+#define CanCompressMetric(m) (Compressable((m)->leftSideBearing) && \
+ Compressable((m)->rightSideBearing) && \
+ Compressable((m)->characterWidth) && \
+ Compressable((m)->ascent) && \
+ Compressable((m)->descent) && \
+ (m)->attributes == 0)
+
+#define CanCompressMetrics(min,max) (CanCompressMetric(min) && CanCompressMetric(max))
+
+static char *
+pcfNameForAtom(Atom a)
+{
+ return NameForAtom(a);
+}
+
+int
+pcfWriteFont(FontPtr pFont, FontFilePtr file)
+{
+ PCFTableRec tables[32],
+ *table;
+ CARD32 mask,
+ bit;
+ int ntables;
+ int size;
+ CARD32 format;
+ int i;
+ int cur_table;
+ int prop_string_size;
+ int glyph_string_size;
+ xCharInfo *minbounds,
+ *maxbounds;
+ xCharInfo *ink_minbounds,
+ *ink_maxbounds;
+ BitmapFontPtr bitmapFont;
+ int nencodings = 0;
+ int header_size;
+ FontPropPtr offsetProps;
+ int prop_pad = 0;
+ char *atom_name;
+ int glyph;
+ CARD32 offset;
+
+ bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
+ if (bitmapFont->bitmapExtra) {
+ minbounds = &bitmapFont->bitmapExtra->info.minbounds;
+ maxbounds = &bitmapFont->bitmapExtra->info.maxbounds;
+ ink_minbounds = &bitmapFont->bitmapExtra->info.ink_minbounds;
+ ink_maxbounds = &bitmapFont->bitmapExtra->info.ink_maxbounds;
+ } else {
+ minbounds = &pFont->info.minbounds;
+ maxbounds = &pFont->info.maxbounds;
+ ink_minbounds = &pFont->info.ink_minbounds;
+ ink_maxbounds = &pFont->info.ink_maxbounds;
+ }
+ offsetProps = malloc(pFont->info.nprops * sizeof(FontPropRec));
+ if (!offsetProps) {
+ pcfError("pcfWriteFont(): Couldn't allocate offsetProps (%d*%d)", pFont->info.nprops, sizeof(FontPropRec));
+ return AllocError;
+ }
+ prop_string_size = 0;
+ for (i = 0; i < pFont->info.nprops; i++) {
+ offsetProps[i].name = prop_string_size;
+ prop_string_size += strlen(pcfNameForAtom(pFont->info.props[i].name)) + 1;
+ if (pFont->info.isStringProp[i]) {
+ offsetProps[i].value = prop_string_size;
+ prop_string_size += strlen(pcfNameForAtom(pFont->info.props[i].value)) + 1;
+ } else
+ offsetProps[i].value = pFont->info.props[i].value;
+ }
+ format = PCF_FORMAT(pFont->bit, pFont->byte, pFont->glyph, pFont->scan);
+ mask = 0xFFFFFFF;
+ ntables = 0;
+ table = tables;
+ while (mask) {
+ bit = lowbit(mask);
+ mask &= ~bit;
+ table->type = bit;
+ switch (bit) {
+ case PCF_PROPERTIES:
+ table->format = PCF_DEFAULT_FORMAT | format;
+ size = S32 + S32 + (S32 + S8 + S32) * pFont->info.nprops;
+ prop_pad = Pad(size);
+ table->size = RoundUp(size) + S32 +
+ RoundUp(prop_string_size);
+ table++;
+ break;
+ case PCF_ACCELERATORS:
+ if (bitmapFont->bitmapExtra->info.inkMetrics)
+ table->format = PCF_ACCEL_W_INKBOUNDS | format;
+ else
+ table->format = PCF_DEFAULT_FORMAT | format;
+ table->size = 100;
+ table++;
+ break;
+ case PCF_METRICS:
+ if (CanCompressMetrics(minbounds, maxbounds)) {
+ table->format = PCF_COMPRESSED_METRICS | format;
+ size = S32 + S16 + bitmapFont->num_chars * (5 * S8);
+ table->size = RoundUp(size);
+ } else {
+ table->format = PCF_DEFAULT_FORMAT | format;
+ table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16);
+ }
+ table++;
+ break;
+ case PCF_BITMAPS:
+ table->format = PCF_DEFAULT_FORMAT | format;
+ size = S32 + S32 + bitmapFont->num_chars * S32 +
+ GLYPHPADOPTIONS * S32 +
+ bitmapFont->bitmapExtra->bitmapsSizes[PCF_GLYPH_PAD_INDEX(format)];
+ table->size = RoundUp(size);
+ table++;
+ break;
+ case PCF_INK_METRICS:
+ if (bitmapFont->ink_metrics) {
+ if (CanCompressMetrics(ink_minbounds, ink_maxbounds)) {
+ table->format = PCF_COMPRESSED_METRICS | format;
+ size = S32 + S16 + bitmapFont->num_chars * (5 * S8);
+ table->size = RoundUp(size);
+ } else {
+ table->format = PCF_DEFAULT_FORMAT | format;
+ table->size = S32 + S32 + bitmapFont->num_chars * (6 * S16);
+ }
+ table++;
+ }
+ break;
+ case PCF_BDF_ENCODINGS:
+ table->format = PCF_DEFAULT_FORMAT | format;
+ nencodings = (pFont->info.lastRow - pFont->info.firstRow + 1) *
+ (pFont->info.lastCol - pFont->info.firstCol + 1);
+ size = S32 + 5 * S16 + nencodings * S16;
+ table->size = RoundUp(size);
+ table++;
+ break;
+ case PCF_SWIDTHS:
+ table->format = PCF_DEFAULT_FORMAT | format;
+ table->size = S32 + S32 + bitmapFont->num_chars * S32;
+ table++;
+ break;
+ case PCF_GLYPH_NAMES:
+ table->format = PCF_DEFAULT_FORMAT | format;
+ glyph_string_size = 0;
+ for (i = 0; i < bitmapFont->num_chars; i++)
+ glyph_string_size += strlen(pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i])) + 1;
+ table->size = S32 + S32 + bitmapFont->num_chars * S32 +
+ S32 + RoundUp(glyph_string_size);
+ table++;
+ break;
+ case PCF_BDF_ACCELERATORS:
+ if (pFont->info.inkMetrics)
+ table->format = PCF_ACCEL_W_INKBOUNDS | format;
+ else
+ table->format = PCF_DEFAULT_FORMAT | format;
+ table->size = 100;
+ table++;
+ break;
+ }
+ }
+ ntables = table - tables;
+ offset = 0;
+ header_size = S32 + S32 + ntables * (4 * S32);
+ offset = header_size;
+ for (cur_table = 0, table = tables;
+ cur_table < ntables;
+ cur_table++, table++) {
+ table->offset = offset;
+ offset += table->size;
+ }
+ current_position = 0;
+ pcfWriteTOC(file, tables, ntables);
+ for (cur_table = 0, table = tables;
+ cur_table < ntables;
+ cur_table++, table++) {
+ if (current_position > table->offset) {
+ printf("can't go backwards... %d > %d\n",
+ (int)current_position, (int)table->offset);
+ free(offsetProps);
+ return BadFontName;
+ }
+ while (current_position < table->offset)
+ pcfPutINT8(file, format, '\0');
+ pcfPutLSB32(file, table->format);
+ switch (table->type) {
+ case PCF_PROPERTIES:
+ pcfPutINT32(file, format, pFont->info.nprops);
+ for (i = 0; i < pFont->info.nprops; i++) {
+ pcfPutINT32(file, format, offsetProps[i].name);
+ pcfPutINT8(file, format, pFont->info.isStringProp[i]);
+ pcfPutINT32(file, format, offsetProps[i].value);
+ }
+ for (i = 0; i < prop_pad; i++)
+ pcfPutINT8(file, format, 0);
+ pcfPutINT32(file, format, prop_string_size);
+ for (i = 0; i < pFont->info.nprops; i++) {
+ atom_name = pcfNameForAtom(pFont->info.props[i].name);
+ pcfWrite(file, atom_name, strlen(atom_name) + 1);
+ if (pFont->info.isStringProp[i]) {
+ atom_name = pcfNameForAtom(pFont->info.props[i].value);
+ pcfWrite(file, atom_name, strlen(atom_name) + 1);
+ }
+ }
+ break;
+ case PCF_ACCELERATORS:
+ pcfPutAccel(file, table->format, &bitmapFont->bitmapExtra->info);
+ break;
+ case PCF_METRICS:
+ if (PCF_FORMAT_MATCH(table->format, PCF_COMPRESSED_METRICS)) {
+ pcfPutINT16(file, format, bitmapFont->num_chars);
+ for (i = 0; i < bitmapFont->num_chars; i++)
+ pcfPutCompressedMetric(file, format, &bitmapFont->metrics[i].metrics);
+ } else {
+ pcfPutINT32(file, format, bitmapFont->num_chars);
+ for (i = 0; i < bitmapFont->num_chars; i++)
+ pcfPutMetric(file, format, &bitmapFont->metrics[i].metrics);
+ }
+ break;
+ case PCF_BITMAPS:
+ pcfPutINT32(file, format, bitmapFont->num_chars);
+ glyph = PCF_GLYPH_PAD(format);
+ offset = 0;
+ for (i = 0; i < bitmapFont->num_chars; i++) {
+ pcfPutINT32(file, format, offset);
+ offset += BYTES_FOR_GLYPH(&bitmapFont->metrics[i], glyph);
+ }
+ for (i = 0; i < GLYPHPADOPTIONS; i++) {
+ pcfPutINT32(file, format,
+ bitmapFont->bitmapExtra->bitmapsSizes[i]);
+ }
+ for (i = 0; i < bitmapFont->num_chars; i++)
+ pcfPutBitmap(file, format, &bitmapFont->metrics[i]);
+ break;
+ case PCF_INK_METRICS:
+ if (PCF_FORMAT_MATCH(table->format, PCF_COMPRESSED_METRICS)) {
+ pcfPutINT16(file, format, bitmapFont->num_chars);
+ for (i = 0; i < bitmapFont->num_chars; i++)
+ pcfPutCompressedMetric(file, format, &bitmapFont->ink_metrics[i]);
+ } else {
+ pcfPutINT32(file, format, bitmapFont->num_chars);
+ for (i = 0; i < bitmapFont->num_chars; i++)
+ pcfPutMetric(file, format, &bitmapFont->ink_metrics[i]);
+ }
+ break;
+ case PCF_BDF_ENCODINGS:
+ pcfPutINT16(file, format, pFont->info.firstCol);
+ pcfPutINT16(file, format, pFont->info.lastCol);
+ pcfPutINT16(file, format, pFont->info.firstRow);
+ pcfPutINT16(file, format, pFont->info.lastRow);
+ pcfPutINT16(file, format, pFont->info.defaultCh);
+ for (i = 0; i < nencodings; i++) {
+ if (ACCESSENCODING(bitmapFont->encoding,i))
+ pcfPutINT16(file, format,
+ ACCESSENCODING(bitmapFont->encoding, i) -
+ bitmapFont->metrics);
+ else
+ pcfPutINT16(file, format, 0xFFFF);
+ }
+ break;
+ case PCF_SWIDTHS:
+ pcfPutINT32(file, format, bitmapFont->num_chars);
+ for (i = 0; i < bitmapFont->num_chars; i++)
+ pcfPutINT32(file, format, bitmapFont->bitmapExtra->sWidths[i]);
+ break;
+ case PCF_GLYPH_NAMES:
+ pcfPutINT32(file, format, bitmapFont->num_chars);
+ offset = 0;
+ for (i = 0; i < bitmapFont->num_chars; i++) {
+ pcfPutINT32(file, format, offset);
+ offset += strlen(pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i])) + 1;
+ }
+ pcfPutINT32(file, format, offset);
+ for (i = 0; i < bitmapFont->num_chars; i++) {
+ atom_name = pcfNameForAtom(bitmapFont->bitmapExtra->glyphNames[i]);
+ pcfWrite(file, atom_name, strlen(atom_name) + 1);
+ }
+ break;
+ case PCF_BDF_ACCELERATORS:
+ pcfPutAccel(file, table->format, &pFont->info);
+ break;
+ }
+ }
+
+ free(offsetProps);
+ return Successful;
+}
diff --git a/libXfont/src/bitmap/snfread.c b/libXfont/src/bitmap/snfread.c index d003cc5a5..d0b0dfe3c 100644 --- a/libXfont/src/bitmap/snfread.c +++ b/libXfont/src/bitmap/snfread.c @@ -1,508 +1,508 @@ -/************************************************************************ -Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -************************************************************************/ - -/* - -Copyright 1994, 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. - -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <ctype.h> -#include <X11/fonts/fntfilst.h> -#include <X11/fonts/bitmap.h> -#include "snfstr.h" - -#include <stdarg.h> - -static void -snfError(const char* message, ...) -{ - va_list args; - - va_start(args, message); - - fprintf(stderr, "SNF Error: "); - vfprintf(stderr, message, args); - va_end(args); -} - -static void snfUnloadFont(FontPtr pFont); - -static int -snfReadCharInfo(FontFilePtr file, CharInfoPtr charInfo, char *base) -{ - snfCharInfoRec snfCharInfo; - -#define Width(m) ((m).rightSideBearing - (m).leftSideBearing) -#define Height(m) ((m).ascent + (m).descent) - - if (FontFileRead(file, (char *) &snfCharInfo, sizeof snfCharInfo) != - sizeof(snfCharInfo)) { - return BadFontName; - } - charInfo->metrics = snfCharInfo.metrics; - if (snfCharInfo.exists) - charInfo->bits = base + snfCharInfo.byteOffset; - else - charInfo->bits = 0; - return Successful; -} - -static int -snfReadxCharInfo(FontFilePtr file, xCharInfo *charInfo) -{ - snfCharInfoRec snfCharInfo; - - if (FontFileRead(file, (char *) &snfCharInfo, sizeof snfCharInfo) != - sizeof(snfCharInfo)) { - return BadFontName; - } - *charInfo = snfCharInfo.metrics; - return Successful; -} - -static void -snfCopyInfo(snfFontInfoPtr snfInfo, FontInfoPtr pFontInfo) -{ - pFontInfo->firstCol = snfInfo->firstCol; - pFontInfo->lastCol = snfInfo->lastCol; - pFontInfo->firstRow = snfInfo->firstRow; - pFontInfo->lastRow = snfInfo->lastRow; - pFontInfo->defaultCh = snfInfo->chDefault; - pFontInfo->noOverlap = snfInfo->noOverlap; - pFontInfo->terminalFont = snfInfo->terminalFont; - pFontInfo->constantMetrics = snfInfo->constantMetrics; - pFontInfo->constantWidth = snfInfo->constantWidth; - pFontInfo->inkInside = snfInfo->inkInside; - pFontInfo->inkMetrics = snfInfo->inkMetrics; - pFontInfo->allExist = snfInfo->allExist; - pFontInfo->drawDirection = snfInfo->drawDirection; - pFontInfo->anamorphic = FALSE; - pFontInfo->cachable = TRUE; - pFontInfo->maxOverlap = 0; - pFontInfo->minbounds = snfInfo->minbounds.metrics; - pFontInfo->maxbounds = snfInfo->maxbounds.metrics; - pFontInfo->fontAscent = snfInfo->fontAscent; - pFontInfo->fontDescent = snfInfo->fontDescent; - pFontInfo->nprops = snfInfo->nProps; -} - -static int -snfReadProps(snfFontInfoPtr snfInfo, FontInfoPtr pFontInfo, FontFilePtr file) -{ - char *strings; - FontPropPtr pfp; - snfFontPropPtr psnfp; - char *propspace; - int bytestoalloc; - int i; - - bytestoalloc = snfInfo->nProps * sizeof(snfFontPropRec) + - BYTESOFSTRINGINFO(snfInfo); - propspace = malloc(bytestoalloc); - if (!propspace) { - snfError("snfReadProps(): Couldn't allocate propspace (%d)\n", bytestoalloc); - return AllocError; - } - - if (FontFileRead(file, propspace, bytestoalloc) != bytestoalloc) { - free(propspace); - return BadFontName; - } - psnfp = (snfFontPropPtr) propspace; - - strings = propspace + BYTESOFPROPINFO(snfInfo); - - for (i = 0, pfp = pFontInfo->props; i < snfInfo->nProps; i++, pfp++, psnfp++) { - pfp->name = MakeAtom(&strings[psnfp->name], - (unsigned) strlen(&strings[psnfp->name]), 1); - pFontInfo->isStringProp[i] = psnfp->indirect; - if (psnfp->indirect) - pfp->value = (INT32) MakeAtom(&strings[psnfp->value], - (unsigned) strlen(&strings[psnfp->value]), 1); - else - pfp->value = psnfp->value; - } - - free(propspace); - return Successful; -} - -static int -snfReadHeader(snfFontInfoPtr snfInfo, FontFilePtr file) -{ - if (FontFileRead(file, (char *) snfInfo, sizeof *snfInfo) != sizeof *snfInfo) - return BadFontName; - - if (snfInfo->version1 != FONT_FILE_VERSION || - snfInfo->version2 != FONT_FILE_VERSION) - return BadFontName; - return Successful; -} - -static int snf_set; -static int snf_bit, snf_byte, snf_glyph, snf_scan; - -void -SnfSetFormat (int bit, int byte, int glyph, int scan) -{ - snf_bit = bit; - snf_byte = byte; - snf_glyph = glyph; - snf_scan = scan; - snf_set = 1; -} - -static void -SnfGetFormat (int *bit, int *byte, int *glyph, int *scan) -{ - if (!snf_set) - FontDefaultFormat (&snf_bit, &snf_byte, &snf_glyph, &snf_scan); - *bit = snf_bit; - *byte = snf_byte; - *glyph = snf_glyph; - *scan = snf_scan; -} - -int -snfReadFont(FontPtr pFont, FontFilePtr file, - int bit, int byte, int glyph, int scan) -{ - snfFontInfoRec fi; - unsigned bytestoalloc; - int i, j; - char *fontspace; - BitmapFontPtr bitmapFont; - int num_chars; - int bitmapsSize; - int ret; - int metrics_off; - int encoding_off; - int props_off; - int isStringProp_off; - int ink_off; - char *bitmaps; - int def_bit, def_byte, def_glyph, def_scan; - - ret = snfReadHeader(&fi, file); - if (ret != Successful) - return ret; - - SnfGetFormat (&def_bit, &def_byte, &def_glyph, &def_scan); - - /* - * we'll allocate one chunk of memory and split it among the various parts - * of the font: - * - * BitmapFontRec CharInfoRec's Glyphs Encoding DIX Properties Ink CharInfoRec's - * - * If the glyphpad is not the same as the font file, then the glyphs - * are allocated separately, to be later realloc'ed when we know - * how big to make them. - */ - - bitmapsSize = BYTESOFGLYPHINFO(&fi); - num_chars = n2dChars(&fi); - bytestoalloc = sizeof(BitmapFontRec); /* bitmapFont */ - metrics_off = bytestoalloc; - bytestoalloc += num_chars * sizeof(CharInfoRec); /* metrics */ - encoding_off = bytestoalloc; - bytestoalloc += NUM_SEGMENTS(num_chars) * sizeof(CharInfoPtr**); - /* encoding */ - props_off = bytestoalloc; - bytestoalloc += fi.nProps * sizeof(FontPropRec); /* props */ - isStringProp_off = bytestoalloc; - bytestoalloc += fi.nProps * sizeof(char); /* isStringProp */ - bytestoalloc = (bytestoalloc + 3) & ~3; - ink_off = bytestoalloc; - if (fi.inkMetrics) - bytestoalloc += num_chars * sizeof(xCharInfo); /* ink_metrics */ - - fontspace = malloc(bytestoalloc); - if (!fontspace) { - snfError("snfReadFont(): Couldn't allocate fontspace (%d)\n", bytestoalloc); - return AllocError; - } - bitmaps = malloc (bitmapsSize); - if (!bitmaps) - { - snfError("snfReadFont(): Couldn't allocate bitmaps (%d)\n", bitmapsSize); - free (fontspace); - return AllocError; - } - /* - * now fix up pointers - */ - - bitmapFont = (BitmapFontPtr) fontspace; - bitmapFont->num_chars = num_chars; - bitmapFont->metrics = (CharInfoPtr) (fontspace + metrics_off); - bitmapFont->encoding = (CharInfoPtr **) (fontspace + encoding_off); - bitmapFont->bitmaps = bitmaps; - bitmapFont->pDefault = NULL; - bitmapFont->bitmapExtra = NULL; - pFont->info.props = (FontPropPtr) (fontspace + props_off); - pFont->info.isStringProp = (char *) (fontspace + isStringProp_off); - if (fi.inkMetrics) - bitmapFont->ink_metrics = (xCharInfo *) (fontspace + ink_off); - else - bitmapFont->ink_metrics = 0; - - /* - * read the CharInfo - */ - - ret = Successful; - memset(bitmapFont->encoding, 0, - NUM_SEGMENTS(num_chars)*sizeof(CharInfoPtr*)); - for (i = 0; ret == Successful && i < num_chars; i++) { - ret = snfReadCharInfo(file, &bitmapFont->metrics[i], bitmaps); - if (bitmapFont->metrics[i].bits) { - if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) { - bitmapFont->encoding[SEGMENT_MAJOR(i)]= - calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr)); - if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) { - ret = AllocError; - break; - } - } - ACCESSENCODINGL(bitmapFont->encoding,i) = &bitmapFont->metrics[i]; - } - } - - if (ret != Successful) { - free(bitmaps); - if(bitmapFont->encoding) { - for(j=0; j<SEGMENT_MAJOR(i); j++) - free(bitmapFont->encoding[i]); - } - free(fontspace); - return ret; - } - /* - * read the glyphs - */ - - if (FontFileRead(file, bitmaps, bitmapsSize) != bitmapsSize) { - free(bitmaps); - free(fontspace); - return BadFontName; - } - - if (def_bit != bit) - BitOrderInvert((unsigned char *)bitmaps, bitmapsSize); - if ((def_byte == def_bit) != (bit == byte)) { - switch (bit == byte ? def_scan : scan) { - case 1: - break; - case 2: - TwoByteSwap((unsigned char *)bitmaps, bitmapsSize); - break; - case 4: - FourByteSwap((unsigned char *)bitmaps, bitmapsSize); - break; - } - } - if (def_glyph != glyph) { - char *padbitmaps; - int sizepadbitmaps; - int sizechar; - CharInfoPtr metric; - - sizepadbitmaps = 0; - metric = bitmapFont->metrics; - for (i = 0; i < num_chars; i++) - { - if (metric->bits) - sizepadbitmaps += BYTES_FOR_GLYPH(metric,glyph); - metric++; - } - padbitmaps = malloc(sizepadbitmaps); - if (!padbitmaps) { - snfError("snfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps); - free (bitmaps); - free (fontspace); - return AllocError; - } - metric = bitmapFont->metrics; - bitmapFont->bitmaps = padbitmaps; - for (i = 0; i < num_chars; i++) { - sizechar = RepadBitmap(metric->bits, padbitmaps, - def_glyph, glyph, - metric->metrics.rightSideBearing - - metric->metrics.leftSideBearing, - metric->metrics.ascent + metric->metrics.descent); - metric->bits = padbitmaps; - padbitmaps += sizechar; - metric++; - } - free(bitmaps); - } - - /* now read and atom'ize properties */ - - ret = snfReadProps(&fi, &pFont->info, file); - if (ret != Successful) { - free(fontspace); - return ret; - } - snfCopyInfo(&fi, &pFont->info); - - /* finally, read the ink metrics if the exist */ - - if (fi.inkMetrics) { - ret = Successful; - ret = snfReadxCharInfo(file, &pFont->info.ink_minbounds); - ret = snfReadxCharInfo(file, &pFont->info.ink_maxbounds); - for (i = 0; ret == Successful && i < num_chars; i++) - ret = snfReadxCharInfo(file, &bitmapFont->ink_metrics[i]); - if (ret != Successful) { - free(fontspace); - return ret; - } - } else { - pFont->info.ink_minbounds = pFont->info.minbounds; - pFont->info.ink_maxbounds = pFont->info.maxbounds; - } - - if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) { - unsigned int r, - c, - cols; - - r = pFont->info.defaultCh >> 8; - c = pFont->info.defaultCh & 0xFF; - if (pFont->info.firstRow <= r && r <= pFont->info.lastRow && - pFont->info.firstCol <= c && c <= pFont->info.lastCol) { - cols = pFont->info.lastCol - pFont->info.firstCol + 1; - r = r - pFont->info.firstRow; - c = c - pFont->info.firstCol; - bitmapFont->pDefault = &bitmapFont->metrics[r * cols + c]; - } - } - bitmapFont->bitmapExtra = (BitmapExtraPtr) 0; - pFont->fontPrivate = (pointer) bitmapFont; - pFont->get_glyphs = bitmapGetGlyphs; - pFont->get_metrics = bitmapGetMetrics; - pFont->unload_font = snfUnloadFont; - pFont->unload_glyphs = NULL; - pFont->bit = bit; - pFont->byte = byte; - pFont->glyph = glyph; - pFont->scan = scan; - return Successful; -} - -int -snfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file) -{ - int ret; - snfFontInfoRec fi; - int bytestoskip; - int num_chars; - - ret = snfReadHeader(&fi, file); - if (ret != Successful) - return ret; - snfCopyInfo(&fi, pFontInfo); - - pFontInfo->props = malloc(fi.nProps * sizeof(FontPropRec)); - if (!pFontInfo->props) { - snfError("snfReadFontInfo(): Couldn't allocate props (%d*%d)\n", fi.nProps, sizeof(FontPropRec)); - return AllocError; - } - pFontInfo->isStringProp = malloc(fi.nProps * sizeof(char)); - if (!pFontInfo->isStringProp) { - snfError("snfReadFontInfo(): Couldn't allocate isStringProp (%d*%d)\n", fi.nProps, sizeof(char)); - free(pFontInfo->props); - return AllocError; - } - num_chars = n2dChars(&fi); - bytestoskip = num_chars * sizeof(snfCharInfoRec); /* charinfos */ - bytestoskip += BYTESOFGLYPHINFO(&fi); - (void)FontFileSkip(file, bytestoskip); - - ret = snfReadProps(&fi, pFontInfo, file); - if (ret != Successful) { - free(pFontInfo->props); - free(pFontInfo->isStringProp); - return ret; - } - if (fi.inkMetrics) { - ret = snfReadxCharInfo(file, &pFontInfo->ink_minbounds); - if (ret != Successful) { - free(pFontInfo->props); - free(pFontInfo->isStringProp); - return ret; - } - ret = snfReadxCharInfo(file, &pFontInfo->ink_maxbounds); - if (ret != Successful) { - free(pFontInfo->props); - free(pFontInfo->isStringProp); - return ret; - } - } else { - pFontInfo->ink_minbounds = pFontInfo->minbounds; - pFontInfo->ink_maxbounds = pFontInfo->maxbounds; - } - return Successful; - -} - -static void -snfUnloadFont(FontPtr pFont) -{ - BitmapFontPtr bitmapFont; - - bitmapFont = (BitmapFontPtr) pFont->fontPrivate; - free (bitmapFont->bitmaps); - free (bitmapFont); - DestroyFontRec (pFont); -} - +/************************************************************************
+Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+************************************************************************/
+
+/*
+
+Copyright 1994, 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.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <X11/fonts/fntfilst.h>
+#include <X11/fonts/bitmap.h>
+#include "snfstr.h"
+
+#include <stdarg.h>
+
+static void
+snfError(const char* message, ...)
+{
+ va_list args;
+
+ va_start(args, message);
+
+ fprintf(stderr, "SNF Error: ");
+ vfprintf(stderr, message, args);
+ va_end(args);
+}
+
+static void snfUnloadFont(FontPtr pFont);
+
+static int
+snfReadCharInfo(FontFilePtr file, CharInfoPtr charInfo, char *base)
+{
+ snfCharInfoRec snfCharInfo;
+
+#define Width(m) ((m).rightSideBearing - (m).leftSideBearing)
+#define Height(m) ((m).ascent + (m).descent)
+
+ if (FontFileRead(file, (char *) &snfCharInfo, sizeof snfCharInfo) !=
+ sizeof(snfCharInfo)) {
+ return BadFontName;
+ }
+ charInfo->metrics = snfCharInfo.metrics;
+ if (snfCharInfo.exists)
+ charInfo->bits = base + snfCharInfo.byteOffset;
+ else
+ charInfo->bits = 0;
+ return Successful;
+}
+
+static int
+snfReadxCharInfo(FontFilePtr file, xCharInfo *charInfo)
+{
+ snfCharInfoRec snfCharInfo;
+
+ if (FontFileRead(file, (char *) &snfCharInfo, sizeof snfCharInfo) !=
+ sizeof(snfCharInfo)) {
+ return BadFontName;
+ }
+ *charInfo = snfCharInfo.metrics;
+ return Successful;
+}
+
+static void
+snfCopyInfo(snfFontInfoPtr snfInfo, FontInfoPtr pFontInfo)
+{
+ pFontInfo->firstCol = snfInfo->firstCol;
+ pFontInfo->lastCol = snfInfo->lastCol;
+ pFontInfo->firstRow = snfInfo->firstRow;
+ pFontInfo->lastRow = snfInfo->lastRow;
+ pFontInfo->defaultCh = snfInfo->chDefault;
+ pFontInfo->noOverlap = snfInfo->noOverlap;
+ pFontInfo->terminalFont = snfInfo->terminalFont;
+ pFontInfo->constantMetrics = snfInfo->constantMetrics;
+ pFontInfo->constantWidth = snfInfo->constantWidth;
+ pFontInfo->inkInside = snfInfo->inkInside;
+ pFontInfo->inkMetrics = snfInfo->inkMetrics;
+ pFontInfo->allExist = snfInfo->allExist;
+ pFontInfo->drawDirection = snfInfo->drawDirection;
+ pFontInfo->anamorphic = FALSE;
+ pFontInfo->cachable = TRUE;
+ pFontInfo->maxOverlap = 0;
+ pFontInfo->minbounds = snfInfo->minbounds.metrics;
+ pFontInfo->maxbounds = snfInfo->maxbounds.metrics;
+ pFontInfo->fontAscent = snfInfo->fontAscent;
+ pFontInfo->fontDescent = snfInfo->fontDescent;
+ pFontInfo->nprops = snfInfo->nProps;
+}
+
+static int
+snfReadProps(snfFontInfoPtr snfInfo, FontInfoPtr pFontInfo, FontFilePtr file)
+{
+ char *strings;
+ FontPropPtr pfp;
+ snfFontPropPtr psnfp;
+ char *propspace;
+ int bytestoalloc;
+ int i;
+
+ bytestoalloc = snfInfo->nProps * sizeof(snfFontPropRec) +
+ BYTESOFSTRINGINFO(snfInfo);
+ propspace = malloc(bytestoalloc);
+ if (!propspace) {
+ snfError("snfReadProps(): Couldn't allocate propspace (%d)\n", bytestoalloc);
+ return AllocError;
+ }
+
+ if (FontFileRead(file, propspace, bytestoalloc) != bytestoalloc) {
+ free(propspace);
+ return BadFontName;
+ }
+ psnfp = (snfFontPropPtr) propspace;
+
+ strings = propspace + BYTESOFPROPINFO(snfInfo);
+
+ for (i = 0, pfp = pFontInfo->props; i < snfInfo->nProps; i++, pfp++, psnfp++) {
+ pfp->name = MakeAtom(&strings[psnfp->name],
+ (unsigned) strlen(&strings[psnfp->name]), 1);
+ pFontInfo->isStringProp[i] = psnfp->indirect;
+ if (psnfp->indirect)
+ pfp->value = (INT32) MakeAtom(&strings[psnfp->value],
+ (unsigned) strlen(&strings[psnfp->value]), 1);
+ else
+ pfp->value = psnfp->value;
+ }
+
+ free(propspace);
+ return Successful;
+}
+
+static int
+snfReadHeader(snfFontInfoPtr snfInfo, FontFilePtr file)
+{
+ if (FontFileRead(file, (char *) snfInfo, sizeof *snfInfo) != sizeof *snfInfo)
+ return BadFontName;
+
+ if (snfInfo->version1 != FONT_FILE_VERSION ||
+ snfInfo->version2 != FONT_FILE_VERSION)
+ return BadFontName;
+ return Successful;
+}
+
+static int snf_set;
+static int snf_bit, snf_byte, snf_glyph, snf_scan;
+
+void
+SnfSetFormat (int bit, int byte, int glyph, int scan)
+{
+ snf_bit = bit;
+ snf_byte = byte;
+ snf_glyph = glyph;
+ snf_scan = scan;
+ snf_set = 1;
+}
+
+static void
+SnfGetFormat (int *bit, int *byte, int *glyph, int *scan)
+{
+ if (!snf_set)
+ FontDefaultFormat (&snf_bit, &snf_byte, &snf_glyph, &snf_scan);
+ *bit = snf_bit;
+ *byte = snf_byte;
+ *glyph = snf_glyph;
+ *scan = snf_scan;
+}
+
+int
+snfReadFont(FontPtr pFont, FontFilePtr file,
+ int bit, int byte, int glyph, int scan)
+{
+ snfFontInfoRec fi;
+ unsigned bytestoalloc;
+ int i, j;
+ char *fontspace;
+ BitmapFontPtr bitmapFont;
+ int num_chars;
+ int bitmapsSize;
+ int ret;
+ int metrics_off;
+ int encoding_off;
+ int props_off;
+ int isStringProp_off;
+ int ink_off;
+ char *bitmaps;
+ int def_bit, def_byte, def_glyph, def_scan;
+
+ ret = snfReadHeader(&fi, file);
+ if (ret != Successful)
+ return ret;
+
+ SnfGetFormat (&def_bit, &def_byte, &def_glyph, &def_scan);
+
+ /*
+ * we'll allocate one chunk of memory and split it among the various parts
+ * of the font:
+ *
+ * BitmapFontRec CharInfoRec's Glyphs Encoding DIX Properties Ink CharInfoRec's
+ *
+ * If the glyphpad is not the same as the font file, then the glyphs
+ * are allocated separately, to be later realloc'ed when we know
+ * how big to make them.
+ */
+
+ bitmapsSize = BYTESOFGLYPHINFO(&fi);
+ num_chars = n2dChars(&fi);
+ bytestoalloc = sizeof(BitmapFontRec); /* bitmapFont */
+ metrics_off = bytestoalloc;
+ bytestoalloc += num_chars * sizeof(CharInfoRec); /* metrics */
+ encoding_off = bytestoalloc;
+ bytestoalloc += NUM_SEGMENTS(num_chars) * sizeof(CharInfoPtr**);
+ /* encoding */
+ props_off = bytestoalloc;
+ bytestoalloc += fi.nProps * sizeof(FontPropRec); /* props */
+ isStringProp_off = bytestoalloc;
+ bytestoalloc += fi.nProps * sizeof(char); /* isStringProp */
+ bytestoalloc = (bytestoalloc + 3) & ~3;
+ ink_off = bytestoalloc;
+ if (fi.inkMetrics)
+ bytestoalloc += num_chars * sizeof(xCharInfo); /* ink_metrics */
+
+ fontspace = malloc(bytestoalloc);
+ if (!fontspace) {
+ snfError("snfReadFont(): Couldn't allocate fontspace (%d)\n", bytestoalloc);
+ return AllocError;
+ }
+ bitmaps = malloc (bitmapsSize);
+ if (!bitmaps)
+ {
+ snfError("snfReadFont(): Couldn't allocate bitmaps (%d)\n", bitmapsSize);
+ free (fontspace);
+ return AllocError;
+ }
+ /*
+ * now fix up pointers
+ */
+
+ bitmapFont = (BitmapFontPtr) fontspace;
+ bitmapFont->num_chars = num_chars;
+ bitmapFont->metrics = (CharInfoPtr) (fontspace + metrics_off);
+ bitmapFont->encoding = (CharInfoPtr **) (fontspace + encoding_off);
+ bitmapFont->bitmaps = bitmaps;
+ bitmapFont->pDefault = NULL;
+ bitmapFont->bitmapExtra = NULL;
+ pFont->info.props = (FontPropPtr) (fontspace + props_off);
+ pFont->info.isStringProp = (char *) (fontspace + isStringProp_off);
+ if (fi.inkMetrics)
+ bitmapFont->ink_metrics = (xCharInfo *) (fontspace + ink_off);
+ else
+ bitmapFont->ink_metrics = 0;
+
+ /*
+ * read the CharInfo
+ */
+
+ ret = Successful;
+ memset(bitmapFont->encoding, 0,
+ NUM_SEGMENTS(num_chars)*sizeof(CharInfoPtr*));
+ for (i = 0; ret == Successful && i < num_chars; i++) {
+ ret = snfReadCharInfo(file, &bitmapFont->metrics[i], bitmaps);
+ if (bitmapFont->metrics[i].bits) {
+ if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) {
+ bitmapFont->encoding[SEGMENT_MAJOR(i)]=
+ calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr));
+ if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) {
+ ret = AllocError;
+ break;
+ }
+ }
+ ACCESSENCODINGL(bitmapFont->encoding,i) = &bitmapFont->metrics[i];
+ }
+ }
+
+ if (ret != Successful) {
+ free(bitmaps);
+ if(bitmapFont->encoding) {
+ for(j=0; j<SEGMENT_MAJOR(i); j++)
+ free(bitmapFont->encoding[i]);
+ }
+ free(fontspace);
+ return ret;
+ }
+ /*
+ * read the glyphs
+ */
+
+ if (FontFileRead(file, bitmaps, bitmapsSize) != bitmapsSize) {
+ free(bitmaps);
+ free(fontspace);
+ return BadFontName;
+ }
+
+ if (def_bit != bit)
+ BitOrderInvert((unsigned char *)bitmaps, bitmapsSize);
+ if ((def_byte == def_bit) != (bit == byte)) {
+ switch (bit == byte ? def_scan : scan) {
+ case 1:
+ break;
+ case 2:
+ TwoByteSwap((unsigned char *)bitmaps, bitmapsSize);
+ break;
+ case 4:
+ FourByteSwap((unsigned char *)bitmaps, bitmapsSize);
+ break;
+ }
+ }
+ if (def_glyph != glyph) {
+ char *padbitmaps;
+ int sizepadbitmaps;
+ int sizechar;
+ CharInfoPtr metric;
+
+ sizepadbitmaps = 0;
+ metric = bitmapFont->metrics;
+ for (i = 0; i < num_chars; i++)
+ {
+ if (metric->bits)
+ sizepadbitmaps += BYTES_FOR_GLYPH(metric,glyph);
+ metric++;
+ }
+ padbitmaps = malloc(sizepadbitmaps);
+ if (!padbitmaps) {
+ snfError("snfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps);
+ free (bitmaps);
+ free (fontspace);
+ return AllocError;
+ }
+ metric = bitmapFont->metrics;
+ bitmapFont->bitmaps = padbitmaps;
+ for (i = 0; i < num_chars; i++) {
+ sizechar = RepadBitmap(metric->bits, padbitmaps,
+ def_glyph, glyph,
+ metric->metrics.rightSideBearing -
+ metric->metrics.leftSideBearing,
+ metric->metrics.ascent + metric->metrics.descent);
+ metric->bits = padbitmaps;
+ padbitmaps += sizechar;
+ metric++;
+ }
+ free(bitmaps);
+ }
+
+ /* now read and atom'ize properties */
+
+ ret = snfReadProps(&fi, &pFont->info, file);
+ if (ret != Successful) {
+ free(fontspace);
+ return ret;
+ }
+ snfCopyInfo(&fi, &pFont->info);
+
+ /* finally, read the ink metrics if the exist */
+
+ if (fi.inkMetrics) {
+ ret = Successful;
+ ret = snfReadxCharInfo(file, &pFont->info.ink_minbounds);
+ ret = snfReadxCharInfo(file, &pFont->info.ink_maxbounds);
+ for (i = 0; ret == Successful && i < num_chars; i++)
+ ret = snfReadxCharInfo(file, &bitmapFont->ink_metrics[i]);
+ if (ret != Successful) {
+ free(fontspace);
+ return ret;
+ }
+ } else {
+ pFont->info.ink_minbounds = pFont->info.minbounds;
+ pFont->info.ink_maxbounds = pFont->info.maxbounds;
+ }
+
+ if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) {
+ unsigned int r,
+ c,
+ cols;
+
+ r = pFont->info.defaultCh >> 8;
+ c = pFont->info.defaultCh & 0xFF;
+ if (pFont->info.firstRow <= r && r <= pFont->info.lastRow &&
+ pFont->info.firstCol <= c && c <= pFont->info.lastCol) {
+ cols = pFont->info.lastCol - pFont->info.firstCol + 1;
+ r = r - pFont->info.firstRow;
+ c = c - pFont->info.firstCol;
+ bitmapFont->pDefault = &bitmapFont->metrics[r * cols + c];
+ }
+ }
+ bitmapFont->bitmapExtra = (BitmapExtraPtr) 0;
+ pFont->fontPrivate = (pointer) bitmapFont;
+ pFont->get_glyphs = bitmapGetGlyphs;
+ pFont->get_metrics = bitmapGetMetrics;
+ pFont->unload_font = snfUnloadFont;
+ pFont->unload_glyphs = NULL;
+ pFont->bit = bit;
+ pFont->byte = byte;
+ pFont->glyph = glyph;
+ pFont->scan = scan;
+ return Successful;
+}
+
+int
+snfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file)
+{
+ int ret;
+ snfFontInfoRec fi;
+ int bytestoskip;
+ int num_chars;
+
+ ret = snfReadHeader(&fi, file);
+ if (ret != Successful)
+ return ret;
+ snfCopyInfo(&fi, pFontInfo);
+
+ pFontInfo->props = malloc(fi.nProps * sizeof(FontPropRec));
+ if (!pFontInfo->props) {
+ snfError("snfReadFontInfo(): Couldn't allocate props (%d*%d)\n", fi.nProps, sizeof(FontPropRec));
+ return AllocError;
+ }
+ pFontInfo->isStringProp = malloc(fi.nProps * sizeof(char));
+ if (!pFontInfo->isStringProp) {
+ snfError("snfReadFontInfo(): Couldn't allocate isStringProp (%d*%d)\n", fi.nProps, sizeof(char));
+ free(pFontInfo->props);
+ return AllocError;
+ }
+ num_chars = n2dChars(&fi);
+ bytestoskip = num_chars * sizeof(snfCharInfoRec); /* charinfos */
+ bytestoskip += BYTESOFGLYPHINFO(&fi);
+ (void)FontFileSkip(file, bytestoskip);
+
+ ret = snfReadProps(&fi, pFontInfo, file);
+ if (ret != Successful) {
+ free(pFontInfo->props);
+ free(pFontInfo->isStringProp);
+ return ret;
+ }
+ if (fi.inkMetrics) {
+ ret = snfReadxCharInfo(file, &pFontInfo->ink_minbounds);
+ if (ret != Successful) {
+ free(pFontInfo->props);
+ free(pFontInfo->isStringProp);
+ return ret;
+ }
+ ret = snfReadxCharInfo(file, &pFontInfo->ink_maxbounds);
+ if (ret != Successful) {
+ free(pFontInfo->props);
+ free(pFontInfo->isStringProp);
+ return ret;
+ }
+ } else {
+ pFontInfo->ink_minbounds = pFontInfo->minbounds;
+ pFontInfo->ink_maxbounds = pFontInfo->maxbounds;
+ }
+ return Successful;
+
+}
+
+static void
+snfUnloadFont(FontPtr pFont)
+{
+ BitmapFontPtr bitmapFont;
+
+ bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
+ free (bitmapFont->bitmaps);
+ free (bitmapFont);
+ DestroyFontRec (pFont);
+}
+
diff --git a/libXfont/src/bitmap/snfstr.h b/libXfont/src/bitmap/snfstr.h index 148bb1fcc..89372669e 100644 --- a/libXfont/src/bitmap/snfstr.h +++ b/libXfont/src/bitmap/snfstr.h @@ -1,182 +1,182 @@ -/*********************************************************** -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -******************************************************************/ - -/* - -Copyright 1994, 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. - -*/ - -#ifndef SNFSTR_H -#define SNFSTR_H 1 - -#include <X11/fonts/fntfilio.h> - -/*- - * This file describes the Server Natural Font format. - * SNF fonts are both CPU-dependent and frame buffer bit order dependent. - * This file is used by: - * 1) the server, to hold font information read out of font files. - * 2) font converters - * - * Each font file contains the following - * data structures, with no padding in-between. - * - * 1) The XFONTINFO structure - * hand-padded to a two-short boundary. - * maxbounds.byteoffset is the total number of bytes in the - * glpyh array - * maxbounds.bitOffset is thetotal width of the unpadded font - * - * 2) The XCHARINFO array - * indexed directly with character codes, both on disk - * and in memory. - * - * 3) Character glyphs - * padded in the server-natural way, and - * ordered in the device-natural way. - * End of glyphs padded to 32-bit boundary. - * - * 4) nProps font properties - * - * 5) a sequence of null-terminated strings, for font properties - */ - -#define FONT_FILE_VERSION 4 - -typedef struct _snfFontProp { - CARD32 name; /* offset of string */ - INT32 value; /* number or offset of string */ - Bool indirect; /* value is a string offset */ -} snfFontPropRec; - -/* - * the following macro definitions describe a font file image in memory - */ -#define ADDRCharInfoRec( pfi) \ - ((snfCharInfoRec *) &(pfi)[1]) - -#define ADDRCHARGLYPHS( pfi) \ - (((char *) &(pfi)[1]) + BYTESOFCHARINFO(pfi)) - -/* - * pad out glyphs to a CARD32 boundary - */ -#define ADDRXFONTPROPS( pfi) \ - ((snfFontPropRec *) ((char *)ADDRCHARGLYPHS( pfi) + BYTESOFGLYPHINFO(pfi))) - -#define ADDRSTRINGTAB( pfi) \ - ((char *)ADDRXFONTPROPS( pfi) + BYTESOFPROPINFO(pfi)) - -#define n2dChars(pfi) (((pfi)->lastRow - (pfi)->firstRow + 1) * \ - ((pfi)->lastCol - (pfi)->firstCol + 1)) -#define BYTESOFFONTINFO(pfi) (sizeof(snfFontInfoRec)) -#define BYTESOFCHARINFO(pfi) (sizeof(snfCharInfoRec) * n2dChars(pfi)) -#define BYTESOFPROPINFO(pfi) (sizeof(snfFontPropRec) * (pfi)->nProps) -#define BYTESOFSTRINGINFO(pfi) ((pfi)->lenStrings) -#define BYTESOFGLYPHINFO(pfi) (((pfi)->maxbounds.byteOffset+3) & ~0x3) -#define BYTESOFINKINFO(pfi) (sizeof(snfCharInfoRec) * n2dChars(pfi)) - -typedef struct _snfFontProp *snfFontPropPtr; -typedef struct _snfCharInfo *snfCharInfoPtr; -typedef struct _snfFontInfo *snfFontInfoPtr; - -typedef struct _snfCharInfo { - xCharInfo metrics; /* info preformatted for Queries */ - unsigned byteOffset:24; /* byte offset of the raster from pGlyphs */ - unsigned exists:1; /* true iff glyph exists for this char */ - unsigned pad:7; /* must be zero for now */ -} snfCharInfoRec; - -typedef struct _snfFontInfo { - unsigned int version1; /* version stamp */ - unsigned int allExist; - unsigned int drawDirection; - unsigned int noOverlap; /* true if: - * max(rightSideBearing-characterWidth) <= - * minbounds->metrics.leftSideBearing */ - unsigned int constantMetrics; - unsigned int terminalFont; /* Should be deprecated! true if: constant - * metrics && leftSideBearing == 0 && - * rightSideBearing == characterWidth && - * ascent == fontAscent && descent == - * fontDescent */ - unsigned int linear:1; /* true if firstRow == lastRow */ - unsigned int constantWidth:1; /* true if - * minbounds->metrics.characterWidth - * == - * maxbounds->metrics.characterWidth */ - unsigned int inkInside:1; /* true if for all defined glyphs: - * leftSideBearing >= 0 && rightSideBearing <= - * characterWidth && -fontDescent <= ascent <= - * fontAscent && -fontAscent <= descent <= - * fontDescent */ - unsigned int inkMetrics:1; /* ink metrics != bitmap metrics */ - /* used with terminalFont */ - /* see font's pInk{CI,Min,Max} */ - unsigned int padding:28; - unsigned int firstCol; - unsigned int lastCol; - unsigned int firstRow; - unsigned int lastRow; - unsigned int nProps; - unsigned int lenStrings; /* length in bytes of string table */ - unsigned int chDefault; /* default character */ - int fontDescent; /* minimum for quality typography */ - int fontAscent; /* minimum for quality typography */ - snfCharInfoRec minbounds; /* MIN of glyph metrics over all chars */ - snfCharInfoRec maxbounds; /* MAX of glyph metrics over all chars */ - unsigned int pixDepth; /* intensity bits per pixel */ - unsigned int glyphSets; /* number of sets of glyphs, for sub-pixel - * positioning */ - unsigned int version2; /* version stamp double-check */ -} snfFontInfoRec; - -extern void SnfSetFormat ( int bit, int byte, int glyph, int scan ); -extern int snfReadFont ( FontPtr pFont, FontFilePtr file, - int bit, int byte, int glyph, int scan ); -extern int snfReadFontInfo ( FontInfoPtr pFontInfo, FontFilePtr file ); - -#endif /* SNFSTR_H */ +/***********************************************************
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/*
+
+Copyright 1994, 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.
+
+*/
+
+#ifndef SNFSTR_H
+#define SNFSTR_H 1
+
+#include <X11/fonts/fntfilio.h>
+
+/*-
+ * This file describes the Server Natural Font format.
+ * SNF fonts are both CPU-dependent and frame buffer bit order dependent.
+ * This file is used by:
+ * 1) the server, to hold font information read out of font files.
+ * 2) font converters
+ *
+ * Each font file contains the following
+ * data structures, with no padding in-between.
+ *
+ * 1) The XFONTINFO structure
+ * hand-padded to a two-short boundary.
+ * maxbounds.byteoffset is the total number of bytes in the
+ * glpyh array
+ * maxbounds.bitOffset is thetotal width of the unpadded font
+ *
+ * 2) The XCHARINFO array
+ * indexed directly with character codes, both on disk
+ * and in memory.
+ *
+ * 3) Character glyphs
+ * padded in the server-natural way, and
+ * ordered in the device-natural way.
+ * End of glyphs padded to 32-bit boundary.
+ *
+ * 4) nProps font properties
+ *
+ * 5) a sequence of null-terminated strings, for font properties
+ */
+
+#define FONT_FILE_VERSION 4
+
+typedef struct _snfFontProp {
+ CARD32 name; /* offset of string */
+ INT32 value; /* number or offset of string */
+ Bool indirect; /* value is a string offset */
+} snfFontPropRec;
+
+/*
+ * the following macro definitions describe a font file image in memory
+ */
+#define ADDRCharInfoRec( pfi) \
+ ((snfCharInfoRec *) &(pfi)[1])
+
+#define ADDRCHARGLYPHS( pfi) \
+ (((char *) &(pfi)[1]) + BYTESOFCHARINFO(pfi))
+
+/*
+ * pad out glyphs to a CARD32 boundary
+ */
+#define ADDRXFONTPROPS( pfi) \
+ ((snfFontPropRec *) ((char *)ADDRCHARGLYPHS( pfi) + BYTESOFGLYPHINFO(pfi)))
+
+#define ADDRSTRINGTAB( pfi) \
+ ((char *)ADDRXFONTPROPS( pfi) + BYTESOFPROPINFO(pfi))
+
+#define n2dChars(pfi) (((pfi)->lastRow - (pfi)->firstRow + 1) * \
+ ((pfi)->lastCol - (pfi)->firstCol + 1))
+#define BYTESOFFONTINFO(pfi) (sizeof(snfFontInfoRec))
+#define BYTESOFCHARINFO(pfi) (sizeof(snfCharInfoRec) * n2dChars(pfi))
+#define BYTESOFPROPINFO(pfi) (sizeof(snfFontPropRec) * (pfi)->nProps)
+#define BYTESOFSTRINGINFO(pfi) ((pfi)->lenStrings)
+#define BYTESOFGLYPHINFO(pfi) (((pfi)->maxbounds.byteOffset+3) & ~0x3)
+#define BYTESOFINKINFO(pfi) (sizeof(snfCharInfoRec) * n2dChars(pfi))
+
+typedef struct _snfFontProp *snfFontPropPtr;
+typedef struct _snfCharInfo *snfCharInfoPtr;
+typedef struct _snfFontInfo *snfFontInfoPtr;
+
+typedef struct _snfCharInfo {
+ xCharInfo metrics; /* info preformatted for Queries */
+ unsigned byteOffset:24; /* byte offset of the raster from pGlyphs */
+ unsigned exists:1; /* true iff glyph exists for this char */
+ unsigned pad:7; /* must be zero for now */
+} snfCharInfoRec;
+
+typedef struct _snfFontInfo {
+ unsigned int version1; /* version stamp */
+ unsigned int allExist;
+ unsigned int drawDirection;
+ unsigned int noOverlap; /* true if:
+ * max(rightSideBearing-characterWidth) <=
+ * minbounds->metrics.leftSideBearing */
+ unsigned int constantMetrics;
+ unsigned int terminalFont; /* Should be deprecated! true if: constant
+ * metrics && leftSideBearing == 0 &&
+ * rightSideBearing == characterWidth &&
+ * ascent == fontAscent && descent ==
+ * fontDescent */
+ unsigned int linear:1; /* true if firstRow == lastRow */
+ unsigned int constantWidth:1; /* true if
+ * minbounds->metrics.characterWidth
+ * ==
+ * maxbounds->metrics.characterWidth */
+ unsigned int inkInside:1; /* true if for all defined glyphs:
+ * leftSideBearing >= 0 && rightSideBearing <=
+ * characterWidth && -fontDescent <= ascent <=
+ * fontAscent && -fontAscent <= descent <=
+ * fontDescent */
+ unsigned int inkMetrics:1; /* ink metrics != bitmap metrics */
+ /* used with terminalFont */
+ /* see font's pInk{CI,Min,Max} */
+ unsigned int padding:28;
+ unsigned int firstCol;
+ unsigned int lastCol;
+ unsigned int firstRow;
+ unsigned int lastRow;
+ unsigned int nProps;
+ unsigned int lenStrings; /* length in bytes of string table */
+ unsigned int chDefault; /* default character */
+ int fontDescent; /* minimum for quality typography */
+ int fontAscent; /* minimum for quality typography */
+ snfCharInfoRec minbounds; /* MIN of glyph metrics over all chars */
+ snfCharInfoRec maxbounds; /* MAX of glyph metrics over all chars */
+ unsigned int pixDepth; /* intensity bits per pixel */
+ unsigned int glyphSets; /* number of sets of glyphs, for sub-pixel
+ * positioning */
+ unsigned int version2; /* version stamp double-check */
+} snfFontInfoRec;
+
+extern void SnfSetFormat ( int bit, int byte, int glyph, int scan );
+extern int snfReadFont ( FontPtr pFont, FontFilePtr file,
+ int bit, int byte, int glyph, int scan );
+extern int snfReadFontInfo ( FontInfoPtr pFontInfo, FontFilePtr file );
+
+#endif /* SNFSTR_H */
diff --git a/libXfont/src/builtins/builtin.h b/libXfont/src/builtins/builtin.h index 418bfe984..b767dd0f3 100644 --- a/libXfont/src/builtins/builtin.h +++ b/libXfont/src/builtins/builtin.h @@ -1,62 +1,62 @@ -/* - * - * Copyright 1999 SuSE, Inc. - * - * 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, and that the name of SuSE not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. SuSE makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE - * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Keith Packard, SuSE, Inc. - */ - -#include <X11/Xdefs.h> -#include <X11/fonts/font.h> -#include <X11/fonts/fontxlfd.h> -#include <X11/fonts/fntfil.h> -#include <X11/fonts/fntfilio.h> -#include <X11/fonts/fntfilst.h> - -typedef struct _BuiltinFile { - const char *name; - int len; - const char *bits; -} BuiltinFileRec, *BuiltinFilePtr; - -typedef struct _BuiltinDir { - char *file_name; - char *font_name; -} BuiltinDirRec, *BuiltinDirPtr; - -typedef struct _BuiltinAlias { - char *alias_name; - char *font_name; -} BuiltinAliasRec, *BuiltinAliasPtr; - -extern const BuiltinFileRec builtin_files[]; -extern const int builtin_files_count; - -extern const BuiltinDirRec builtin_dir[]; -extern const int builtin_dir_count; - -extern const BuiltinAliasRec builtin_alias[]; -extern const int builtin_alias_count; - -extern FontFilePtr BuiltinFileOpen (char *); -extern int BuiltinFileClose (BufFilePtr, int); -extern int BuiltinReadDirectory (char *, FontDirectoryPtr *); -extern void BuiltinRegisterFontFileFunctions (void); - -extern void BuiltinRegisterFpeFunctions (void); +/*
+ *
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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, and that the name of SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+
+#include <X11/Xdefs.h>
+#include <X11/fonts/font.h>
+#include <X11/fonts/fontxlfd.h>
+#include <X11/fonts/fntfil.h>
+#include <X11/fonts/fntfilio.h>
+#include <X11/fonts/fntfilst.h>
+
+typedef struct _BuiltinFile {
+ const char *name;
+ int len;
+ const char *bits;
+} BuiltinFileRec, *BuiltinFilePtr;
+
+typedef struct _BuiltinDir {
+ char *file_name;
+ char *font_name;
+} BuiltinDirRec, *BuiltinDirPtr;
+
+typedef struct _BuiltinAlias {
+ char *alias_name;
+ char *font_name;
+} BuiltinAliasRec, *BuiltinAliasPtr;
+
+extern const BuiltinFileRec builtin_files[];
+extern const int builtin_files_count;
+
+extern const BuiltinDirRec builtin_dir[];
+extern const int builtin_dir_count;
+
+extern const BuiltinAliasRec builtin_alias[];
+extern const int builtin_alias_count;
+
+extern FontFilePtr BuiltinFileOpen (char *);
+extern int BuiltinFileClose (BufFilePtr, int);
+extern int BuiltinReadDirectory (char *, FontDirectoryPtr *);
+extern void BuiltinRegisterFontFileFunctions (void);
+
+extern void BuiltinRegisterFpeFunctions (void);
diff --git a/libXfont/src/builtins/dir.c b/libXfont/src/builtins/dir.c index bf351b147..cd50cef56 100644 --- a/libXfont/src/builtins/dir.c +++ b/libXfont/src/builtins/dir.c @@ -25,6 +25,7 @@ #include <config.h> #endif #include "builtin.h" +#include <unistd.h> static BuiltinDirPtr BuiltinDirsDup (const BuiltinDirPtr a_dirs, diff --git a/libXfont/src/builtins/file.c b/libXfont/src/builtins/file.c index 549253926..9fcc25f3f 100644 --- a/libXfont/src/builtins/file.c +++ b/libXfont/src/builtins/file.c @@ -1,130 +1,130 @@ -/* - * Copyright 1999 SuSE, Inc. - * - * 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, and that the name of SuSE not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. SuSE makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE - * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Keith Packard, SuSE, Inc. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <string.h> -#include "builtin.h" - -typedef struct _BuiltinIO { - int offset; - BuiltinFilePtr file; -} BuiltinIORec, *BuiltinIOPtr; - -static int -BuiltinFill (BufFilePtr f) -{ - int left, len; - BuiltinIOPtr io = ((BuiltinIOPtr) f->private); - - left = io->file->len - io->offset; - if (left <= 0) - { - f->left = 0; - return BUFFILEEOF; - } - len = BUFFILESIZE; - if (len > left) - len = left; - memcpy (f->buffer, io->file->bits + io->offset, len); - io->offset += len; - f->left = len - 1; - f->bufp = f->buffer + 1; - return f->buffer[0]; -} - -static int -BuiltinSkip (BufFilePtr f, int count) -{ - BuiltinIOPtr io = ((BuiltinIOPtr) f->private); - int curoff; - int fileoff; - int todo; - - curoff = f->bufp - f->buffer; - fileoff = curoff + f->left; - if (curoff + count <= fileoff) { - f->bufp += count; - f->left -= count; - } else { - todo = count - (fileoff - curoff); - io->offset += todo; - if (io->offset > io->file->len) - io->offset = io->file->len; - if (io->offset < 0) - io->offset = 0; - f->left = 0; - } - return count; -} - -static int -BuiltinClose (BufFilePtr f, int unused) -{ - BuiltinIOPtr io = ((BuiltinIOPtr) f->private); - - free (io); - return 1; -} - - -FontFilePtr -BuiltinFileOpen (char *name) -{ - int i; - BuiltinIOPtr io; - BufFilePtr raw, cooked; - - if (*name == '/') name++; - for (i = 0; i < builtin_files_count; i++) - if (!strcmp (name, builtin_files[i].name)) - break; - if (i == builtin_files_count) - return NULL; - io = malloc (sizeof (BuiltinIORec)); - if (!io) - return NULL; - io->offset = 0; - io->file = (void *) &builtin_files[i]; - raw = BufFileCreate ((char *) io, BuiltinFill, 0, BuiltinSkip, BuiltinClose); - if (!raw) - { - free (io); - return NULL; - } - if ((cooked = BufFilePushZIP (raw))) - raw = cooked; - else - { - raw->left += raw->bufp - raw->buffer; - raw->bufp = raw->buffer; - } - return (FontFilePtr) raw; -} - -int -BuiltinFileClose (FontFilePtr f, int unused) -{ - return BufFileClose ((BufFilePtr) f, TRUE); -} +/*
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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, and that the name of SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <string.h>
+#include "builtin.h"
+
+typedef struct _BuiltinIO {
+ int offset;
+ BuiltinFilePtr file;
+} BuiltinIORec, *BuiltinIOPtr;
+
+static int
+BuiltinFill (BufFilePtr f)
+{
+ int left, len;
+ BuiltinIOPtr io = ((BuiltinIOPtr) f->private);
+
+ left = io->file->len - io->offset;
+ if (left <= 0)
+ {
+ f->left = 0;
+ return BUFFILEEOF;
+ }
+ len = BUFFILESIZE;
+ if (len > left)
+ len = left;
+ memcpy (f->buffer, io->file->bits + io->offset, len);
+ io->offset += len;
+ f->left = len - 1;
+ f->bufp = f->buffer + 1;
+ return f->buffer[0];
+}
+
+static int
+BuiltinSkip (BufFilePtr f, int count)
+{
+ BuiltinIOPtr io = ((BuiltinIOPtr) f->private);
+ int curoff;
+ int fileoff;
+ int todo;
+
+ curoff = f->bufp - f->buffer;
+ fileoff = curoff + f->left;
+ if (curoff + count <= fileoff) {
+ f->bufp += count;
+ f->left -= count;
+ } else {
+ todo = count - (fileoff - curoff);
+ io->offset += todo;
+ if (io->offset > io->file->len)
+ io->offset = io->file->len;
+ if (io->offset < 0)
+ io->offset = 0;
+ f->left = 0;
+ }
+ return count;
+}
+
+static int
+BuiltinClose (BufFilePtr f, int unused)
+{
+ BuiltinIOPtr io = ((BuiltinIOPtr) f->private);
+
+ free (io);
+ return 1;
+}
+
+
+FontFilePtr
+BuiltinFileOpen (char *name)
+{
+ int i;
+ BuiltinIOPtr io;
+ BufFilePtr raw, cooked;
+
+ if (*name == '/') name++;
+ for (i = 0; i < builtin_files_count; i++)
+ if (!strcmp (name, builtin_files[i].name))
+ break;
+ if (i == builtin_files_count)
+ return NULL;
+ io = malloc (sizeof (BuiltinIORec));
+ if (!io)
+ return NULL;
+ io->offset = 0;
+ io->file = (void *) &builtin_files[i];
+ raw = BufFileCreate ((char *) io, BuiltinFill, 0, BuiltinSkip, BuiltinClose);
+ if (!raw)
+ {
+ free (io);
+ return NULL;
+ }
+ if ((cooked = BufFilePushZIP (raw)))
+ raw = cooked;
+ else
+ {
+ raw->left += raw->bufp - raw->buffer;
+ raw->bufp = raw->buffer;
+ }
+ return (FontFilePtr) raw;
+}
+
+int
+BuiltinFileClose (FontFilePtr f, int unused)
+{
+ return BufFileClose ((BufFilePtr) f, TRUE);
+}
diff --git a/libXfont/src/builtins/fonts.c b/libXfont/src/builtins/fonts.c index 9a9d7d273..161e7bdbb 100644 --- a/libXfont/src/builtins/fonts.c +++ b/libXfont/src/builtins/fonts.c @@ -1,1252 +1,1252 @@ -/* - * Copyright 1999 SuSE, Inc. - * - * 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, and that the name of SuSE not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. SuSE makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE - * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Keith Packard, SuSE, Inc. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include "builtin.h" - -static const char file_cursor[] = { - '\037', '\213', '\010', '\010', '\143', '\117', '\054', '\100', - '\000', '\003', '\143', '\165', '\162', '\163', '\157', '\162', - '\056', '\160', '\143', '\146', '\000', '\355', '\233', '\177', - '\160', '\124', '\327', '\165', '\307', '\317', '\112', '\102', - '\022', '\130', '\040', '\021', '\300', '\226', '\023', '\031', - '\311', '\100', '\034', '\114', '\354', '\104', '\004', '\033', - '\013', '\233', '\040', '\141', '\040', '\006', '\327', '\001', - '\154', '\213', '\000', '\216', '\143', '\151', '\221', '\026', - '\244', '\146', '\365', '\203', '\325', '\352', '\027', '\010', - '\264', '\253', '\137', '\273', '\010', '\320', '\217', '\332', - '\155', '\035', '\217', '\123', '\323', '\044', '\323', '\361', - '\340', '\114', '\207', '\231', '\144', '\062', '\324', '\303', - '\324', '\212', '\235', '\232', '\046', '\045', '\305', '\323', - '\072', '\143', '\322', '\060', '\365', '\062', '\166', '\143', - '\246', '\166', '\221', '\360', '\057', '\224', '\262', '\150', - '\373', '\075', '\357', '\234', '\273', '\357', '\355', '\112', - '\313', '\217', '\244', '\371', '\057', '\232', '\371', '\274', - '\167', '\357', '\271', '\347', '\336', '\167', '\177', '\236', - '\173', '\356', '\173', '\053', '\327', '\316', '\252', '\306', - '\154', '\042', '\162', '\201', '\064', '\360', '\056', '\010', - '\153', '\230', '\251', '\006', '\136', '\044', '\146', '\160', - '\034', '\367', '\354', '\164', '\242', '\067', '\370', '\256', - '\351', '\147', '\027', '\021', '\235', '\101', '\142', '\221', - '\306', '\327', '\042', '\355', '\307', '\167', '\022', '\225', - '\151', '\274', '\021', '\227', '\361', '\045', '\104', '\001', - '\215', '\237', '\237', '\116', '\124', '\163', '\267', '\074', - '\320', '\224', '\277', '\371', '\076', '\011', '\043', '\311', - '\372', '\163', '\315', '\300', '\145', '\011', '\207', '\226', - '\103', '\353', '\136', '\226', '\334', '\217', '\313', '\152', - '\226', '\160', '\322', '\172', '\016', '\174', '\033', '\074', - '\316', '\201', '\215', '\240', '\322', '\004', '\352', '\070', - '\020', '\303', '\137', '\013', '\007', '\146', '\112', '\171', - '\101', '\260', '\146', '\323', '\346', '\355', '\217', '\155', - '\170', '\150', '\175', '\071', '\225', '\327', '\170', '\232', - '\074', '\105', '\013', '\166', '\171', '\333', '\033', '\153', - '\232', '\026', '\024', '\271', '\175', '\236', '\242', '\346', - '\172', '\117', '\175', '\125', '\163', '\335', '\016', '\217', - '\317', '\123', '\115', '\233', '\067', '\155', '\330', '\130', - '\136', '\361', '\370', '\206', '\047', '\326', '\321', '\327', - '\066', '\155', '\054', '\247', '\252', '\146', '\137', '\123', - '\203', '\217', '\266', '\256', '\263', '\162', '\077', '\266', - '\356', '\361', '\115', '\217', '\154', '\051', '\337', '\260', - '\151', '\243', '\043', '\130', '\261', '\315', '\031', '\331', - '\116', '\333', '\052', '\326', '\213', '\366', '\243', '\133', - '\126', '\257', '\255', '\330', '\272', '\141', '\155', '\271', - '\125', '\345', '\064', '\262', '\377', '\362', '\300', '\154', - '\255', '\353', '\305', '\030', '\267', '\053', '\026', '\263', - '\332', '\216', '\224', '\331', '\224', '\153', '\245', '\377', - '\076', '\177', '\074', '\106', '\317', '\321', '\236', '\360', - '\160', '\137', '\270', '\375', '\300', '\160', '\350', '\100', - '\123', '\160', '\070', '\060', '\340', '\353', '\032', '\016', - '\016', '\356', '\353', '\035', '\076', '\020', '\354', '\350', - '\033', '\356', '\357', '\262', '\103', '\110', '\350', '\356', - '\305', '\245', '\247', '\167', '\117', '\210', '\163', '\204', - '\221', '\043', '\060', '\060', '\174', '\070', '\330', '\071', - '\070', '\074', '\320', '\205', '\274', '\207', '\203', '\110', - '\035', '\350', '\102', '\352', '\341', '\040', '\122', '\007', - '\272', '\332', '\103', '\310', '\333', '\026', '\106', '\336', - '\266', '\320', '\160', '\070', '\214', '\120', '\070', '\214', - '\242', '\002', '\003', '\173', '\103', '\170', '\006', '\122', - '\103', '\041', '\113', '\206', '\032', '\164', '\037', '\336', - '\163', '\000', '\027', '\144', '\073', '\020', '\102', '\135', - '\254', '\113', '\110', '\152', '\025', '\017', '\205', '\035', - '\262', '\260', '\011', '\355', '\355', '\035', '\356', '\355', - '\335', '\323', '\067', '\334', '\327', '\207', '\113', '\157', - '\250', '\235', '\253', '\006', '\131', '\050', '\204', '\150', - '\070', '\354', '\103', '\213', '\006', '\371', '\062', '\024', - '\017', '\015', '\332', '\172', '\166', '\313', '\355', '\272', - '\240', '\011', '\135', '\207', '\271', '\251', '\207', '\367', - '\017', '\040', '\233', '\165', '\361', '\007', '\315', '\045', - '\060', '\210', '\332', '\007', '\206', '\120', '\173', '\124', - '\067', '\334', '\147', '\135', '\254', '\154', '\326', '\305', - '\052', '\264', '\315', '\352', '\227', '\060', '\364', '\072', - '\017', '\100', '\017', '\075', '\324', '\027', '\102', '\017', - '\205', '\302', '\201', '\176', '\074', '\243', '\363', '\240', - '\121', '\266', '\272', '\004', '\262', '\003', '\101', '\310', - '\372', '\273', '\132', '\203', '\010', '\265', '\164', '\111', - '\077', '\367', '\036', '\264', '\056', '\266', '\136', '\307', - '\301', '\341', '\340', '\341', '\216', '\103', '\050', '\257', - '\045', '\070', '\074', '\030', '\154', '\356', '\302', '\005', - '\175', '\160', '\250', '\007', '\265', '\077', '\324', '\203', - '\076', '\355', '\355', '\105', '\237', '\366', '\365', '\165', - '\240', '\345', '\341', '\275', '\334', '\362', '\166', '\036', - '\313', '\066', '\036', '\113', '\214', '\114', '\137', '\010', - '\345', '\205', '\302', '\170', '\106', '\050', '\204', '\147', - '\070', '\153', '\140', '\367', '\001', '\372', '\245', '\163', - '\000', '\011', '\201', '\241', '\175', '\075', '\303', '\203', - '\001', '\024', '\145', '\075', '\243', '\273', '\007', '\227', - '\236', '\336', '\340', '\020', '\102', '\150', '\171', '\117', - '\357', '\356', '\000', '\102', '\273', '\203', '\010', '\101', - '\257', '\163', '\010', '\172', '\126', '\216', '\120', '\330', - '\172', '\170', '\013', '\107', '\233', '\371', '\342', '\030', - '\337', '\176', '\056', '\236', '\057', '\255', '\350', '\335', - '\201', '\026', '\276', '\130', '\323', '\307', '\214', '\145', - '\237', '\065', '\334', '\241', '\075', '\241', '\041', '\204', - '\302', '\103', '\350', '\253', '\001', '\356', '\277', '\101', - '\351', '\077', '\015', '\331', '\263', '\023', '\063', '\054', - '\300', '\005', '\130', '\163', '\050', '\320', '\217', '\147', - '\004', '\017', '\242', '\006', '\001', '\251', '\013', '\372', - '\064', '\320', '\217', '\076', '\015', '\036', '\104', '\152', - '\327', '\041', '\244', '\166', '\015', '\240', '\345', '\201', - '\176', '\074', '\067', '\170', '\020', '\025', '\077', '\020', - '\262', '\056', '\373', '\172', '\372', '\103', '\241', '\216', - '\336', '\376', '\160', '\230', '\327', '\332', '\163', '\272', - '\046', '\112', '\100', '\033', '\070', '\006', '\306', '\100', - '\076', '\326', '\310', '\172', '\320', '\010', '\216', '\200', - '\021', '\360', '\056', '\050', '\100', '\246', '\047', '\301', - '\063', '\340', '\115', '\220', '\003', '\133', '\367', '\010', - '\350', '\001', '\077', '\003', '\037', '\200', '\002', '\330', - '\272', '\047', '\301', '\363', '\340', '\115', '\060', '\167', - '\032', '\164', '\300', '\041', '\160', '\012', '\344', '\144', - '\042', '\016', '\016', '\201', '\177', '\006', '\331', '\131', - '\260', '\211', '\040', '\000', '\116', '\200', '\050', '\050', - '\201', '\361', '\154', '\003', '\107', '\300', '\033', '\331', - '\142', '\370', '\112', '\100', '\043', '\070', '\006', '\076', - '\000', '\167', '\301', '\320', '\325', '\200', '\037', '\200', - '\067', '\101', '\316', '\115', '\050', '\007', '\364', '\200', - '\023', '\040', '\012', '\112', '\162', '\120', '\016', '\070', - '\016', '\306', '\101', '\011', '\354', '\135', '\033', '\070', - '\006', '\306', '\300', '\342', '\131', '\260', '\214', '\340', - '\010', '\210', '\200', '\374', '\134', '\242', '\155', '\140', - '\010', '\274', '\001', '\062', '\140', '\144', '\312', '\100', - '\033', '\070', '\016', '\306', '\101', '\011', '\214', '\122', - '\045', '\030', '\002', '\307', '\301', '\171', '\260', '\370', - '\063', '\250', '\013', '\170', '\021', '\234', '\007', '\105', - '\163', '\240', '\003', '\216', '\200', '\010', '\050', '\232', - '\213', '\070', '\010', '\203', '\343', '\340', '\143', '\160', - '\317', '\074', '\354', '\033', '\340', '\207', '\040', '\002', - '\012', '\156', '\046', '\052', '\007', '\317', '\200', '\067', - '\301', '\334', '\133', '\320', '\117', '\340', '\020', '\030', - '\271', '\205', '\007', '\205', '\150', '\045', '\350', '\000', - '\317', '\202', '\023', '\340', '\014', '\210', '\202', '\374', - '\133', '\221', '\006', '\332', '\300', '\161', '\360', '\061', - '\050', '\376', '\054', '\372', '\013', '\034', '\003', '\347', - '\301', '\342', '\317', '\241', '\216', '\340', '\105', '\160', - '\036', '\054', '\056', '\100', '\034', '\274', '\010', '\316', - '\202', '\271', '\267', '\141', '\314', '\101', '\017', '\070', - '\001', '\242', '\340', '\236', '\371', '\104', '\176', '\360', - '\103', '\360', '\001', '\130', '\124', '\210', '\375', '\010', - '\034', '\002', '\047', '\100', '\024', '\254', '\304', '\306', - '\126', '\015', '\236', '\001', '\247', '\100', '\316', '\355', - '\310', '\007', '\252', '\301', '\017', '\300', '\273', '\240', - '\140', '\001', '\321', '\217', '\320', '\167', '\137', '\102', - '\137', '\075', '\211', '\360', '\361', '\265', '\104', '\131', - '\230', '\164', '\271', '\053', '\211', '\012', '\127', '\021', - '\255', '\342', '\262', '\320', '\337', '\343', '\030', '\373', - '\261', '\164', '\201', '\303', '\054', '\343', '\064', '\326', - '\141', '\135', '\053', '\017', '\046', '\150', '\341', '\070', - '\121', '\151', '\224', '\250', '\163', '\202', '\150', '\242', - '\023', '\172', '\245', '\320', '\207', '\336', '\130', '\256', - '\300', '\141', '\226', '\161', '\032', '\353', '\260', '\056', - '\347', '\341', '\274', '\124', '\014', '\120', '\026', '\101', - '\147', '\104', '\363', '\360', '\163', '\106', '\360', '\274', - '\010', '\150', '\304', '\263', '\113', '\170', '\036', '\143', - '\276', '\317', '\002', '\131', '\146', '\137', '\212', '\000', - '\224', '\101', '\050', '\057', '\200', '\162', '\043', '\140', - '\274', '\124', '\236', '\303', '\375', '\020', '\321', '\262', - '\306', '\101', '\007', '\062', '\255', '\002', '\205', '\310', - '\210', '\151', '\145', '\371', '\006', '\061', '\135', '\153', - '\061', '\031', '\312', '\004', '\236', '\320', '\052', '\161', - '\070', '\226', '\076', '\231', '\066', '\135', '\237', '\023', - '\056', '\233', '\250', '\312', '\362', '\065', '\357', '\023', - '\123', '\224', '\353', '\174', '\146', '\361', '\024', '\145', - '\230', '\162', '\247', '\172', '\146', '\200', '\233', '\214', - '\373', '\354', '\114', '\222', '\235', '\067', '\137', '\033', - '\222', '\046', '\351', '\334', '\035', '\074', '\116', '\277', - '\313', '\222', '\364', '\070', '\350', '\207', '\130', '\226', - '\350', '\074', '\204', '\171', '\265', '\066', '\303', '\206', - '\323', '\326', '\315', '\115', '\204', '\145', '\116', '\035', - '\316', '\363', '\366', '\076', '\233', '\263', '\230', '\207', - '\261', '\116', '\033', '\043', '\167', '\312', '\130', '\307', - '\231', '\007', '\217', '\266', '\130', '\010', '\333', '\261', - '\020', '\145', '\056', '\104', '\235', '\027', '\242', '\275', - '\337', '\207', '\254', '\012', '\274', '\223', '\153', '\353', - '\060', '\261', '\122', '\001', '\142', '\213', '\121', '\164', - '\326', '\050', '\346', '\332', '\050', '\352', '\062', '\212', - '\001', '\034', '\105', '\173', '\106', '\241', '\070', '\132', - '\152', '\303', '\172', '\011', '\355', '\066', '\235', '\014', - '\062', '\226', '\302', '\256', '\201', '\074', '\120', '\004', - '\312', '\100', '\000', '\104', '\227', '\332', '\072', '\214', - '\171', '\256', '\145', '\164', '\101', '\316', '\045', '\314', - '\073', '\120', '\002', '\032', '\101', '\004', '\214', '\200', - '\250', '\003', '\326', '\113', '\176', '\156', '\031', '\115', - '\015', '\367', '\347', '\172', '\264', '\175', '\263', '\113', - '\306', '\253', '\314', '\314', '\207', '\102', '\141', '\304', - '\065', '\065', '\247', '\156', '\225', '\076', '\345', '\271', - '\074', '\226', '\045', '\363', '\200', '\345', '\316', '\076', - '\147', '\106', '\350', '\352', '\230', '\366', '\215', '\244', - '\137', '\235', '\344', '\366', '\160', '\331', '\354', '\157', - '\137', '\301', '\175', '\032', '\052', '\375', '\111', '\005', - '\321', '\274', '\315', '\104', '\277', '\332', '\112', '\264', - '\245', '\034', '\154', '\101', '\030', '\314', '\103', '\370', - '\023', '\310', '\246', '\041', '\355', '\012', '\164', '\134', - '\145', '\132', '\267', '\344', '\362', '\156', '\020', '\063', - '\104', '\146', '\175', '\104', '\025', '\263', '\156', '\226', - '\241', '\316', '\113', '\323', '\022', '\206', '\322', '\102', - '\207', '\221', '\306', '\135', '\102', '\064', '\135', '\230', - '\310', '\022', '\142', '\271', '\066', '\227', '\146', '\331', - '\372', '\206', '\210', '\313', '\266', '\173', '\363', '\141', - '\157', '\147', '\025', '\210', '\315', '\163', '\302', '\062', - '\116', '\063', '\366', '\222', '\363', '\260', '\335', '\162', - '\332', '\074', '\306', '\330', '\074', '\047', '\054', '\063', - '\351', '\306', '\146', '\106', '\364', '\171', '\277', '\305', - '\230', '\317', '\131', '\106', '\364', '\163', '\234', '\127', - '\332', '\301', '\154', '\330', '\351', '\167', '\060', '\137', - '\047', '\240', '\363', '\213', '\271', '\066', '\377', '\215', - '\275', '\352', '\137', '\356', '\021', '\173', '\154', '\306', - '\227', '\165', '\056', '\255', '\040', '\372', '\115', '\053', - '\321', '\377', '\340', '\204', '\161', '\245', '\001', '\166', - '\141', '\047', '\321', '\107', '\115', '\222', '\376', '\376', - '\275', '\066', '\227', '\161', '\226', '\171', '\277', '\231', - '\350', '\164', '\207', '\075', '\217', '\306', '\165', '\257', - '\315', '\254', '\204', '\237', '\277', '\215', '\350', '\303', - '\207', '\260', '\056', '\313', '\204', '\064', '\345', '\071', - '\310', '\277', '\201', '\061', '\177', '\013', '\174', '\163', - '\273', '\055', '\267', '\332', '\221', '\053', '\066', '\170', - '\042', '\046', '\044', '\217', '\347', '\325', '\344', '\234', - '\277', '\314', '\065', '\065', '\235', '\152', '\100', '\371', - '\236', '\112', '\207', '\327', '\106', '\062', '\123', '\315', - '\251', '\251', '\364', '\230', '\007', '\261', '\077', '\256', - '\173', '\224', '\350', '\141', '\234', '\011', '\313', '\321', - '\267', '\065', '\360', '\133', '\066', '\303', '\117', '\172', - '\145', '\102', '\312', '\347', '\073', '\307', '\131', '\316', - '\351', '\254', '\307', '\372', '\234', '\157', '\047', '\306', - '\253', '\356', '\067', '\104', '\173', '\321', '\337', '\055', - '\350', '\127', '\057', '\366', '\365', '\212', '\053', '\030', - '\347', '\011', '\261', '\337', '\174', '\347', '\070', '\313', - '\071', '\235', '\365', '\130', '\237', '\363', '\161', '\172', - '\052', '\270', '\275', '\127', '\113', '\117', '\145', '\067', - '\234', '\355', '\115', '\245', '\063', '\242', '\375', '\126', - '\231', '\056', '\355', '\132', '\017', '\137', '\156', '\355', - '\154', '\151', '\117', '\147', '\247', '\366', '\167', '\247', - '\304', '\131', '\316', '\351', '\254', '\307', '\372', '\246', - '\277', '\331', '\046', '\361', '\230', '\263', '\215', '\372', - '\127', '\314', '\273', '\223', '\273', '\345', '\231', '\235', - '\372', '\154', '\216', '\263', '\174', '\052', '\033', '\346', - '\334', '\003', '\223', '\367', '\074', '\347', '\276', '\310', - '\353', '\167', '\252', '\165', '\353', '\304', '\244', '\263', - '\056', '\307', '\135', '\331', '\211', '\270', '\225', '\144', - '\271', '\225', '\277', '\324', '\306', '\254', '\355', '\367', - '\126', '\044', '\142', '\344', '\116', '\135', '\143', '\227', - '\330', '\036', '\375', '\104', '\155', '\121', '\262', '\035', - '\142', '\331', '\117', '\034', '\076', '\202', '\261', '\115', - '\306', '\046', '\045', '\267', '\311', '\330', '\237', '\344', - '\266', '\261', '\056', '\347', '\341', '\064', '\153', '\363', - '\110', '\341', '\073', '\261', '\357', '\136', '\006', '\212', - '\240', '\237', '\007', '\262', '\371', '\175', '\210', '\276', - '\277', '\140', '\073', '\156', '\275', '\176', '\340', '\212', - '\354', '\207', '\156', '\251', '\370', '\112', '\154', '\173', - '\046', '\162', '\005', '\266', '\101', '\074', '\106', '\307', - '\221', '\367', '\171', '\060', '\200', '\114', '\041', '\227', - '\354', '\315', '\256', '\024', '\317', '\266', '\034', '\053', - '\370', '\360', '\001', '\354', '\161', '\145', '\372', '\176', - '\205', '\337', '\011', '\360', '\161', '\101', '\335', '\224', - '\304', '\147', '\257', '\262', '\237', '\315', '\004', '\330', - '\347', '\343', '\147', '\147', '\312', '\073', '\030', '\076', - '\003', '\025', '\150', '\261', '\354', '\363', '\245', '\153', - '\177', '\014', '\243', '\300', '\357', '\140', '\016', '\316', - '\304', '\372', '\313', '\232', '\145', '\217', '\051', '\207', - '\131', '\306', '\151', '\303', '\111', '\143', '\372', '\321', - '\062', '\261', '\163', '\245', '\010', '\277', '\215', '\347', - '\216', '\176', '\125', '\340', '\060', '\313', '\070', '\215', - '\165', '\214', '\376', '\105', '\074', '\354', '\062', '\373', - '\213', '\070', '\243', '\114', '\107', '\131', '\267', '\362', - '\332', '\045', '\307', '\037', '\107', '\356', '\100', '\273', - '\140', '\227', '\163', '\120', '\306', '\070', '\362', '\217', - '\055', '\204', '\175', '\106', '\236', '\113', '\271', '\272', - '\237', '\103', '\247', '\224', '\347', '\112', '\261', '\370', - '\173', '\226', '\351', '\322', '\100', '\016', '\354', '\100', - '\001', '\046', '\103', '\024', '\341', '\161', '\060', '\066', - '\212', '\166', '\237', '\224', '\075', '\232', '\367', '\017', - '\366', '\343', '\070', '\374', '\063', '\074', '\373', '\365', - '\174', '\273', '\136', '\034', '\146', '\031', '\247', '\261', - '\016', '\353', '\162', '\330', '\332', '\267', '\325', '\137', - '\346', '\071', '\160', '\036', '\347', '\223', '\263', '\017', - '\114', '\266', '\171', '\054', '\343', '\264', '\061', '\035', - '\143', '\263', '\337', '\323', '\174', '\351', '\150', '\327', - '\051', '\354', '\023', '\063', '\245', '\357', '\072', '\321', - '\366', '\122', '\220', '\311', '\203', '\240', '\173', '\133', - '\036', '\045', '\322', '\146', '\372', '\002', '\244', '\073', - '\237', '\125', '\072', '\031', '\336', '\223', '\170', '\355', - '\363', '\270', '\226', '\220', '\275', '\207', '\063', '\074', - '\077', '\347', '\140', '\314', '\267', '\302', '\256', '\314', - '\301', '\144', '\371', '\167', '\334', '\013', '\127', '\112', - '\037', '\345', '\275', '\053', '\014', '\175', '\014', '\370', - '\216', '\364', '\060', '\372', '\240', '\007', '\025', '\350', - '\050', '\224', '\374', '\227', '\221', '\377', '\022', '\333', - '\014', '\356', '\177', '\246', '\324', '\366', '\073', '\330', - '\107', '\033', '\143', '\142', '\172', '\177', '\317', '\336', - '\237', '\070', '\277', '\345', '\107', '\317', '\227', '\065', - '\063', '\222', '\156', '\367', '\077', '\267', '\367', '\177', - '\265', '\314', '\053', '\346', '\034', '\204', '\064', '\230', - '\173', '\302', '\120', '\023', '\216', '\204', '\224', '\103', - '\072', '\111', '\013', '\165', '\356', '\146', '\331', '\171', - '\047', '\222', '\355', '\223', '\372', '\340', '\061', '\336', - '\307', '\264', '\333', '\346', '\253', '\355', '\163', '\241', - '\355', '\373', '\321', '\256', '\154', '\264', '\213', '\137', - '\156', '\132', '\167', '\354', '\355', '\331', '\330', '\363', - '\213', '\127', '\243', '\154', '\054', '\246', '\062', '\234', - '\143', '\003', '\274', '\230', '\246', '\311', '\142', '\212', - '\333', '\113', '\265', '\035', '\023', '\272', '\206', '\271', - '\135', '\326', '\071', '\250', '\123', '\347', '\026', '\356', - '\221', '\122', '\131', '\243', '\274', '\306', '\314', '\001', - '\212', '\333', '\376', '\072', '\374', '\211', '\356', '\112', - '\361', '\323', '\234', '\244', '\103', '\226', '\211', '\171', - '\233', '\303', '\147', '\131', '\064', '\262', '\070', '\123', - '\354', '\075', '\333', '\153', '\316', '\067', '\121', '\052', - '\066', '\235', '\363', '\246', '\053', '\153', '\334', '\260', - '\021', '\215', '\230', '\106', '\030', '\334', '\002', '\364', - '\111', '\311', '\254', '\044', '\137', '\025', '\165', '\171', - '\351', '\050', '\174', '\305', '\137', '\311', '\175', '\332', - '\033', '\104', '\067', '\035', '\111', '\175', '\067', '\172', - '\174', '\377', '\103', '\375', '\107', '\313', '\267', '\050', - '\024', '\333', '\370', '\273', '\057', '\310', '\132', '\147', - '\173', '\176', '\332', '\341', '\063', '\161', '\230', '\145', - '\234', '\306', '\072', '\121', '\355', '\123', '\247', '\017', - '\167', '\335', '\317', '\352', '\264', '\175', '\072', '\227', - '\332', '\256', '\054', '\131', '\106', '\074', '\125', '\254', - '\261', '\357', '\124', '\163', '\300', '\161', '\270', '\003', - '\144', '\216', '\042', '\225', '\312', '\325', '\362', '\304', - '\034', '\173', '\045', '\313', '\370', '\030', '\362', '\221', - '\332', '\016', '\143', '\023', '\314', '\131', '\252', '\033', - '\254', '\321', '\071', '\073', '\207', '\327', '\112', '\251', - '\334', '\027', '\252', '\274', '\333', '\241', '\153', '\316', - '\133', '\271', '\210', '\014', '\202', '\323', '\050', '\153', - '\224', '\022', '\333', '\306', '\161', '\226', '\163', '\072', - '\353', '\231', '\074', '\351', '\051', '\060', '\365', '\114', - '\225', '\236', '\233', '\202', '\344', '\275', '\075', '\225', - '\236', '\013', '\215', '\235', '\170', '\105', '\130', '\360', - '\075', '\242', '\357', '\035', '\115', '\204', '\145', '\046', - '\075', '\031', '\053', '\257', '\261', '\025', '\277', '\007', - '\234', '\067', '\125', '\273', '\222', '\333', '\237', '\252', - '\376', '\251', '\332', '\173', '\255', '\202', '\115', '\271', - '\327', '\052', '\070', '\271', '\134', '\313', '\347', '\312', - '\025', '\337', '\215', '\277', '\063', '\274', '\172', '\216', - '\150', '\321', '\277', '\141', '\257', '\347', '\367', '\156', - '\260', '\013', '\105', '\151', '\222', '\306', '\167', '\266', - '\265', '\354', '\357', '\055', '\236', '\001', '\133', '\305', - '\357', '\206', '\242', '\366', '\171', '\210', '\355', '\314', - '\153', '\260', '\115', '\357', '\275', '\243', '\176', '\373', - '\333', '\142', '\127', '\043', '\131', '\211', '\076', '\041', - '\353', '\355', '\057', '\025', '\337', '\227', '\111', '\036', - '\257', '\045', '\107', '\023', '\371', '\143', '\217', '\127', - '\304', '\261', '\316', '\170', '\235', '\360', '\032', '\167', - '\025', '\021', '\375', '\322', '\153', '\343', '\252', '\024', - '\062', '\141', '\313', '\362', '\063', '\165', '\117', '\120', - '\077', '\324', '\072', '\027', '\152', '\076', '\313', '\166', - '\244', '\260', '\001', '\321', '\121', '\373', '\375', '\031', - '\347', '\147', '\077', '\146', '\266', '\256', '\363', '\307', - '\300', '\123', '\240', '\207', '\344', '\333', '\025', '\357', - '\177', '\171', '\240', '\330', '\364', '\177', '\206', '\354', - '\107', '\226', '\001', '\300', '\363', '\331', '\201', '\162', - '\256', '\177', '\164', '\043', '\105', '\135', '\302', '\170', - '\272', '\356', '\115', '\272', '\377', '\107', '\162', '\325', - '\326', '\027', '\252', '\341', '\340', '\115', '\246', '\040', - '\161', '\137', '\073', '\225', '\043', '\070', '\353', '\167', - '\016', '\376', '\375', '\071', '\330', '\360', '\127', '\261', - '\257', '\026', '\314', '\322', '\263', '\057', '\316', '\175', - '\271', '\035', '\322', '\077', '\316', '\167', '\200', '\334', - '\166', '\143', '\117', '\131', '\166', '\021', '\106', '\344', - '\042', '\346', '\301', '\107', '\060', '\102', '\243', '\053', - '\344', '\074', '\314', '\371', '\047', '\116', '\112', '\137', - '\160', '\031', '\311', '\076', '\261', '\231', '\277', '\251', - '\316', '\354', '\123', '\371', '\300', '\116', '\337', '\330', - '\320', '\241', '\375', '\161', '\022', '\317', '\353', '\126', - '\077', '\365', '\165', '\175', '\277', '\302', '\343', '\305', - '\276', '\306', '\142', '\345', '\002', '\360', '\252', '\214', - '\375', '\227', '\161', '\355', '\307', '\011', '\335', '\107', - '\007', '\301', '\013', '\340', '\077', '\035', '\276', '\366', - '\170', '\222', '\136', '\124', '\145', '\330', '\352', '\344', - '\354', '\245', '\363', '\141', '\314', '\350', '\151', '\175', - '\142', '\032', '\077', '\003', '\016', '\221', '\370', '\012', - '\231', '\012', '\257', '\337', '\200', '\372', '\136', '\021', - '\035', '\077', '\036', '\107', '\353', '\054', '\340', '\130', - '\333', '\054', '\073', '\001', '\126', '\246', '\313', '\060', - '\316', '\327', '\162', '\114', '\147', '\225', '\201', '\100', - '\261', '\116', '\252', '\257', '\040', '\317', '\175', '\162', - '\347', '\170', '\100', '\323', '\223', '\073', '\166', '\204', - '\271', '\210', '\164', '\336', '\060', '\056', '\045', '\316', - '\131', '\216', '\263', '\234', '\323', '\107', '\234', '\235', - '\174', '\055', '\033', '\164', '\203', '\306', '\175', '\222', - '\255', '\113', '\101', '\262', '\255', '\070', '\232', '\304', - '\037', '\333', '\126', '\360', '\372', '\166', '\055', '\260', - '\211', '\055', '\224', '\367', '\060', '\116', '\056', '\102', - '\147', '\166', '\221', '\115', '\262', '\115', '\310', '\302', - '\244', '\213', '\215', '\332', '\264', '\136', '\020', '\056', - '\305', '\154', '\132', '\043', '\211', '\171', '\002', '\072', - '\267', '\370', '\133', '\017', '\163', '\214', '\111', '\227', - '\363', '\030', '\163', '\102', '\277', '\315', '\374', '\043', - '\203', '\176', '\052', '\064', '\007', '\044', '\375', '\156', - '\063', '\142', '\316', '\122', '\271', '\372', '\036', '\134', - '\141', '\277', '\060', '\376', '\216', '\074', '\246', '\357', - '\140', '\012', '\345', '\154', '\011', '\167', '\363', '\272', - '\141', '\073', '\264', '\112', '\314', '\212', '\165', '\276', - '\353', '\270', '\116', '\054', '\277', '\305', '\045', '\353', - '\243', '\303', '\261', '\016', '\331', '\337', '\145', '\137', - '\223', '\373', '\074', '\267', '\115', '\356', '\034', '\147', - '\071', '\373', '\237', '\354', '\117', '\046', '\217', '\045', - '\307', '\131', '\316', '\351', '\331', '\272', '\056', '\330', - '\347', '\312', '\325', '\173', '\216', '\326', '\255', '\130', - '\237', '\023', '\157', '\257', '\336', '\071', '\136', '\242', - '\351', '\226', '\242', '\236', '\263', '\330', '\150', '\130', - '\367', '\174', '\262', '\013', '\056', '\320', '\161', '\355', - '\244', '\370', '\373', '\120', '\113', '\247', '\100', '\322', - '\263', '\065', '\270', '\112', '\373', '\346', '\106', '\372', - '\062', '\117', '\353', '\147', '\354', '\230', '\351', '\243', - '\353', '\355', '\323', '\033', '\171', '\166', '\362', '\270', - '\135', '\357', '\163', '\247', '\032', '\067', '\353', '\120', - '\317', '\233', '\032', '\357', '\065', '\173', '\061', '\117', - '\301', '\020', '\010', '\047', '\161', '\010', '\014', '\200', - '\127', '\100', '\076', '\157', '\200', '\306', '\210', '\071', - '\053', '\215', '\076', '\255', '\004', '\215', '\240', '\055', - '\211', '\016', '\260', '\077', '\046', '\357', '\222', '\366', - '\103', '\267', '\170', '\077', '\131', '\357', '\035', '\330', - '\134', '\271', '\034', '\360', '\231', '\175', '\166', '\232', - '\275', '\056', '\363', '\026', '\310', '\231', '\234', '\160', - '\106', '\267', '\214', '\077', '\006', '\172', '\244', '\224', - '\022', '\336', '\057', '\361', '\262', '\341', '\363', '\272', - '\205', '\163', '\155', '\216', '\312', '\231', '\174', '\114', - '\215', '\370', '\110', '\314', '\046', '\203', '\317', '\147', - '\031', '\102', '\136', '\232', '\160', '\356', '\234', '\274', - '\257', '\345', '\275', '\220', '\341', '\060', '\313', '\114', - '\272', '\321', '\347', '\274', '\231', '\230', '\127', '\071', - '\071', '\022', '\147', '\337', '\202', '\367', '\116', '\336', - '\067', '\077', '\175', '\100', '\375', '\052', '\344', '\377', - '\264', '\120', '\144', '\234', '\226', '\237', '\046', '\172', - '\234', '\207', '\363', '\362', '\006', '\302', '\266', '\341', - '\056', '\334', '\377', '\006', '\367', '\233', '\063', '\305', - '\067', '\300', '\366', '\115', '\070', '\266', '\320', '\347', - '\223', '\356', '\137', '\320', '\064', '\206', '\365', '\270', - '\357', '\363', '\161', '\306', '\357', '\120', '\366', '\317', - '\244', '\370', '\373', '\211', '\353', '\201', '\237', '\355', - '\174', '\337', '\132', '\224', '\146', '\363', '\174', '\201', - '\234', '\005', '\171', '\135', '\032', '\337', '\161', '\021', - '\316', '\255', '\163', '\347', '\312', '\172', '\346', '\167', - '\312', '\234', '\337', '\274', '\167', '\344', '\063', '\045', - '\303', '\347', '\313', '\022', '\314', '\213', '\027', '\060', - '\271', '\322', '\043', '\230', '\122', '\035', '\122', '\026', - '\177', '\367', '\340', '\167', '\243', '\313', '\227', '\213', - '\377', '\311', '\147', '\113', '\316', '\307', '\276', '\016', - '\237', '\057', '\271', '\114', '\076', '\247', '\166', '\127', - '\312', '\371', '\223', '\357', '\346', '\334', '\152', '\316', - '\237', '\043', '\111', '\357', '\050', '\127', '\316', '\227', - '\162', '\370', '\254', '\372', '\032', '\306', '\250', '\352', - '\035', '\271', '\233', '\263', '\053', '\247', '\133', '\176', - '\154', '\172', '\352', '\357', '\070', '\154', '\063', '\123', - '\245', '\245', '\174', '\027', '\353', '\260', '\135', '\251', - '\164', '\314', '\226', '\271', '\112', '\327', '\244', '\365', - '\275', '\042', '\327', '\366', '\101', '\212', '\215', '\217', - '\310', '\357', '\327', '\170', '\001', '\263', '\361', '\050', - '\222', '\171', '\134', '\250', '\113', '\151', '\102', '\337', - '\223', '\106', '\325', '\316', '\133', '\066', '\137', '\333', - '\077', '\306', '\176', '\035', '\373', '\202', '\150', '\147', - '\204', '\035', '\230', '\010', '\131', '\016', '\214', '\071', - '\003', '\073', '\267', '\156', '\376', '\046', '\127', '\105', - '\362', '\215', '\216', '\277', '\325', '\131', '\337', '\354', - '\062', '\344', '\033', '\136', '\374', '\154', '\023', '\113', - '\204', '\353', '\356', '\374', '\046', '\147', '\175', '\243', - '\313', '\322', '\157', '\166', '\005', '\372', '\015', '\257', - '\330', '\161', '\346', '\321', '\347', '\072', '\035', '\300', - '\250', '\176', '\233', '\053', '\323', '\157', '\165', '\171', - '\372', '\355', '\056', '\303', '\361', '\255', '\156', '\322', - '\167', '\276', '\261', '\304', '\157', '\162', '\043', '\372', - '\255', '\256', '\121', '\277', '\335', '\361', '\067', '\274', - '\034', '\375', '\126', '\147', '\175', '\257', '\053', '\024', - '\110', '\307', '\214', '\273', '\201', '\277', '\311', '\361', - '\267', '\071', '\376', '\106', '\227', '\162', '\334', '\073', - '\047', '\217', '\143', '\362', '\373', '\157', '\236', '\263', - '\051', '\347', '\200', '\266', '\167', '\204', '\256', '\361', - '\235', '\056', '\251', '\175', '\327', '\372', '\136', '\227', - '\055', '\115', '\111', '\060', '\251', '\255', '\064', '\331', - '\336', '\177', '\213', '\344', '\147', '\150', '\033', '\110', - '\176', '\234', '\146', '\060', '\357', '\344', '\222', '\367', - '\002', '\247', '\315', '\177', '\071', '\111', '\376', '\226', - '\162', '\322', '\361', '\056', '\342', '\232', '\147', '\341', - '\353', '\074', '\323', '\033', '\302', '\074', '\317', '\161', - '\366', '\374', '\071', '\174', '\332', '\017', '\247', '\313', - '\357', '\124', '\326', '\344', '\247', '\030', '\037', '\265', - '\107', '\001', '\204', '\317', '\267', '\020', '\135', '\176', - '\233', '\350', '\112', '\251', '\356', '\371', '\352', '\223', - '\235', '\156', '\237', '\142', '\134', '\262', '\022', '\011', - '\134', '\217', '\137', '\153', '\374', '\337', '\353', '\364', - '\143', '\015', '\146', '\177', '\060', '\347', '\250', '\076', - '\264', '\245', '\033', '\363', '\071', '\210', '\011', '\370', - '\323', '\163', '\302', '\355', '\010', '\317', '\051', '\026', - '\133', '\037', '\235', '\042', '\217', '\341', '\132', '\347', - '\117', '\363', '\316', '\325', '\231', '\247', '\325', '\061', - '\027', '\256', '\207', '\002', '\235', '\107', '\243', '\216', - '\161', '\067', '\373', '\377', '\325', '\160', '\372', '\014', - '\234', '\127', '\176', '\107', '\370', '\035', '\062', '\177', - '\056', '\110', '\322', '\341', '\100', '\114', '\303', '\146', - '\226', '\205', '\047', '\115', '\247', '\031', '\164', '\023', - '\066', '\246', '\231', '\160', '\050', '\162', '\255', '\337', - '\023', '\176', '\206', '\346', '\300', '\143', '\231', '\107', - '\067', '\323', '\055', '\160', '\304', '\156', '\245', '\317', - '\322', '\347', '\120', '\233', '\333', '\340', '\074', '\024', - '\302', '\340', '\335', '\116', '\013', '\150', '\041', '\066', - '\366', '\317', '\323', '\035', '\330', '\337', '\026', '\323', - '\235', '\264', '\204', '\276', '\110', '\167', '\321', '\335', - '\364', '\045', '\372', '\062', '\014', '\304', '\122', '\034', - '\202', '\226', '\321', '\075', '\164', '\057', '\055', '\247', - '\373', '\120', '\243', '\025', '\164', '\077', '\075', '\000', - '\247', '\341', '\253', '\130', '\015', '\245', '\230', '\055', - '\253', '\351', '\101', '\132', '\103', '\153', '\151', '\035', - '\175', '\215', '\036', '\242', '\365', '\130', '\017', '\017', - '\323', '\237', '\321', '\043', '\364', '\165', '\332', '\110', - '\233', '\150', '\063', '\075', '\212', '\023', '\372', '\343', - '\124', '\116', '\133', '\350', '\033', '\264', '\225', '\266', - '\321', '\166', '\172', '\202', '\276', '\111', '\117', '\142', - '\375', '\074', '\105', '\025', '\124', '\111', '\156', '\332', - '\001', '\333', '\130', '\115', '\036', '\332', '\111', '\273', - '\250', '\206', '\152', '\351', '\317', '\261', '\256', '\274', - '\124', '\107', '\365', '\324', '\200', '\223', '\341', '\156', - '\362', '\121', '\023', '\371', '\251', '\231', '\132', '\320', - '\177', '\155', '\324', '\116', '\173', '\150', '\057', '\172', - '\145', '\037', '\355', '\307', '\232', '\014', '\120', '\220', - '\272', '\250', '\033', '\247', '\377', '\136', '\352', '\243', - '\020', '\205', '\351', '\000', '\365', '\323', '\101', '\234', - '\022', '\017', '\323', '\000', '\015', '\322', '\020', '\015', - '\323', '\137', '\320', '\323', '\364', '\014', '\375', '\045', - '\375', '\025', '\375', '\065', '\075', '\153', '\365', '\234', - '\371', '\175', '\330', '\242', '\264', '\077', '\361', '\047', - '\260', '\037', '\052', '\377', '\337', '\345', '\076', '\350', - '\022', '\322', '\310', '\376', '\075', '\042', '\377', '\316', - '\231', '\177', '\362', '\206', '\355', '\315', '\162', '\245', - '\127', '\200', '\115', '\044', '\357', '\260', '\174', '\152', - '\043', '\370', '\135', '\142', '\077', '\170', '\026', '\274', - '\004', '\136', '\003', '\157', '\221', '\154', '\271', '\374', - '\116', '\144', '\246', '\113', '\176', '\307', '\270', '\030', - '\054', '\003', '\153', '\300', '\106', '\360', '\024', '\360', - '\200', '\335', '\240', '\025', '\164', '\201', '\303', '\340', - '\273', '\340', '\373', '\340', '\357', '\301', '\011', '\227', - '\274', '\163', '\376', '\065', '\070', '\017', '\076', '\005', - '\323', '\121', '\301', '\231', '\340', '\146', '\160', '\033', - '\270', '\023', '\054', '\117', '\223', '\075', '\274', '\034', - '\170', '\300', '\156', '\320', '\005', '\016', '\203', '\357', - '\202', '\277', '\003', '\077', '\006', '\057', '\203', '\177', - '\002', '\277', '\004', '\377', '\001', '\042', '\340', '\175', - '\160', '\021', '\104', '\101', '\032', '\154', '\373', '\114', - '\060', '\207', '\337', '\273', '\200', '\205', '\340', '\356', - '\164', '\371', '\035', '\332', '\172', '\360', '\050', '\250', - '\000', '\265', '\240', '\015', '\004', '\323', '\345', '\175', - '\370', '\163', '\340', '\050', '\370', '\021', '\370', '\051', - '\370', '\005', '\070', '\003', '\316', '\202', '\377', '\002', - '\037', '\202', '\014', '\354', '\151', '\063', '\300', '\274', - '\014', '\371', '\155', '\346', '\142', '\360', '\145', '\360', - '\200', '\176', '\067', '\175', '\030', '\154', '\007', '\165', - '\240', '\025', '\364', '\201', '\141', '\360', '\267', '\340', - '\045', '\360', '\062', '\170', '\035', '\274', '\005', '\042', - '\340', '\002', '\270', '\004', '\246', '\361', '\267', '\063', - '\160', '\007', '\050', '\001', '\233', '\300', '\267', '\100', - '\043', '\350', '\004', '\117', '\203', '\027', '\300', '\061', - '\360', '\052', '\370', '\065', '\070', '\007', '\056', '\200', - '\117', '\200', '\213', '\177', '\373', '\011', '\346', '\202', - '\333', '\300', '\027', '\063', '\305', '\057', '\277', '\037', - '\254', '\006', '\137', '\007', '\345', '\374', '\035', '\010', - '\064', '\200', '\156', '\360', '\064', '\170', '\021', '\374', - '\003', '\070', '\015', '\316', '\200', '\337', '\202', '\013', - '\340', '\062', '\277', '\350', '\302', '\236', '\065', '\003', - '\314', '\001', '\267', '\203', '\045', '\354', '\267', '\203', - '\325', '\140', '\023', '\330', '\002', '\052', '\301', '\116', - '\260', '\033', '\154', '\253', '\320', '\337', '\256', '\233', - '\100', '\105', '\235', '\273', '\351', '\333', '\344', '\366', - '\371', '\032', '\132', '\345', '\052', '\202', '\035', '\356', - '\046', '\117', '\165', '\205', '\010', '\252', '\033', '\132', - '\353', '\047', '\011', '\046', '\253', '\065', '\067', '\046', - '\105', '\125', '\245', '\301', '\355', '\267', '\056', '\046', - '\272', '\253', '\241', '\251', '\326', '\337', '\036', '\017', - '\030', '\261', '\337', '\337', '\120', '\127', '\341', '\365', - '\354', '\364', '\127', '\124', '\065', '\370', '\352', '\075', - '\276', '\051', '\104', '\011', '\252', '\276', '\332', '\135', - '\065', '\311', '\272', '\116', '\131', '\202', '\162', '\123', - '\155', '\265', '\307', '\031', '\116', '\110', '\364', '\173', - '\074', '\216', '\240', '\111', '\152', '\253', '\150', '\152', - '\254', '\365', '\271', '\275', '\216', '\240', '\044', '\125', - '\171', '\352', '\375', '\050', '\276', '\321', '\357', '\163', - '\004', '\065', '\251', '\326', '\127', '\345', '\365', '\350', - '\115', '\105', '\336', '\206', '\052', '\275', '\252', '\240', - '\141', '\347', '\116', '\176', '\112', '\363', '\056', '\107', - '\120', '\223', '\174', '\015', '\115', '\115', '\162', '\165', - '\010', '\052', '\174', '\236', '\026', '\217', '\257', '\311', - '\223', '\030', '\163', '\050', '\324', '\270', '\153', '\175', - '\166', '\110', '\022', '\252', '\153', '\335', '\165', '\015', - '\365', '\325', '\025', '\122', '\144', '\102', '\114', '\025', - '\032', '\374', '\114', '\074', '\202', '\126', '\352', '\315', - '\210', '\232', '\167', '\240', '\015', '\062', '\061', '\234', - '\021', '\115', '\366', '\271', '\061', '\054', '\136', '\267', - '\157', '\227', '\307', '\031', '\166', '\046', '\066', '\325', - '\271', '\275', '\136', '\147', '\070', '\236', '\330', '\210', - '\111', '\142', '\075', '\057', '\036', '\224', '\044', '\117', - '\133', '\125', '\215', '\273', '\036', '\045', '\232', '\200', - '\210', '\167', '\172', '\075', '\315', '\076', '\271', '\212', - '\140', '\127', '\303', '\016', '\124', '\307', '\147', '\356', - '\052', '\154', '\256', '\333', '\321', '\056', '\127', '\021', - '\240', '\204', '\352', '\245', '\162', '\265', '\005', '\137', - '\221', '\253', '\012', '\074', '\156', '\237', '\137', '\256', - '\042', '\250', '\255', '\152', '\250', '\267', '\056', '\032', - '\365', '\041', '\044', '\075', '\150', '\007', '\045', '\311', - '\232', '\225', '\074', '\005', '\114', '\300', '\041', '\266', - '\046', '\133', '\074', '\344', '\110', '\340', '\211', '\146', - '\002', '\266', '\170', '\107', '\063', '\246', '\136', '\275', - '\043', '\250', '\111', '\336', '\012', '\164', '\001', '\146', - '\223', '\011', '\250', '\330', '\147', '\304', '\076', '\247', - '\270', '\316', '\135', '\317', '\150', '\244', '\266', '\272', - '\332', '\353', '\321', '\162', '\235', '\021', '\115', '\156', - '\150', '\306', '\154', '\262', '\256', '\042', '\150', '\364', - '\324', '\127', '\325', '\172', '\365', '\246', '\042', '\314', - '\167', '\277', '\107', '\157', '\052', '\362', '\066', '\067', - '\131', '\027', '\211', '\356', '\156', '\366', '\064', '\371', - '\153', '\121', '\246', '\114', '\221', '\304', '\250', '\250', - '\310', '\162', '\344', '\136', '\212', '\207', '\234', '\011', - '\126', '\077', '\331', '\101', '\147', '\022', '\367', '\124', - '\074', '\344', '\110', '\320', '\066', '\071', '\302', '\232', - '\350', '\367', '\126', '\170', '\141', '\120', '\342', '\001', - '\021', '\067', '\271', '\153', '\275', '\226', '\375', '\061', - '\001', '\025', '\357', '\020', '\023', '\046', '\065', '\117', - '\210', '\305', '\025', '\152', '\052', '\022', '\126', '\300', - '\044', '\111', '\134', '\321', '\032', '\320', '\270', '\222', - '\035', '\213', '\053', '\110', '\073', '\342', '\032', '\216', - '\150', '\134', '\005', '\266', '\062', '\236', '\156', '\302', - '\361', '\304', '\226', '\111', '\065', '\151', '\231', '\252', - '\046', '\065', '\350', '\016', '\114', '\013', '\275', '\253', - '\260', '\166', '\117', '\155', '\375', '\056', '\275', '\251', - '\250', '\021', '\135', '\355', '\323', '\233', '\021', '\371', - '\334', '\355', '\125', '\230', '\100', '\046', '\240', '\142', - '\277', '\333', '\147', '\135', '\044', '\352', '\347', '\365', - '\355', '\327', '\233', '\212', '\144', '\155', '\370', '\035', - '\353', '\302', '\337', '\320', '\350', '\354', '\221', '\304', - '\150', '\222', '\212', '\332', '\356', '\244', '\270', '\255', - '\224', '\140', '\341', '\223', '\005', '\266', '\232', '\065', - '\215', '\114', '\300', '\026', '\363', '\024', '\322', '\273', - '\012', '\175', '\036', '\271', '\110', '\264', '\331', '\254', - '\257', '\346', '\204', '\365', '\005', '\373', '\341', '\363', - '\170', '\275', '\356', '\170', '\100', '\305', '\146', '\331', - '\065', '\047', '\054', '\273', '\126', '\267', '\277', '\252', - '\106', '\256', '\042', '\150', '\303', '\176', '\120', '\047', - '\127', '\021', '\320', '\215', '\377', '\217', '\327', '\377', - '\001', '\226', '\047', '\030', '\162', '\200', '\067', '\000', - '\000', - -}; - -static const char file_6x13[] = { - '\037', '\213', '\010', '\010', '\126', '\121', '\054', '\100', - '\000', '\003', '\066', '\170', '\061', '\063', '\055', '\111', - '\123', '\117', '\070', '\070', '\065', '\071', '\055', '\061', - '\056', '\160', '\143', '\146', '\000', '\355', '\234', '\177', - '\170', '\024', '\307', '\171', '\307', '\277', '\002', '\001', - '\002', '\013', '\020', '\106', '\004', '\141', '\203', '\045', - '\333', '\330', '\306', '\066', '\262', '\045', '\014', '\030', - '\073', '\330', '\346', '\054', '\035', '\240', '\104', '\110', - '\030', '\111', '\061', '\070', '\151', '\345', '\343', '\156', - '\045', '\155', '\270', '\037', '\362', '\375', '\300', '\222', - '\215', '\101', '\010', '\044', '\204', '\114', '\012', '\051', - '\216', '\103', '\034', '\222', '\100', '\203', '\123', '\334', - '\342', '\032', '\327', '\264', '\265', '\023', '\307', '\165', - '\152', '\047', '\301', '\055', '\165', '\150', '\202', '\133', - '\352', '\322', '\230', '\076', '\365', '\037', '\364', '\251', - '\363', '\074', '\116', '\037', '\047', '\161', '\373', '\270', - '\245', '\337', '\331', '\335', '\071', '\215', '\206', '\335', - '\273', '\225', '\340', '\111', '\237', '\247', '\017', '\003', - '\237', '\331', '\331', '\335', '\171', '\147', '\346', '\175', - '\347', '\335', '\231', '\331', '\071', '\335', '\025', '\264', - '\205', '\073', '\047', '\002', '\050', '\040', '\143', '\110', - '\007', '\243', '\175', '\116', '\172', '\014', '\057', '\106', - '\170', '\304', '\130', '\240', '\120', '\236', '\063', '\021', - '\341', '\171', '\221', '\223', '\347', '\154', '\025', '\160', - '\174', '\002', '\120', '\242', '\334', '\077', '\274', '\004', - '\250', '\160', '\356', '\227', '\060', '\052', '\276', '\007', - '\130', '\346', '\234', '\157', '\247', '\354', '\354', '\373', - '\200', '\036', '\347', '\174', '\037', '\053', '\077', '\160', - '\277', '\335', '\000', '\131', '\337', '\222', '\172', '\373', - '\336', '\247', '\140', '\207', '\202', '\053', '\031', '\115', - '\027', '\211', '\253', '\141', '\227', '\134', '\060', '\237', - '\321', '\002', '\221', '\270', '\227', '\121', '\120', '\044', - '\076', '\313', '\150', '\225', '\110', '\174', '\236', '\221', - '\051', '\022', '\135', '\214', '\272', '\205', '\374', '\144', - '\121', '\257', '\110', '\210', '\053', '\273', '\105', '\102', - '\144', '\336', '\057', '\023', '\317', '\211', '\314', '\057', - '\062', '\172', '\111', '\134', '\131', '\112', '\176', '\040', - '\256', '\374', '\224', '\321', '\273', '\042', '\361', '\357', - '\214', '\176', '\041', '\022', '\277', '\141', '\064', '\107', - '\030', '\112', '\030', '\154', '\236', '\110', '\214', '\047', - '\325', '\114', '\024', '\054', '\146', '\264', '\121', '\134', - '\231', '\104', '\236', '\020', '\211', '\166', '\062', '\040', - '\363', '\000', '\173', '\231', '\134', '\336', '\330', '\320', - '\334', '\020', '\130', '\025', '\154', '\135', '\023', '\134', - '\121', '\327', '\324', '\274', '\146', '\235', '\270', '\324', - '\322', '\120', '\313', '\304', '\052', '\063', '\025', '\306', - '\362', '\300', '\252', '\272', '\372', '\165', '\255', '\042', - '\013', '\226', '\233', '\135', '\106', '\004', '\017', '\006', - '\353', '\126', '\254', '\154', '\266', '\257', '\254', '\062', - '\042', '\146', '\046', '\206', '\246', '\372', '\100', '\103', - '\063', '\326', '\240', '\051', '\330', '\374', '\140', '\135', - '\155', '\363', '\112', '\373', '\146', '\223', '\021', '\063', - '\153', '\022', '\361', '\210', '\021', '\117', '\121', '\054', - '\120', '\133', '\333', '\332', '\324', '\274', '\256', '\076', - '\150', '\337', '\304', '\352', '\272', '\265', '\301', '\372', - '\326', '\246', '\272', '\207', '\202', '\130', '\335', '\130', - '\327', '\320', '\154', '\047', '\327', '\004', '\233', '\032', - '\353', '\133', '\232', '\353', '\032', '\033', '\132', '\327', - '\252', '\047', '\353', '\320', '\264', '\072', '\120', '\123', - '\327', '\260', '\002', '\065', '\010', '\174', '\056', '\270', - '\046', '\260', '\042', '\330', '\152', '\125', '\205', '\232', - '\225', '\201', '\065', '\254', '\167', '\250', '\375', '\165', - '\115', '\215', '\113', '\226', '\054', '\272', '\053', '\173', - '\043', '\330', '\120', '\323', '\130', '\053', '\044', '\253', - '\121', '\323', '\270', '\172', '\335', '\032', '\321', '\172', - '\254', '\316', '\254', '\217', '\232', '\341', '\212', '\110', - '\042', '\026', '\062', '\343', '\025', '\155', '\211', '\170', - '\372', '\266', '\212', '\212', '\246', '\216', '\120', '\322', - '\250', '\010', '\305', '\043', '\025', '\106', '\374', '\213', - '\211', '\356', '\333', '\120', '\023', '\130', '\335', '\272', - '\322', '\122', '\027', '\153', '\145', '\102', '\030', '\014', - '\225', '\302', '\066', '\225', '\226', '\075', '\052', '\155', - '\033', '\124', '\256', '\251', '\034', '\246', '\157', '\145', - '\145', '\365', '\035', '\225', '\325', '\013', '\252', '\052', - '\357', '\134', '\044', '\376', '\327', '\124', '\056', '\256', - '\252', '\164', '\132', '\126', '\131', '\355', '\330', '\120', - '\121', '\020', '\017', '\264', '\004', '\152', '\035', '\215', - '\054', '\237', '\053', '\260', '\002', '\160', '\205', '\343', - '\223', '\166', '\030', '\317', '\177', '\127', '\070', '\347', - '\152', '\132', '\234', '\235', '\077', '\377', '\353', '\363', - '\042', '\357', '\360', '\353', '\136', '\101', '\324', '\361', - '\036', '\172', '\372', '\373', '\237', '\354', '\275', '\034', - '\135', '\216', '\056', '\107', '\227', '\243', '\113', '\033', - '\071', '\343', '\326', '\173', '\316', '\170', '\263', '\120', - '\314', '\343', '\316', '\014', '\167', '\222', '\024', '\162', - '\374', '\131', '\102', '\242', '\344', '\000', '\071', '\105', - '\212', '\050', '\260', '\224', '\164', '\222', '\103', '\344', - '\264', '\230', '\247', '\071', '\067', '\057', '\043', '\151', - '\162', '\230', '\234', '\041', '\045', '\234', '\317', '\153', - '\111', '\027', '\071', '\102', '\316', '\222', '\322', '\161', - '\300', '\112', '\262', '\211', '\034', '\045', '\357', '\223', - '\062', '\116', '\163', '\365', '\244', '\207', '\034', '\043', - '\347', '\310', '\154', '\256', '\013', '\126', '\223', '\355', - '\344', '\145', '\362', '\001', '\251', '\340', '\302', '\241', - '\231', '\014', '\220', '\127', '\311', '\207', '\144', '\056', - '\347', '\323', '\265', '\144', '\027', '\171', '\235', '\174', - '\104', '\346', '\161', '\042', '\375', '\002', '\331', '\103', - '\336', '\044', '\037', '\223', '\371', '\034', '\240', '\037', - '\046', '\117', '\221', '\343', '\344', '\023', '\122', '\125', - '\314', '\065', '\003', '\331', '\107', '\116', '\024', '\333', - '\223', '\375', '\102', '\322', '\101', '\366', '\223', '\223', - '\244', '\160', '\012', '\365', '\047', '\121', '\162', '\200', - '\234', '\042', '\105', '\123', '\251', '\077', '\351', '\044', - '\207', '\310', '\151', '\122', '\314', '\105', '\314', '\062', - '\222', '\046', '\207', '\311', '\031', '\122', '\062', '\215', - '\372', '\223', '\056', '\162', '\204', '\234', '\045', '\245', - '\134', '\217', '\254', '\044', '\233', '\310', '\121', '\362', - '\076', '\051', '\343', '\372', '\244', '\236', '\364', '\220', - '\143', '\344', '\034', '\231', '\135', '\112', '\375', '\311', - '\166', '\362', '\062', '\371', '\200', '\124', '\314', '\240', - '\376', '\144', '\200', '\274', '\112', '\076', '\044', '\163', - '\271', '\320', '\131', '\113', '\166', '\221', '\327', '\311', - '\107', '\144', '\336', '\114', '\352', '\117', '\366', '\220', - '\067', '\311', '\307', '\144', '\176', '\031', '\365', '\047', - '\117', '\221', '\343', '\344', '\023', '\122', '\065', '\213', - '\372', '\223', '\175', '\344', '\004', '\301', '\125', '\324', - '\237', '\164', '\220', '\375', '\344', '\044', '\051', '\344', - '\262', '\151', '\011', '\211', '\222', '\003', '\344', '\024', - '\051', '\232', '\115', '\375', '\111', '\047', '\071', '\104', - '\116', '\223', '\342', '\071', '\324', '\237', '\244', '\311', - '\141', '\162', '\206', '\224', '\134', '\103', '\375', '\111', - '\027', '\071', '\102', '\316', '\222', '\322', '\162', '\352', - '\117', '\066', '\221', '\243', '\344', '\175', '\122', '\306', - '\145', '\131', '\075', '\351', '\041', '\307', '\310', '\071', - '\062', '\373', '\132', '\352', '\117', '\266', '\223', '\227', - '\311', '\007', '\244', '\342', '\072', '\352', '\117', '\006', - '\310', '\253', '\344', '\103', '\062', '\367', '\172', '\352', - '\117', '\166', '\221', '\327', '\311', '\107', '\144', '\336', - '\134', '\352', '\117', '\366', '\220', '\067', '\311', '\307', - '\144', '\376', '\015', '\324', '\237', '\074', '\105', '\216', - '\223', '\117', '\110', '\325', '\215', '\324', '\237', '\354', - '\043', '\047', '\010', '\156', '\242', '\376', '\244', '\203', - '\354', '\047', '\047', '\111', '\341', '\074', '\352', '\117', - '\242', '\344', '\000', '\071', '\105', '\212', '\156', '\246', - '\376', '\244', '\223', '\034', '\042', '\247', '\111', '\361', - '\055', '\324', '\237', '\244', '\311', '\141', '\162', '\206', - '\224', '\334', '\112', '\375', '\111', '\027', '\071', '\102', - '\316', '\222', '\122', '\256', '\076', '\127', '\222', '\115', - '\344', '\050', '\171', '\237', '\224', '\125', '\002', '\115', - '\364', '\307', '\357', '\260', '\357', '\352', '\231', '\336', - '\367', '\320', '\320', '\374', '\077', '\303', '\071', '\116', - '\363', '\070', '\316', '\200', '\167', '\020', '\353', '\156', - '\272', '\053', '\312', '\235', '\143', '\241', '\113', '\036', - '\041', '\177', '\313', '\010', '\217', '\062', '\214', '\163', - '\230', '\240', '\244', '\351', '\012', '\326', '\372', '\136', - '\242', '\007', '\221', '\127', '\254', '\154', '\307', '\072', - '\307', '\071', '\116', '\273', '\212', '\235', '\243', '\133', - '\033', '\307', '\073', '\171', '\345', '\212', '\130', '\344', - '\055', '\125', '\216', '\245', '\056', '\062', '\005', '\012', - '\023', '\234', '\166', '\345', '\253', '\107', '\334', '\273', - '\322', '\241', '\330', '\345', '\276', '\127', '\220', '\345', - '\225', '\153', '\145', '\227', '\173', '\344', '\027', '\257', - '\000', '\142', '\275', '\070', '\331', '\111', '\027', '\152', - '\314', '\166', '\221', '\031', '\247', '\060', '\306', '\301', - '\313', '\326', '\172', '\171', '\222', '\011', '\043', '\320', - '\111', '\206', '\011', '\071', '\312', '\363', '\012', '\113', - '\163', '\310', '\170', '\261', '\064', '\107', '\171', '\136', - '\062', '\367', '\345', '\271', '\167', '\061', '\341', '\377', - '\203', '\174', '\056', '\133', '\217', '\264', '\177', '\162', - '\371', '\301', '\245', '\354', '\203', '\134', '\355', '\036', - '\015', '\152', '\340', '\224', '\227', '\035', '\113', '\306', - '\073', '\347', '\042', '\170', '\075', '\247', '\042', '\210', - '\161', '\112', '\214', '\005', '\045', '\316', '\161', '\254', - '\017', '\031', '\031', '\104', '\236', '\111', '\056', '\344', - '\012', '\045', '\030', '\032', '\107', '\312', '\235', '\266', - '\272', '\005', '\071', '\126', '\311', '\261', '\140', '\202', - '\222', '\026', '\327', '\047', '\373', '\150', '\337', '\110', - '\306', '\270', '\221', '\204', '\174', '\375', '\341', '\066', - '\166', '\370', '\265', '\217', '\227', '\134', '\271', '\166', - '\364', '\052', '\107', '\324', '\315', '\145', '\110', '\166', - '\054', '\025', '\363', '\242', '\234', '\103', '\246', '\172', - '\264', '\115', '\330', '\163', '\206', '\123', '\146', '\221', - '\223', '\147', '\214', '\163', '\056', '\256', '\117', '\364', - '\250', '\153', '\014', '\206', '\217', '\331', '\342', '\070', - '\313', '\311', '\377', '\051', '\227', '\374', '\176', '\306', - '\126', '\065', '\310', '\266', '\310', '\366', '\350', '\310', - '\173', '\352', '\334', '\240', '\137', '\327', '\121', '\313', - '\323', '\333', '\046', '\164', '\235', '\342', '\034', '\375', - '\266', '\121', '\325', '\113', '\237', '\037', '\107', '\032', - '\344', '\334', '\235', '\157', '\317', '\304', '\317', '\263', - '\231', '\053', '\210', '\072', '\334', '\326', '\113', '\045', - '\016', '\252', '\255', '\244', '\255', '\345', '\132', '\303', - '\255', '\054', '\341', '\047', '\323', '\134', '\230', '\344', - '\122', '\207', '\224', '\021', '\343', '\323', '\070', '\270', - '\077', '\103', '\156', '\372', '\115', '\121', '\312', '\225', - '\155', '\224', '\355', '\053', '\360', '\220', '\051', '\327', - '\362', '\116', '\121', '\164', '\234', '\346', '\234', '\353', - '\101', '\352', '\136', '\214', '\241', '\347', '\154', '\242', - '\123', '\226', '\327', '\232', '\117', '\216', '\143', '\002', - '\061', '\056', '\115', '\367', '\121', '\217', '\324', '\107', - '\312', '\115', '\305', '\160', '\333', '\271', '\311', '\250', - '\372', '\170', '\075', '\033', '\136', '\365', '\250', '\345', - '\346', '\253', '\107', '\317', '\163', '\215', '\017', '\175', - '\144', '\160', '\363', '\055', '\057', '\177', '\313', '\165', - '\337', '\353', '\131', '\160', '\353', '\173', '\371', '\314', - '\027', '\071', '\367', '\163', '\205', '\162', '\217', '\264', - '\036', '\334', '\312', '\325', '\353', '\325', '\203', '\227', - '\217', '\346', '\232', '\027', '\124', '\031', '\061', '\166', - '\316', '\160', '\230', '\354', '\324', '\161', '\215', '\213', - '\214', '\333', '\063', '\127', '\256', '\235', '\353', '\101', - '\370', '\327', '\225', '\012', '\123', '\264', '\363', '\251', - '\071', '\332', '\126', '\340', '\202', '\227', '\037', '\350', - '\365', '\350', '\270', '\325', '\243', '\076', '\077', '\362', - '\131', '\120', '\317', '\275', '\236', '\355', '\134', '\062', - '\271', '\372', '\107', '\315', '\063', '\013', '\271', '\237', - '\005', '\175', '\114', '\323', '\355', '\354', '\146', '\153', - '\351', '\313', '\136', '\270', '\325', '\243', '\277', '\353', - '\250', '\210', '\361', '\147', '\174', '\216', '\266', '\211', - '\373', '\142', '\054', '\035', '\353', '\034', '\047', '\346', - '\150', '\233', '\133', '\137', '\346', '\263', '\265', '\054', - '\113', '\174', '\302', '\044', '\375', '\063', '\237', '\015', - '\304', '\265', '\351', '\016', '\122', '\146', '\026', '\206', - '\333', '\133', '\017', '\372', '\270', '\243', '\343', '\345', - '\157', '\152', '\236', '\221', '\370', '\201', '\033', '\162', - '\015', '\240', '\217', '\043', '\156', '\365', '\344', '\263', - '\265', '\356', '\157', '\176', '\346', '\037', '\165', '\015', - '\341', '\147', '\315', '\217', '\034', '\272', '\214', '\304', - '\257', '\325', '\365', '\251', '\337', '\172', '\146', '\150', - '\270', '\255', '\111', '\365', '\362', '\013', '\225', '\164', - '\056', '\337', '\321', '\145', '\362', '\331', '\300', '\155', - '\156', '\124', '\327', '\056', '\272', '\137', '\117', '\201', - '\373', '\232', '\122', '\107', '\267', '\235', '\354', '\113', - '\165', '\015', '\052', '\353', '\224', '\175', '\253', '\327', - '\343', '\365', '\134', '\253', '\350', '\365', '\250', '\143', - '\374', '\245', '\014', '\252', '\035', '\364', '\265', '\363', - '\150', '\202', '\364', '\151', '\061', '\117', '\311', '\071', - '\314', '\155', '\355', '\257', '\217', '\325', '\272', '\057', - '\271', '\315', '\013', '\172', '\075', '\352', '\263', '\344', - '\345', '\327', '\045', '\012', '\262', '\115', '\372', '\132', - '\306', '\117', '\075', '\162', '\176', '\361', '\252', '\107', - '\177', '\077', '\235', '\212', '\013', '\175', '\307', '\117', - '\075', '\372', '\032', '\113', '\257', '\117', '\265', '\233', - '\134', '\133', '\346', '\033', '\173', '\105', '\220', '\317', - '\310', '\170', '\370', '\233', '\177', '\104', '\220', '\276', - '\120', '\014', '\367', '\071', '\110', '\237', '\207', '\324', - '\266', '\171', '\315', '\101', '\172', '\160', '\153', '\217', - '\237', '\266', '\311', '\040', '\366', '\025', '\365', '\161', - '\047', '\337', '\063', '\062', '\022', '\273', '\311', '\340', - '\066', '\107', '\344', '\153', '\133', '\276', '\271', '\310', - '\055', '\350', '\076', '\252', '\256', '\265', '\275', '\326', - '\262', '\122', '\237', '\174', '\363', '\234', '\233', '\076', - '\302', '\376', '\105', '\171', '\364', '\361', '\362', '\151', - '\077', '\373', '\306', '\272', '\315', '\274', '\306', '\003', - '\057', '\031', '\165', '\314', '\367', '\043', '\223', '\157', - '\376', '\321', '\145', '\324', '\371', '\304', '\317', '\370', - '\352', '\246', '\113', '\276', '\367', '\040', '\371', '\256', - '\230', '\353', '\375', '\264', '\014', '\027', '\372', '\376', - '\130', '\227', '\153', '\145', '\232', '\334', '\110', '\367', - '\004', '\275', '\312', '\164', '\253', '\133', '\015', '\162', - '\117', '\310', '\153', '\357', '\347', '\122', '\005', '\365', - '\335', '\310', '\357', '\172', '\107', '\216', '\023', '\242', - '\175', '\162', '\377', '\111', '\256', '\333', '\274', '\374', - '\346', '\142', '\366', '\023', '\145', '\137', '\113', '\337', - '\224', '\317', '\222', '\127', '\136', '\325', '\217', '\325', - '\275', '\316', '\134', '\372', '\350', '\372', '\346', '\262', - '\201', '\252', '\213', '\376', '\231', '\116', '\011', '\334', - '\237', '\323', '\321', '\354', '\075', '\112', '\075', '\205', - '\155', '\305', '\332', '\177', '\072', '\206', '\336', '\001', - '\162', '\371', '\277', '\276', '\046', '\220', '\163', '\256', - '\237', '\175', '\253', '\122', '\247', '\235', '\262', '\137', - '\047', '\301', '\375', '\363', '\057', '\267', '\040', '\327', - '\200', '\371', '\366', '\000', '\364', '\266', '\346', '\273', - '\057', '\164', '\230', '\011', '\133', '\367', '\253', '\225', - '\164', '\276', '\061', '\140', '\244', '\341', '\267', '\361', - '\371', '\234', '\334', '\247', '\225', '\143', '\223', '\237', - '\317', '\314', '\244', '\214', '\134', '\357', '\352', '\143', - '\205', '\133', '\220', '\343', '\337', '\305', '\004', '\267', - '\271', '\104', '\330', '\136', '\237', '\357', '\256', '\161', - '\256', '\253', '\210', '\161', '\272', '\024', '\336', '\237', - '\237', '\352', '\341', '\122', '\175', '\126', '\240', '\352', - '\055', '\354', '\065', '\026', '\303', '\307', '\034', '\077', - '\301', '\153', '\217', '\316', '\217', '\117', '\251', '\317', - '\214', '\372', '\054', '\351', '\301', '\255', '\155', '\342', - '\271', '\051', '\163', '\344', '\146', '\343', '\302', '\347', - '\310', '\115', '\246', '\310', '\311', '\057', '\337', '\275', - '\364', '\317', '\166', '\165', '\337', '\021', '\351', '\053', - '\363', '\324', '\003', '\134', '\070', '\016', '\312', '\171', - '\324', '\153', '\055', '\066', '\106', '\223', '\121', '\337', - '\057', '\325', '\075', '\033', '\065', '\024', '\215', '\102', - '\106', '\076', '\243', '\043', '\221', '\221', '\375', '\060', - '\022', '\231', '\111', '\243', '\220', '\221', '\371', '\364', - '\365', '\115', '\056', '\031', '\021', '\256', '\302', '\360', - '\317', '\337', '\305', '\134', '\250', '\376', '\315', '\303', - '\034', '\027', '\031', '\077', '\173', '\203', '\352', '\376', - '\255', '\332', '\077', '\352', '\336', '\235', '\272', '\106', - '\326', '\375', '\273', '\150', '\024', '\062', '\152', '\377', - '\370', '\225', '\121', '\155', '\355', '\127', '\106', '\325', - '\307', '\153', '\277', '\117', '\367', '\321', '\242', '\121', - '\310', '\250', '\372', '\370', '\225', '\121', '\365', '\361', - '\053', '\003', '\134', '\270', '\167', '\073', '\023', '\271', - '\367', '\156', '\125', '\277', '\226', '\276', '\045', '\367', - '\373', '\274', '\366', '\371', '\164', '\273', '\371', '\331', - '\257', '\322', '\355', '\346', '\107', '\106', '\267', '\233', - '\037', '\031', '\125', '\037', '\277', '\062', '\272', '\255', - '\375', '\310', '\350', '\101', '\175', '\057', '\361', '\172', - '\047', '\051', '\161', '\312', '\221', '\173', '\250', '\352', - '\173', '\217', '\334', '\147', '\025', '\367', '\325', '\171', - '\121', '\265', '\265', '\133', '\273', '\362', '\331', '\332', - '\257', '\214', '\152', '\153', '\277', '\062', '\252', '\335', - '\056', '\246', '\155', '\156', '\373', '\203', '\172', '\160', - '\333', '\163', '\312', '\367', '\156', '\056', '\336', '\223', - '\345', '\236', '\207', '\034', '\007', '\325', '\275', '\136', - '\267', '\367', '\005', '\335', '\267', '\375', '\354', '\213', - '\351', '\276', '\355', '\107', '\106', '\367', '\155', '\077', - '\062', '\272', '\157', '\373', '\221', '\321', '\175', '\073', - '\237', '\214', '\154', '\127', '\361', '\010', '\144', '\364', - '\040', '\377', '\136', '\101', '\034', '\345', '\173', '\135', - '\276', '\367', '\026', '\257', '\275', '\101', '\165', '\376', - '\001', '\334', '\307', '\236', '\174', '\373', '\174', '\156', - '\143', '\217', '\337', '\275', '\301', '\221', '\310', '\270', - '\215', '\043', '\371', '\144', '\124', '\175', '\374', '\356', - '\363', '\025', '\215', '\102', '\106', '\325', '\307', '\257', - '\214', '\252', '\217', '\037', '\031', '\371', '\034', '\313', - '\375', '\051', '\277', '\373', '\157', '\252', '\137', '\373', - '\335', '\347', '\313', '\067', '\007', '\371', '\365', '\203', - '\174', '\062', '\371', '\346', '\240', '\174', '\372', '\370', - '\225', '\311', '\067', '\007', '\171', '\315', '\077', '\156', - '\357', '\212', '\136', '\143', '\250', '\032', '\324', '\271', - '\110', '\235', '\203', '\364', '\371', '\107', '\204', '\134', - '\163', '\220', '\237', '\061', '\321', '\257', '\114', '\256', - '\071', '\310', '\317', '\370', '\166', '\261', '\155', '\313', - '\267', '\067', '\350', '\265', '\207', '\077', '\035', '\103', - '\237', '\365', '\253', '\266', '\363', '\152', '\233', '\133', - '\075', '\316', '\167', '\250', '\372', '\372', '\167', '\366', - '\060', '\332', '\261', '\331', '\376', '\362', '\203', '\163', - '\252', '\106', '\133', '\031', '\075', '\316', '\324', '\300', - '\026', '\345', '\306', '\266', '\376', '\047', '\067', '\061', - '\352', '\353', '\355', '\355', '\267', '\043', '\236', '\312', - '\157', '\117', '\154', '\144', '\064', '\320', '\315', '\250', - '\117', '\134', '\353', '\335', '\302', '\150', '\213', '\225', - '\245', '\127', '\210', '\131', '\131', '\304', '\015', '\212', - '\155', '\263', '\253', '\264', '\112', '\266', '\242', '\176', - '\121', '\174', '\277', '\135', '\121', '\357', '\166', '\121', - '\100', '\017', '\057', '\061', '\037', '\233', '\261', '\275', - '\177', '\347', '\143', '\172', '\063', '\170', '\152', '\335', - '\175', '\214', '\167', '\007', '\267', '\132', '\221', '\270', - '\261', '\311', '\322', '\210', '\247', '\275', '\342', '\264', - '\157', '\223', '\114', '\135', '\240', '\233', '\217', '\210', - '\262', '\073', '\266', '\132', '\221', '\274', '\326', '\277', - '\171', '\364', '\105', '\371', '\316', '\074', '\262', '\346', - '\146', '\065', '\037', '\112', '\011', '\133', '\365', '\154', - '\245', '\021', '\007', '\273', '\244', '\141', '\355', '\326', - '\273', '\245', '\172', '\245', '\354', '\100', '\117', '\017', - '\243', '\336', '\141', '\315', '\355', '\327', '\242', '\336', - '\154', '\224', '\275', '\066', '\340', '\226', '\257', '\147', - '\130', '\276', '\301', '\255', '\126', '\067', '\132', '\051', - '\273', '\175', '\331', '\256', '\025', '\247', '\331', '\136', - '\335', '\341', '\364', '\376', '\066', '\333', '\365', '\006', - '\055', '\215', '\204', '\012', '\203', '\326', '\215', '\315', - '\062', '\113', '\237', '\350', '\337', '\276', '\115', '\331', - '\033', '\135', '\212', '\237', '\156', '\353', '\037', '\174', - '\334', '\212', '\262', '\352', '\367', '\016', '\271', '\024', - '\243', '\236', '\136', '\073', '\213', '\132', '\336', '\140', - '\317', '\260', '\150', '\147', '\317', '\205', '\327', '\334', - '\262', '\354', '\354', '\165', '\273', '\053', '\332', '\354', - '\104', '\331', '\123', '\177', '\205', '\132', '\316', '\157', - '\131', '\050', '\117', '\275', '\071', '\243', '\301', '\341', - '\035', '\340', '\356', '\211', '\166', '\244', '\366', '\264', - '\217', '\342', '\255', '\307', '\157', '\207', '\247', '\167', - '\132', '\217', '\263', '\125', '\245', '\374', '\016', '\025', - '\160', '\136', '\031', '\317', '\306', '\140', '\054', '\107', - '\302', '\161', '\234', '\261', '\047', '\160', '\124', '\234', - '\310', '\321', '\352', '\012', '\216', '\302', '\223', '\071', - '\042', '\115', '\345', '\350', '\064', '\215', '\243', '\361', - '\164', '\316', '\146', '\063', '\070', '\132', '\315', '\104', - '\031', '\307', '\255', '\253', '\160', '\065', '\146', '\143', - '\016', '\127', '\203', '\345', '\250', '\300', '\265', '\270', - '\016', '\327', '\143', '\056', '\156', '\300', '\215', '\270', - '\011', '\363', '\160', '\063', '\156', '\301', '\255', '\230', - '\217', '\112', '\334', '\206', '\333', '\121', '\205', '\152', - '\054', '\300', '\035', '\130', '\210', '\105', '\130', '\214', - '\073', '\261', '\004', '\167', '\341', '\156', '\174', '\032', - '\113', '\161', '\017', '\356', '\305', '\175', '\130', '\206', - '\000', '\356', '\107', '\015', '\152', '\021', '\304', '\162', - '\254', '\300', '\112', '\324', '\341', '\063', '\370', '\054', - '\352', '\261', '\012', '\015', '\150', '\304', '\152', '\074', - '\040', '\276', '\006', '\214', '\146', '\264', '\340', '\163', - '\170', '\020', '\153', '\261', '\016', '\017', '\341', '\363', - '\370', '\002', '\176', '\007', '\277', '\213', '\126', '\074', - '\214', '\020', '\326', '\043', '\214', '\010', '\014', '\264', - '\241', '\035', '\035', '\060', '\361', '\105', '\154', '\100', - '\024', '\061', '\304', '\221', '\100', '\047', '\036', '\101', - '\022', '\051', '\244', '\221', '\301', '\106', '\074', '\212', - '\056', '\164', '\343', '\061', '\074', '\216', '\115', '\170', - '\002', '\233', '\161', '\376', '\242', '\303', '\026', '\364', - '\140', '\053', '\172', '\261', '\015', '\333', '\321', '\207', - '\176', '\354', '\300', '\000', '\166', '\142', '\020', '\117', - '\142', '\027', '\276', '\204', '\337', '\303', '\156', '\354', - '\301', '\227', '\361', '\373', '\330', '\213', '\247', '\360', - '\025', '\074', '\215', '\257', '\142', '\037', '\276', '\206', - '\147', '\360', '\165', '\354', '\307', '\067', '\360', '\115', - '\174', '\013', '\007', '\160', '\020', '\177', '\200', '\157', - '\343', '\020', '\236', '\305', '\167', '\360', '\207', '\070', - '\214', '\347', '\360', '\107', '\370', '\143', '\034', '\301', - '\363', '\370', '\023', '\274', '\200', '\243', '\170', '\021', - '\177', '\212', '\227', '\160', '\014', '\177', '\206', '\077', - '\307', '\137', '\340', '\145', '\274', '\202', '\357', '\342', - '\173', '\170', '\025', '\337', '\307', '\153', '\370', '\113', - '\274', '\216', '\037', '\340', '\257', '\360', '\006', '\336', - '\304', '\017', '\361', '\043', '\374', '\030', '\307', '\361', - '\026', '\376', '\032', '\177', '\203', '\023', '\370', '\133', - '\274', '\215', '\237', '\340', '\044', '\376', '\016', '\077', - '\305', '\317', '\160', '\012', '\357', '\340', '\357', '\361', - '\017', '\070', '\215', '\177', '\304', '\273', '\370', '\047', - '\234', '\301', '\077', '\343', '\347', '\030', '\372', '\116', - '\335', '\331', '\202', '\313', '\134', '\346', '\062', '\377', - '\027', '\250', '\337', '\153', '\225', '\337', '\025', '\023', - '\173', '\271', '\327', '\301', '\376', '\056', '\233', '\370', - '\021', '\210', '\273', '\111', '\000', '\366', '\217', '\071', - '\064', '\021', '\361', '\013', '\020', '\021', '\022', '\043', - '\033', '\311', '\026', '\062', '\100', '\366', '\300', '\376', - '\155', '\213', '\203', '\260', '\177', '\364', '\341', '\105', - '\362', '\135', '\362', '\006', '\071', '\101', '\336', '\041', - '\342', '\271', '\077', '\107', '\176', '\105', '\076', '\026', - '\163', '\000', '\333', '\060', '\211', '\314', '\042', '\345', - '\344', '\106', '\162', '\073', '\271', '\233', '\004', '\110', - '\035', '\151', '\042', '\255', '\304', '\044', '\351', '\002', - '\373', '\367', '\037', '\172', '\013', '\354', '\237', '\177', - '\330', '\115', '\236', '\046', '\373', '\311', '\101', '\362', - '\054', '\171', '\216', '\274', '\100', '\216', '\221', '\127', - '\310', '\367', '\311', '\033', '\344', '\055', '\362', '\166', - '\201', '\375', '\375', '\334', '\237', '\223', '\177', '\045', - '\377', '\106', '\176', '\111', '\376', '\213', '\374', '\067', - '\071', '\117', '\012', '\150', '\224', '\261', '\144', '\034', - '\231', '\100', '\046', '\222', '\053', '\310', '\144', '\062', - '\225', '\114', '\043', '\323', '\311', '\014', '\062', '\223', - '\314', '\042', '\127', '\223', '\071', '\244', '\234', '\134', - '\113', '\256', '\047', '\067', '\220', '\233', '\310', '\315', - '\344', '\126', '\122', '\111', '\156', '\047', '\325', '\344', - '\036', '\262', '\202', '\064', '\223', '\207', '\311', '\006', - '\362', '\010', '\111', '\221', '\014', '\171', '\224', '\164', - '\223', '\307', '\311', '\023', '\144', '\013', '\331', '\112', - '\266', '\221', '\076', '\262', '\203', '\354', '\044', '\117', - '\222', '\057', '\221', '\335', '\344', '\313', '\144', '\057', - '\371', '\012', '\371', '\052', '\371', '\032', '\371', '\072', - '\371', '\006', '\371', '\026', '\071', '\110', '\276', '\115', - '\236', '\045', '\057', '\220', '\227', '\310', '\153', '\344', - '\055', '\362', '\023', '\362', '\056', '\171', '\217', '\234', - '\043', '\277', '\044', '\277', '\042', '\347', '\205', '\015', - '\304', '\367', '\224', '\311', '\125', '\344', '\106', '\262', - '\220', '\334', '\107', '\226', '\223', '\007', '\310', '\132', - '\322', '\112', '\114', '\222', '\041', '\333', '\310', '\116', - '\262', '\213', '\074', '\115', '\236', '\045', '\317', '\223', - '\127', '\310', '\217', '\310', '\073', '\344', '\054', '\071', - '\107', '\176', '\115', '\306', '\362', '\145', '\150', '\022', - '\231', '\106', '\346', '\220', '\271', '\344', '\066', '\262', - '\220', '\334', '\111', '\226', '\221', '\025', '\244', '\201', - '\074', '\124', '\150', '\377', '\006', '\312', '\006', '\222', - '\044', '\233', '\311', '\000', '\331', '\105', '\366', '\222', - '\147', '\310', '\101', '\362', '\074', '\071', '\106', '\136', - '\043', '\077', '\046', '\157', '\223', '\167', '\310', '\031', - '\162', '\216', '\374', '\007', '\371', '\117', '\162', '\136', - '\324', '\075', '\216', '\165', '\213', '\357', '\130', '\223', - '\271', '\344', '\126', '\262', '\210', '\174', '\232', '\334', - '\113', '\126', '\220', '\006', '\322', '\102', '\102', '\144', - '\003', '\111', '\222', '\156', '\322', '\107', '\166', '\223', - '\275', '\344', '\031', '\162', '\220', '\034', '\046', '\307', - '\310', '\367', '\310', '\017', '\311', '\011', '\362', '\063', - '\362', '\056', '\371', '\027', '\362', '\013', '\362', '\033', - '\362', '\077', '\244', '\160', '\074', '\337', '\277', '\110', - '\304', '\150', '\013', '\145', '\242', '\351', '\160', '\107', - '\050', '\211', '\114', '\334', '\134', '\260', '\250', '\146', - '\061', '\122', '\035', '\241', '\210', '\141', '\235', '\055', - '\254', '\272', '\313', '\071', '\326', '\070', '\307', '\132', - '\347', '\030', '\240', '\144', '\173', '\322', '\060', '\320', - '\031', '\315', '\244', '\142', '\146', '\074', '\223', '\262', - '\157', '\054', '\130', '\350', '\144', '\270', '\037', '\115', - '\313', '\253', '\026', '\126', '\061', '\210', '\304', '\035', - '\062', '\121', '\055', '\023', '\013', '\144', '\142', '\221', - '\225', '\020', '\102', '\167', '\334', '\037', '\160', '\216', - '\102', '\330', '\312', '\051', '\157', '\324', '\070', '\307', - '\132', '\041', '\261', '\104', '\212', '\336', '\045', '\023', - '\167', '\312', '\304', '\142', '\047', '\121', '\155', '\327', - '\023', '\065', '\122', '\051', '\343', '\221', '\114', '\050', - '\012', '\266', '\065', '\224', '\066', '\222', '\366', '\111', - '\247', '\211', '\170', '\042', '\155', '\247', '\123', '\274', - '\032', '\065', '\343', '\355', '\350', '\064', '\222', '\146', - '\042', '\022', '\066', '\342', '\042', '\133', '\004', '\251', - '\316', '\120', '\330', '\200', '\321', '\025', '\216', '\206', - '\142', '\170', '\044', '\303', '\354', '\221', '\365', '\121', - '\304', '\063', '\261', '\365', '\106', '\062', '\145', '\266', - '\307', '\021', '\111', '\104', '\243', '\064', '\032', '\305', - '\204', '\014', '\102', '\061', '\246', '\122', '\241', '\170', - '\304', '\316', '\234', '\142', '\221', '\121', '\132', '\047', - '\224', '\064', '\342', '\121', '\243', '\055', '\155', '\247', - '\222', '\146', '\173', '\007', '\263', '\212', '\072', '\315', - '\324', '\006', '\313', '\166', '\010', '\047', '\142', '\261', - '\020', '\072', '\272', '\073', '\073', '\214', '\270', '\323', - '\010', '\244', '\242', '\241', '\124', '\007', '\036', '\063', - '\222', '\011', '\044', '\342', '\006', '\322', '\217', '\046', - '\220', '\356', '\020', '\326', '\156', '\113', '\144', '\222', - '\150', '\063', '\067', '\032', '\110', '\231', '\135', '\110', - '\031', '\033', '\051', '\143', '\130', '\205', '\306', '\115', - '\146', '\014', '\047', '\242', '\211', '\070', '\057', '\307', - '\114', '\073', '\045', '\364', '\307', '\060', '\003', '\260', - '\165', '\106', '\052', '\155', '\362', '\136', '\050', '\075', - '\252', '\205', '\350', '\372', '\144', '\050', '\274', '\301', - '\110', '\133', '\072', '\255', '\147', '\322', '\156', '\252', - '\163', '\125', '\352', '\027', '\066', '\315', '\260', '\231', - '\014', '\147', '\142', '\354', '\266', '\010', '\315', '\022', - '\116', '\044', '\015', '\266', '\040', '\304', '\166', '\217', - '\146', '\361', '\052', '\112', '\067', '\234', '\032', '\223', - '\366', '\231', '\122', '\123', '\332', '\214', '\322', '\135', - '\325', '\376', '\212', '\044', '\036', '\215', '\303', '\352', - '\225', '\154', '\357', '\206', '\063', '\111', '\332', '\077', - '\334', '\215', '\156', '\132', '\154', '\175', '\062', '\261', - '\301', '\210', '\213', '\262', '\122', '\106', '\330', '\062', - '\106', '\304', '\144', '\247', '\247', '\114', '\321', '\033', - '\235', '\335', '\166', '\331', '\211', '\144', '\244', '\215', - '\206', '\264', '\354', '\332', '\236', '\061', '\243', '\121', - '\043', '\226', '\260', '\325', '\216', '\046', '\332', '\315', - '\160', '\050', '\112', '\027', '\222', '\335', '\226', '\064', - '\332', '\315', '\224', '\355', '\067', '\261', '\120', '\070', - '\051', '\012', '\324', '\237', '\016', '\366', '\141', '\052', - '\143', '\165', '\157', '\322', '\356', '\313', '\354', '\131', - '\050', '\234', '\111', '\033', '\210', '\145', '\204', '\213', - '\204', '\150', '\244', '\316', '\016', '\335', '\027', '\303', - '\106', '\204', '\365', '\207', '\204', '\057', '\144', '\245', - '\330', '\274', '\030', '\325', '\317', '\104', '\207', '\265', - '\317', '\151', '\172', '\134', '\364', '\171', '\122', '\164', - '\067', '\223', '\035', '\241', '\150', '\233', '\135', '\245', - '\163', '\061', '\225', '\165', '\002', '\313', '\120', '\001', - '\273', '\143', '\002', '\166', '\073', '\002', '\166', '\307', - '\265', '\105', '\215', '\056', '\004', '\154', '\323', '\006', - '\262', '\326', '\011', '\044', '\205', '\055', '\003', '\101', - '\324', '\310', '\046', '\005', '\155', '\341', '\240', '\055', - '\034', '\124', '\204', '\203', '\131', '\251', '\072', '\073', - '\117', '\235', '\235', '\247', '\116', '\311', '\123', '\227', - '\315', '\023', '\114', '\167', '\240', '\301', '\256', '\256', - '\321', '\316', '\336', '\150', '\147', '\157', '\124', '\262', - '\067', '\072', '\031', '\262', '\122', '\061', '\016', '\135', - '\146', '\147', '\264', '\033', '\215', '\266', '\033', '\266', - '\330', '\242', '\055', '\266', '\150', '\213', '\042', '\332', - '\222', '\225', '\131', '\147', '\337', '\154', '\356', '\110', - '\044', '\343', '\150', '\067', '\222', '\061', '\076', '\263', - '\353', '\243', '\051', '\204', '\034', '\377', '\264', '\157', - '\207', '\024', '\331', '\220', '\135', '\155', '\050', '\133', - '\104', '\310', '\062', '\103', '\210', '\317', '\233', '\064', - '\203', '\141', '\013', '\033', '\266', '\260', '\241', '\010', - '\033', '\131', '\051', '\323', '\316', '\143', '\332', '\171', - '\114', '\045', '\217', '\231', '\315', '\143', '\320', '\014', - '\161', '\273', '\272', '\204', '\235', '\075', '\141', '\147', - '\117', '\050', '\331', '\023', '\116', '\206', '\254', '\124', - '\304', '\334', '\150', '\212', '\013', '\266', '\021', '\062', - '\266', '\140', '\306', '\026', '\314', '\050', '\202', '\231', - '\254', '\104', '\267', '\175', '\063', '\155', '\031', '\241', - '\073', '\173', '\371', '\322', '\375', '\156', '\322', '\377', - '\002', '\174', '\155', '\142', '\140', '\200', '\114', '\000', - '\000', - -}; - -static char name_6x13[] = "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1"; -static char name_cursor[] = "cursor"; - -const BuiltinFileRec builtin_files[] = { - { "6x13.builtin", sizeof file_6x13, file_6x13, }, - { "cursor.builtin", sizeof file_cursor, file_cursor, } -}; - -const int builtin_files_count = sizeof (builtin_files) / sizeof (builtin_files[0]); - -const BuiltinDirRec builtin_dir[] = { - { "6x13.builtin", name_6x13, }, - { "cursor.builtin", name_cursor, } -}; - -const int builtin_dir_count = sizeof (builtin_dir) / sizeof (builtin_dir[0]); - -static char alias_fixed[] = "fixed"; -static char alias_6x13[] = "6x13"; -static char alias_6x13_100[] = "-misc-fixed-medium-r-semicondensed--13-100-100-100-c-60-iso8859-1"; - -const BuiltinAliasRec builtin_alias[] = { - { alias_fixed, name_6x13, }, - { alias_6x13, name_6x13, }, - { alias_6x13_100, name_6x13, } -}; - -const int builtin_alias_count = sizeof (builtin_alias) / sizeof (builtin_alias[0]); +/*
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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, and that the name of SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "builtin.h"
+
+static const char file_cursor[] = {
+ '\037', '\213', '\010', '\010', '\143', '\117', '\054', '\100',
+ '\000', '\003', '\143', '\165', '\162', '\163', '\157', '\162',
+ '\056', '\160', '\143', '\146', '\000', '\355', '\233', '\177',
+ '\160', '\124', '\327', '\165', '\307', '\317', '\112', '\102',
+ '\022', '\130', '\040', '\021', '\300', '\226', '\023', '\031',
+ '\311', '\100', '\034', '\114', '\354', '\104', '\004', '\033',
+ '\013', '\233', '\040', '\141', '\040', '\006', '\327', '\001',
+ '\154', '\213', '\000', '\216', '\143', '\151', '\221', '\026',
+ '\244', '\146', '\365', '\203', '\325', '\352', '\027', '\010',
+ '\264', '\253', '\137', '\273', '\010', '\320', '\217', '\332',
+ '\155', '\035', '\217', '\123', '\323', '\044', '\323', '\361',
+ '\340', '\114', '\207', '\231', '\144', '\062', '\324', '\303',
+ '\324', '\212', '\235', '\232', '\046', '\045', '\305', '\323',
+ '\072', '\143', '\322', '\060', '\365', '\062', '\166', '\143',
+ '\246', '\166', '\221', '\360', '\057', '\224', '\262', '\150',
+ '\373', '\075', '\357', '\234', '\273', '\357', '\355', '\112',
+ '\313', '\217', '\244', '\371', '\057', '\232', '\371', '\274',
+ '\167', '\357', '\271', '\347', '\336', '\167', '\177', '\236',
+ '\173', '\356', '\173', '\053', '\327', '\316', '\252', '\306',
+ '\154', '\042', '\162', '\201', '\064', '\360', '\056', '\010',
+ '\153', '\230', '\251', '\006', '\136', '\044', '\146', '\160',
+ '\034', '\367', '\354', '\164', '\242', '\067', '\370', '\256',
+ '\351', '\147', '\027', '\021', '\235', '\101', '\142', '\221',
+ '\306', '\327', '\042', '\355', '\307', '\167', '\022', '\225',
+ '\151', '\274', '\021', '\227', '\361', '\045', '\104', '\001',
+ '\215', '\237', '\237', '\116', '\124', '\163', '\267', '\074',
+ '\320', '\224', '\277', '\371', '\076', '\011', '\043', '\311',
+ '\372', '\163', '\315', '\300', '\145', '\011', '\207', '\226',
+ '\103', '\353', '\136', '\226', '\334', '\217', '\313', '\152',
+ '\226', '\160', '\322', '\172', '\016', '\174', '\033', '\074',
+ '\316', '\201', '\215', '\240', '\322', '\004', '\352', '\070',
+ '\020', '\303', '\137', '\013', '\007', '\146', '\112', '\171',
+ '\101', '\260', '\146', '\323', '\346', '\355', '\217', '\155',
+ '\170', '\150', '\175', '\071', '\225', '\327', '\170', '\232',
+ '\074', '\105', '\013', '\166', '\171', '\333', '\033', '\153',
+ '\232', '\026', '\024', '\271', '\175', '\236', '\242', '\346',
+ '\172', '\117', '\175', '\125', '\163', '\335', '\016', '\217',
+ '\317', '\123', '\115', '\233', '\067', '\155', '\330', '\130',
+ '\136', '\361', '\370', '\206', '\047', '\326', '\321', '\327',
+ '\066', '\155', '\054', '\247', '\252', '\146', '\137', '\123',
+ '\203', '\217', '\266', '\256', '\263', '\162', '\077', '\266',
+ '\356', '\361', '\115', '\217', '\154', '\051', '\337', '\260',
+ '\151', '\243', '\043', '\130', '\261', '\315', '\031', '\331',
+ '\116', '\333', '\052', '\326', '\213', '\366', '\243', '\133',
+ '\126', '\257', '\255', '\330', '\272', '\141', '\155', '\271',
+ '\125', '\345', '\064', '\262', '\377', '\362', '\300', '\154',
+ '\255', '\353', '\305', '\030', '\267', '\053', '\026', '\263',
+ '\332', '\216', '\224', '\331', '\224', '\153', '\245', '\377',
+ '\076', '\177', '\074', '\106', '\317', '\321', '\236', '\360',
+ '\160', '\137', '\270', '\375', '\300', '\160', '\350', '\100',
+ '\123', '\160', '\070', '\060', '\340', '\353', '\032', '\016',
+ '\016', '\356', '\353', '\035', '\076', '\020', '\354', '\350',
+ '\033', '\356', '\357', '\262', '\103', '\110', '\350', '\356',
+ '\305', '\245', '\247', '\167', '\117', '\210', '\163', '\204',
+ '\221', '\043', '\060', '\060', '\174', '\070', '\330', '\071',
+ '\070', '\074', '\320', '\205', '\274', '\207', '\203', '\110',
+ '\035', '\350', '\102', '\352', '\341', '\040', '\122', '\007',
+ '\272', '\332', '\103', '\310', '\333', '\026', '\106', '\336',
+ '\266', '\320', '\160', '\070', '\214', '\120', '\070', '\214',
+ '\242', '\002', '\003', '\173', '\103', '\170', '\006', '\122',
+ '\103', '\041', '\113', '\206', '\032', '\164', '\037', '\336',
+ '\163', '\000', '\027', '\144', '\073', '\020', '\102', '\135',
+ '\254', '\113', '\110', '\152', '\025', '\017', '\205', '\035',
+ '\262', '\260', '\011', '\355', '\355', '\035', '\356', '\355',
+ '\335', '\323', '\067', '\334', '\327', '\207', '\113', '\157',
+ '\250', '\235', '\253', '\006', '\131', '\050', '\204', '\150',
+ '\070', '\354', '\103', '\213', '\006', '\371', '\062', '\024',
+ '\017', '\015', '\332', '\172', '\166', '\313', '\355', '\272',
+ '\240', '\011', '\135', '\207', '\271', '\251', '\207', '\367',
+ '\017', '\040', '\233', '\165', '\361', '\007', '\315', '\045',
+ '\060', '\210', '\332', '\007', '\206', '\120', '\173', '\124',
+ '\067', '\334', '\147', '\135', '\254', '\154', '\326', '\305',
+ '\052', '\264', '\315', '\352', '\227', '\060', '\364', '\072',
+ '\017', '\100', '\017', '\075', '\324', '\027', '\102', '\017',
+ '\205', '\302', '\201', '\176', '\074', '\243', '\363', '\240',
+ '\121', '\266', '\272', '\004', '\262', '\003', '\101', '\310',
+ '\372', '\273', '\132', '\203', '\010', '\265', '\164', '\111',
+ '\077', '\367', '\036', '\264', '\056', '\266', '\136', '\307',
+ '\301', '\341', '\340', '\341', '\216', '\103', '\050', '\257',
+ '\045', '\070', '\074', '\030', '\154', '\356', '\302', '\005',
+ '\175', '\160', '\250', '\007', '\265', '\077', '\324', '\203',
+ '\076', '\355', '\355', '\105', '\237', '\366', '\365', '\165',
+ '\240', '\345', '\341', '\275', '\334', '\362', '\166', '\036',
+ '\313', '\066', '\036', '\113', '\214', '\114', '\137', '\010',
+ '\345', '\205', '\302', '\170', '\106', '\050', '\204', '\147',
+ '\070', '\153', '\140', '\367', '\001', '\372', '\245', '\163',
+ '\000', '\011', '\201', '\241', '\175', '\075', '\303', '\203',
+ '\001', '\024', '\145', '\075', '\243', '\273', '\007', '\227',
+ '\236', '\336', '\340', '\020', '\102', '\150', '\171', '\117',
+ '\357', '\356', '\000', '\102', '\273', '\203', '\010', '\101',
+ '\257', '\163', '\010', '\172', '\126', '\216', '\120', '\330',
+ '\172', '\170', '\013', '\107', '\233', '\371', '\342', '\030',
+ '\337', '\176', '\056', '\236', '\057', '\255', '\350', '\335',
+ '\201', '\026', '\276', '\130', '\323', '\307', '\214', '\145',
+ '\237', '\065', '\334', '\241', '\075', '\241', '\041', '\204',
+ '\302', '\103', '\350', '\253', '\001', '\356', '\277', '\101',
+ '\351', '\077', '\015', '\331', '\263', '\023', '\063', '\054',
+ '\300', '\005', '\130', '\163', '\050', '\320', '\217', '\147',
+ '\004', '\017', '\242', '\006', '\001', '\251', '\013', '\372',
+ '\064', '\320', '\217', '\076', '\015', '\036', '\104', '\152',
+ '\327', '\041', '\244', '\166', '\015', '\240', '\345', '\201',
+ '\176', '\074', '\067', '\170', '\020', '\025', '\077', '\020',
+ '\262', '\056', '\373', '\172', '\372', '\103', '\241', '\216',
+ '\336', '\376', '\160', '\230', '\327', '\332', '\163', '\272',
+ '\046', '\112', '\100', '\033', '\070', '\006', '\306', '\100',
+ '\076', '\326', '\310', '\172', '\320', '\010', '\216', '\200',
+ '\021', '\360', '\056', '\050', '\100', '\246', '\047', '\301',
+ '\063', '\340', '\115', '\220', '\003', '\133', '\367', '\010',
+ '\350', '\001', '\077', '\003', '\037', '\200', '\002', '\330',
+ '\272', '\047', '\301', '\363', '\340', '\115', '\060', '\167',
+ '\032', '\164', '\300', '\041', '\160', '\012', '\344', '\144',
+ '\042', '\016', '\016', '\201', '\177', '\006', '\331', '\131',
+ '\260', '\211', '\040', '\000', '\116', '\200', '\050', '\050',
+ '\201', '\361', '\154', '\003', '\107', '\300', '\033', '\331',
+ '\142', '\370', '\112', '\100', '\043', '\070', '\006', '\076',
+ '\000', '\167', '\301', '\320', '\325', '\200', '\037', '\200',
+ '\067', '\101', '\316', '\115', '\050', '\007', '\364', '\200',
+ '\023', '\040', '\012', '\112', '\162', '\120', '\016', '\070',
+ '\016', '\306', '\101', '\011', '\354', '\135', '\033', '\070',
+ '\006', '\306', '\300', '\342', '\131', '\260', '\214', '\340',
+ '\010', '\210', '\200', '\374', '\134', '\242', '\155', '\140',
+ '\010', '\274', '\001', '\062', '\140', '\144', '\312', '\100',
+ '\033', '\070', '\016', '\306', '\101', '\011', '\214', '\122',
+ '\045', '\030', '\002', '\307', '\301', '\171', '\260', '\370',
+ '\063', '\250', '\013', '\170', '\021', '\234', '\007', '\105',
+ '\163', '\240', '\003', '\216', '\200', '\010', '\050', '\232',
+ '\213', '\070', '\010', '\203', '\343', '\340', '\143', '\160',
+ '\317', '\074', '\354', '\033', '\340', '\207', '\040', '\002',
+ '\012', '\156', '\046', '\052', '\007', '\317', '\200', '\067',
+ '\301', '\334', '\133', '\320', '\117', '\340', '\020', '\030',
+ '\271', '\205', '\007', '\205', '\150', '\045', '\350', '\000',
+ '\317', '\202', '\023', '\340', '\014', '\210', '\202', '\374',
+ '\133', '\221', '\006', '\332', '\300', '\161', '\360', '\061',
+ '\050', '\376', '\054', '\372', '\013', '\034', '\003', '\347',
+ '\301', '\342', '\317', '\241', '\216', '\340', '\105', '\160',
+ '\036', '\054', '\056', '\100', '\034', '\274', '\010', '\316',
+ '\202', '\271', '\267', '\141', '\314', '\101', '\017', '\070',
+ '\001', '\242', '\340', '\236', '\371', '\104', '\176', '\360',
+ '\103', '\360', '\001', '\130', '\124', '\210', '\375', '\010',
+ '\034', '\002', '\047', '\100', '\024', '\254', '\304', '\306',
+ '\126', '\015', '\236', '\001', '\247', '\100', '\316', '\355',
+ '\310', '\007', '\252', '\301', '\017', '\300', '\273', '\240',
+ '\140', '\001', '\321', '\217', '\320', '\167', '\137', '\102',
+ '\137', '\075', '\211', '\360', '\361', '\265', '\104', '\131',
+ '\230', '\164', '\271', '\053', '\211', '\012', '\127', '\021',
+ '\255', '\342', '\262', '\320', '\337', '\343', '\030', '\373',
+ '\261', '\164', '\201', '\303', '\054', '\343', '\064', '\326',
+ '\141', '\135', '\053', '\017', '\046', '\150', '\341', '\070',
+ '\121', '\151', '\224', '\250', '\163', '\202', '\150', '\242',
+ '\023', '\172', '\245', '\320', '\207', '\336', '\130', '\256',
+ '\300', '\141', '\226', '\161', '\032', '\353', '\260', '\056',
+ '\347', '\341', '\274', '\124', '\014', '\120', '\026', '\101',
+ '\147', '\104', '\363', '\360', '\163', '\106', '\360', '\274',
+ '\010', '\150', '\304', '\263', '\113', '\170', '\036', '\143',
+ '\276', '\317', '\002', '\131', '\146', '\137', '\212', '\000',
+ '\224', '\101', '\050', '\057', '\200', '\162', '\043', '\140',
+ '\274', '\124', '\236', '\303', '\375', '\020', '\321', '\262',
+ '\306', '\101', '\007', '\062', '\255', '\002', '\205', '\310',
+ '\210', '\151', '\145', '\371', '\006', '\061', '\135', '\153',
+ '\061', '\031', '\312', '\004', '\236', '\320', '\052', '\161',
+ '\070', '\226', '\076', '\231', '\066', '\135', '\237', '\023',
+ '\056', '\233', '\250', '\312', '\362', '\065', '\357', '\023',
+ '\123', '\224', '\353', '\174', '\146', '\361', '\024', '\145',
+ '\230', '\162', '\247', '\172', '\146', '\200', '\233', '\214',
+ '\373', '\354', '\114', '\222', '\235', '\067', '\137', '\033',
+ '\222', '\046', '\351', '\334', '\035', '\074', '\116', '\277',
+ '\313', '\222', '\364', '\070', '\350', '\207', '\130', '\226',
+ '\350', '\074', '\204', '\171', '\265', '\066', '\303', '\206',
+ '\323', '\326', '\315', '\115', '\204', '\145', '\116', '\035',
+ '\316', '\363', '\366', '\076', '\233', '\263', '\230', '\207',
+ '\261', '\116', '\033', '\043', '\167', '\312', '\130', '\307',
+ '\231', '\007', '\217', '\266', '\130', '\010', '\333', '\261',
+ '\020', '\145', '\056', '\104', '\235', '\027', '\242', '\275',
+ '\337', '\207', '\254', '\012', '\274', '\223', '\153', '\353',
+ '\060', '\261', '\122', '\001', '\142', '\213', '\121', '\164',
+ '\326', '\050', '\346', '\332', '\050', '\352', '\062', '\212',
+ '\001', '\034', '\105', '\173', '\106', '\241', '\070', '\132',
+ '\152', '\303', '\172', '\011', '\355', '\066', '\235', '\014',
+ '\062', '\226', '\302', '\256', '\201', '\074', '\120', '\004',
+ '\312', '\100', '\000', '\104', '\227', '\332', '\072', '\214',
+ '\171', '\256', '\145', '\164', '\101', '\316', '\045', '\314',
+ '\073', '\120', '\002', '\032', '\101', '\004', '\214', '\200',
+ '\250', '\003', '\326', '\113', '\176', '\156', '\031', '\115',
+ '\015', '\367', '\347', '\172', '\264', '\175', '\263', '\113',
+ '\306', '\253', '\314', '\314', '\207', '\102', '\141', '\304',
+ '\065', '\065', '\247', '\156', '\225', '\076', '\345', '\271',
+ '\074', '\226', '\045', '\363', '\200', '\345', '\316', '\076',
+ '\147', '\106', '\350', '\352', '\230', '\366', '\215', '\244',
+ '\137', '\235', '\344', '\366', '\160', '\331', '\354', '\157',
+ '\137', '\301', '\175', '\032', '\052', '\375', '\111', '\005',
+ '\321', '\274', '\315', '\104', '\277', '\332', '\112', '\264',
+ '\245', '\034', '\154', '\101', '\030', '\314', '\103', '\370',
+ '\023', '\310', '\246', '\041', '\355', '\012', '\164', '\134',
+ '\145', '\132', '\267', '\344', '\362', '\156', '\020', '\063',
+ '\104', '\146', '\175', '\104', '\025', '\263', '\156', '\226',
+ '\241', '\316', '\113', '\323', '\022', '\206', '\322', '\102',
+ '\207', '\221', '\306', '\135', '\102', '\064', '\135', '\230',
+ '\310', '\022', '\142', '\271', '\066', '\227', '\146', '\331',
+ '\372', '\206', '\210', '\313', '\266', '\173', '\363', '\141',
+ '\157', '\147', '\025', '\210', '\315', '\163', '\302', '\062',
+ '\116', '\063', '\366', '\222', '\363', '\260', '\335', '\162',
+ '\332', '\074', '\306', '\330', '\074', '\047', '\054', '\063',
+ '\351', '\306', '\146', '\106', '\364', '\171', '\277', '\305',
+ '\230', '\317', '\131', '\106', '\364', '\163', '\234', '\127',
+ '\332', '\301', '\154', '\330', '\351', '\167', '\060', '\137',
+ '\047', '\240', '\363', '\213', '\271', '\066', '\377', '\215',
+ '\275', '\352', '\137', '\356', '\021', '\173', '\154', '\306',
+ '\227', '\165', '\056', '\255', '\040', '\372', '\115', '\053',
+ '\321', '\377', '\340', '\204', '\161', '\245', '\001', '\166',
+ '\141', '\047', '\321', '\107', '\115', '\222', '\376', '\376',
+ '\275', '\066', '\227', '\161', '\226', '\171', '\277', '\231',
+ '\350', '\164', '\207', '\075', '\217', '\306', '\165', '\257',
+ '\315', '\254', '\204', '\237', '\277', '\215', '\350', '\303',
+ '\207', '\260', '\056', '\313', '\204', '\064', '\345', '\071',
+ '\310', '\277', '\201', '\061', '\177', '\013', '\174', '\163',
+ '\273', '\055', '\267', '\332', '\221', '\053', '\066', '\170',
+ '\042', '\046', '\044', '\217', '\347', '\325', '\344', '\234',
+ '\277', '\314', '\065', '\065', '\235', '\152', '\100', '\371',
+ '\236', '\112', '\207', '\327', '\106', '\062', '\123', '\315',
+ '\251', '\251', '\364', '\230', '\007', '\261', '\077', '\256',
+ '\173', '\224', '\350', '\141', '\234', '\011', '\313', '\321',
+ '\267', '\065', '\360', '\133', '\066', '\303', '\117', '\172',
+ '\145', '\102', '\312', '\347', '\073', '\307', '\131', '\316',
+ '\351', '\254', '\307', '\372', '\234', '\157', '\047', '\306',
+ '\253', '\356', '\067', '\104', '\173', '\321', '\337', '\055',
+ '\350', '\127', '\057', '\366', '\365', '\212', '\053', '\030',
+ '\347', '\011', '\261', '\337', '\174', '\347', '\070', '\313',
+ '\071', '\235', '\365', '\130', '\237', '\363', '\161', '\172',
+ '\052', '\270', '\275', '\127', '\113', '\117', '\145', '\067',
+ '\234', '\355', '\115', '\245', '\063', '\242', '\375', '\126',
+ '\231', '\056', '\355', '\132', '\017', '\137', '\156', '\355',
+ '\154', '\151', '\117', '\147', '\247', '\366', '\167', '\247',
+ '\304', '\131', '\316', '\351', '\254', '\307', '\372', '\246',
+ '\277', '\331', '\046', '\361', '\230', '\263', '\215', '\372',
+ '\127', '\314', '\273', '\223', '\273', '\345', '\231', '\235',
+ '\372', '\154', '\216', '\263', '\174', '\052', '\033', '\346',
+ '\334', '\003', '\223', '\367', '\074', '\347', '\276', '\310',
+ '\353', '\167', '\252', '\165', '\353', '\304', '\244', '\263',
+ '\056', '\307', '\135', '\331', '\211', '\270', '\225', '\144',
+ '\271', '\225', '\277', '\324', '\306', '\254', '\355', '\367',
+ '\126', '\044', '\142', '\344', '\116', '\135', '\143', '\227',
+ '\330', '\036', '\375', '\104', '\155', '\121', '\262', '\035',
+ '\142', '\331', '\117', '\034', '\076', '\202', '\261', '\115',
+ '\306', '\046', '\045', '\267', '\311', '\330', '\237', '\344',
+ '\266', '\261', '\056', '\347', '\341', '\064', '\153', '\363',
+ '\110', '\341', '\073', '\261', '\357', '\136', '\006', '\212',
+ '\240', '\237', '\007', '\262', '\371', '\175', '\210', '\276',
+ '\277', '\140', '\073', '\156', '\275', '\176', '\340', '\212',
+ '\354', '\207', '\156', '\251', '\370', '\112', '\154', '\173',
+ '\046', '\162', '\005', '\266', '\101', '\074', '\106', '\307',
+ '\221', '\367', '\171', '\060', '\200', '\114', '\041', '\227',
+ '\354', '\315', '\256', '\024', '\317', '\266', '\034', '\053',
+ '\370', '\360', '\001', '\354', '\161', '\145', '\372', '\176',
+ '\205', '\337', '\011', '\360', '\161', '\101', '\335', '\224',
+ '\304', '\147', '\257', '\262', '\237', '\315', '\004', '\330',
+ '\347', '\343', '\147', '\147', '\312', '\073', '\030', '\076',
+ '\003', '\025', '\150', '\261', '\354', '\363', '\245', '\153',
+ '\177', '\014', '\243', '\300', '\357', '\140', '\016', '\316',
+ '\304', '\372', '\313', '\232', '\145', '\217', '\051', '\207',
+ '\131', '\306', '\151', '\303', '\111', '\143', '\372', '\321',
+ '\062', '\261', '\163', '\245', '\010', '\277', '\215', '\347',
+ '\216', '\176', '\125', '\340', '\060', '\313', '\070', '\215',
+ '\165', '\214', '\376', '\105', '\074', '\354', '\062', '\373',
+ '\213', '\070', '\243', '\114', '\107', '\131', '\267', '\362',
+ '\332', '\045', '\307', '\037', '\107', '\356', '\100', '\273',
+ '\140', '\227', '\163', '\120', '\306', '\070', '\362', '\217',
+ '\055', '\204', '\175', '\106', '\236', '\113', '\271', '\272',
+ '\237', '\103', '\247', '\224', '\347', '\112', '\261', '\370',
+ '\173', '\226', '\351', '\322', '\100', '\016', '\354', '\100',
+ '\001', '\046', '\103', '\024', '\341', '\161', '\060', '\066',
+ '\212', '\166', '\237', '\224', '\075', '\232', '\367', '\017',
+ '\366', '\343', '\070', '\374', '\063', '\074', '\373', '\365',
+ '\174', '\273', '\136', '\034', '\146', '\031', '\247', '\261',
+ '\016', '\353', '\162', '\330', '\332', '\267', '\325', '\137',
+ '\346', '\071', '\160', '\036', '\347', '\223', '\263', '\017',
+ '\114', '\266', '\171', '\054', '\343', '\264', '\061', '\035',
+ '\143', '\263', '\337', '\323', '\174', '\351', '\150', '\327',
+ '\051', '\354', '\023', '\063', '\245', '\357', '\072', '\321',
+ '\366', '\122', '\220', '\311', '\203', '\240', '\173', '\133',
+ '\036', '\045', '\322', '\146', '\372', '\002', '\244', '\073',
+ '\237', '\125', '\072', '\031', '\336', '\223', '\170', '\355',
+ '\363', '\270', '\226', '\220', '\275', '\207', '\063', '\074',
+ '\077', '\347', '\140', '\314', '\267', '\302', '\256', '\314',
+ '\301', '\144', '\371', '\167', '\334', '\013', '\127', '\112',
+ '\037', '\345', '\275', '\053', '\014', '\175', '\014', '\370',
+ '\216', '\364', '\060', '\372', '\240', '\007', '\025', '\350',
+ '\050', '\224', '\374', '\227', '\221', '\377', '\022', '\333',
+ '\014', '\356', '\177', '\246', '\324', '\366', '\073', '\330',
+ '\107', '\033', '\143', '\142', '\172', '\177', '\317', '\336',
+ '\237', '\070', '\277', '\345', '\107', '\317', '\227', '\065',
+ '\063', '\222', '\156', '\367', '\077', '\267', '\367', '\177',
+ '\265', '\314', '\053', '\346', '\034', '\204', '\064', '\230',
+ '\173', '\302', '\120', '\023', '\216', '\204', '\224', '\103',
+ '\072', '\111', '\013', '\165', '\356', '\146', '\331', '\171',
+ '\047', '\222', '\355', '\223', '\372', '\340', '\061', '\336',
+ '\307', '\264', '\333', '\346', '\253', '\355', '\163', '\241',
+ '\355', '\373', '\321', '\256', '\154', '\264', '\213', '\137',
+ '\156', '\132', '\167', '\354', '\355', '\331', '\330', '\363',
+ '\213', '\127', '\243', '\154', '\054', '\246', '\062', '\234',
+ '\143', '\003', '\274', '\230', '\246', '\311', '\142', '\212',
+ '\333', '\113', '\265', '\035', '\023', '\272', '\206', '\271',
+ '\135', '\326', '\071', '\250', '\123', '\347', '\026', '\356',
+ '\221', '\122', '\131', '\243', '\274', '\306', '\314', '\001',
+ '\212', '\333', '\376', '\072', '\374', '\211', '\356', '\112',
+ '\361', '\323', '\234', '\244', '\103', '\226', '\211', '\171',
+ '\233', '\303', '\147', '\131', '\064', '\262', '\070', '\123',
+ '\354', '\075', '\333', '\153', '\316', '\067', '\121', '\052',
+ '\066', '\235', '\363', '\246', '\053', '\153', '\334', '\260',
+ '\021', '\215', '\230', '\106', '\030', '\334', '\002', '\364',
+ '\111', '\311', '\254', '\044', '\137', '\025', '\165', '\171',
+ '\351', '\050', '\174', '\305', '\137', '\311', '\175', '\332',
+ '\033', '\104', '\067', '\035', '\111', '\175', '\067', '\172',
+ '\174', '\377', '\103', '\375', '\107', '\313', '\267', '\050',
+ '\024', '\333', '\370', '\273', '\057', '\310', '\132', '\147',
+ '\173', '\176', '\332', '\341', '\063', '\161', '\230', '\145',
+ '\234', '\306', '\072', '\121', '\355', '\123', '\247', '\017',
+ '\167', '\335', '\317', '\352', '\264', '\175', '\072', '\227',
+ '\332', '\256', '\054', '\131', '\106', '\074', '\125', '\254',
+ '\261', '\357', '\124', '\163', '\300', '\161', '\270', '\003',
+ '\144', '\216', '\042', '\225', '\312', '\325', '\362', '\304',
+ '\034', '\173', '\045', '\313', '\370', '\030', '\362', '\221',
+ '\332', '\016', '\143', '\023', '\314', '\131', '\252', '\033',
+ '\254', '\321', '\071', '\073', '\207', '\327', '\112', '\251',
+ '\334', '\027', '\252', '\274', '\333', '\241', '\153', '\316',
+ '\133', '\271', '\210', '\014', '\202', '\323', '\050', '\153',
+ '\224', '\022', '\333', '\306', '\161', '\226', '\163', '\072',
+ '\353', '\231', '\074', '\351', '\051', '\060', '\365', '\114',
+ '\225', '\236', '\233', '\202', '\344', '\275', '\075', '\225',
+ '\236', '\013', '\215', '\235', '\170', '\105', '\130', '\360',
+ '\075', '\242', '\357', '\035', '\115', '\204', '\145', '\046',
+ '\075', '\031', '\053', '\257', '\261', '\025', '\277', '\007',
+ '\234', '\067', '\125', '\273', '\222', '\333', '\237', '\252',
+ '\376', '\251', '\332', '\173', '\255', '\202', '\115', '\271',
+ '\327', '\052', '\070', '\271', '\134', '\313', '\347', '\312',
+ '\025', '\337', '\215', '\277', '\063', '\274', '\172', '\216',
+ '\150', '\321', '\277', '\141', '\257', '\347', '\367', '\156',
+ '\260', '\013', '\105', '\151', '\222', '\306', '\167', '\266',
+ '\265', '\354', '\357', '\055', '\236', '\001', '\133', '\305',
+ '\357', '\206', '\242', '\366', '\171', '\210', '\355', '\314',
+ '\153', '\260', '\115', '\357', '\275', '\243', '\176', '\373',
+ '\333', '\142', '\127', '\043', '\131', '\211', '\076', '\041',
+ '\353', '\355', '\057', '\025', '\337', '\227', '\111', '\036',
+ '\257', '\045', '\107', '\023', '\371', '\143', '\217', '\127',
+ '\304', '\261', '\316', '\170', '\235', '\360', '\032', '\167',
+ '\025', '\021', '\375', '\322', '\153', '\343', '\252', '\024',
+ '\062', '\141', '\313', '\362', '\063', '\165', '\117', '\120',
+ '\077', '\324', '\072', '\027', '\152', '\076', '\313', '\166',
+ '\244', '\260', '\001', '\321', '\121', '\373', '\375', '\031',
+ '\347', '\147', '\077', '\146', '\266', '\256', '\363', '\307',
+ '\300', '\123', '\240', '\207', '\344', '\333', '\025', '\357',
+ '\177', '\171', '\240', '\330', '\364', '\177', '\206', '\354',
+ '\107', '\226', '\001', '\300', '\363', '\331', '\201', '\162',
+ '\256', '\177', '\164', '\043', '\105', '\135', '\302', '\170',
+ '\272', '\356', '\115', '\272', '\377', '\107', '\162', '\325',
+ '\326', '\027', '\252', '\341', '\340', '\115', '\246', '\040',
+ '\161', '\137', '\073', '\225', '\043', '\070', '\353', '\167',
+ '\016', '\376', '\375', '\071', '\330', '\360', '\127', '\261',
+ '\257', '\026', '\314', '\322', '\263', '\057', '\316', '\175',
+ '\271', '\035', '\322', '\077', '\316', '\167', '\200', '\334',
+ '\166', '\143', '\117', '\131', '\166', '\021', '\106', '\344',
+ '\042', '\346', '\301', '\107', '\060', '\102', '\243', '\053',
+ '\344', '\074', '\314', '\371', '\047', '\116', '\112', '\137',
+ '\160', '\031', '\311', '\076', '\261', '\231', '\277', '\251',
+ '\316', '\354', '\123', '\371', '\300', '\116', '\337', '\330',
+ '\320', '\241', '\375', '\161', '\022', '\317', '\353', '\126',
+ '\077', '\365', '\165', '\175', '\277', '\302', '\343', '\305',
+ '\276', '\306', '\142', '\345', '\002', '\360', '\252', '\214',
+ '\375', '\227', '\161', '\355', '\307', '\011', '\335', '\107',
+ '\007', '\301', '\013', '\340', '\077', '\035', '\276', '\366',
+ '\170', '\222', '\136', '\124', '\145', '\330', '\352', '\344',
+ '\354', '\245', '\363', '\141', '\314', '\350', '\151', '\175',
+ '\142', '\032', '\077', '\003', '\016', '\221', '\370', '\012',
+ '\231', '\012', '\257', '\337', '\200', '\372', '\136', '\021',
+ '\035', '\077', '\036', '\107', '\353', '\054', '\340', '\130',
+ '\333', '\054', '\073', '\001', '\126', '\246', '\313', '\060',
+ '\316', '\327', '\162', '\114', '\147', '\225', '\201', '\100',
+ '\261', '\116', '\252', '\257', '\040', '\317', '\175', '\162',
+ '\347', '\170', '\100', '\323', '\223', '\073', '\166', '\204',
+ '\271', '\210', '\164', '\336', '\060', '\056', '\045', '\316',
+ '\131', '\216', '\263', '\234', '\323', '\107', '\234', '\235',
+ '\174', '\055', '\033', '\164', '\203', '\306', '\175', '\222',
+ '\255', '\113', '\101', '\262', '\255', '\070', '\232', '\304',
+ '\037', '\333', '\126', '\360', '\372', '\166', '\055', '\260',
+ '\211', '\055', '\224', '\367', '\060', '\116', '\056', '\102',
+ '\147', '\166', '\221', '\115', '\262', '\115', '\310', '\302',
+ '\244', '\213', '\215', '\332', '\264', '\136', '\020', '\056',
+ '\305', '\154', '\132', '\043', '\211', '\171', '\002', '\072',
+ '\267', '\370', '\133', '\017', '\163', '\214', '\111', '\227',
+ '\363', '\030', '\163', '\102', '\277', '\315', '\374', '\043',
+ '\203', '\176', '\052', '\064', '\007', '\044', '\375', '\156',
+ '\063', '\142', '\316', '\122', '\271', '\372', '\036', '\134',
+ '\141', '\277', '\060', '\376', '\216', '\074', '\246', '\357',
+ '\140', '\012', '\345', '\154', '\011', '\167', '\363', '\272',
+ '\141', '\073', '\264', '\112', '\314', '\212', '\165', '\276',
+ '\353', '\270', '\116', '\054', '\277', '\305', '\045', '\353',
+ '\243', '\303', '\261', '\016', '\331', '\337', '\145', '\137',
+ '\223', '\373', '\074', '\267', '\115', '\356', '\034', '\147',
+ '\071', '\373', '\237', '\354', '\117', '\046', '\217', '\045',
+ '\307', '\131', '\316', '\351', '\331', '\272', '\056', '\330',
+ '\347', '\312', '\325', '\173', '\216', '\326', '\255', '\130',
+ '\237', '\023', '\157', '\257', '\336', '\071', '\136', '\242',
+ '\351', '\226', '\242', '\236', '\263', '\330', '\150', '\130',
+ '\367', '\174', '\262', '\013', '\056', '\320', '\161', '\355',
+ '\244', '\370', '\373', '\120', '\113', '\247', '\100', '\322',
+ '\263', '\065', '\270', '\112', '\373', '\346', '\106', '\372',
+ '\062', '\117', '\353', '\147', '\354', '\230', '\351', '\243',
+ '\353', '\355', '\323', '\033', '\171', '\166', '\362', '\270',
+ '\135', '\357', '\163', '\247', '\032', '\067', '\353', '\120',
+ '\317', '\233', '\032', '\357', '\065', '\173', '\061', '\117',
+ '\301', '\020', '\010', '\047', '\161', '\010', '\014', '\200',
+ '\127', '\100', '\076', '\157', '\200', '\306', '\210', '\071',
+ '\053', '\215', '\076', '\255', '\004', '\215', '\240', '\055',
+ '\211', '\016', '\260', '\077', '\046', '\357', '\222', '\366',
+ '\103', '\267', '\170', '\077', '\131', '\357', '\035', '\330',
+ '\134', '\271', '\034', '\360', '\231', '\175', '\166', '\232',
+ '\275', '\056', '\363', '\026', '\310', '\231', '\234', '\160',
+ '\106', '\267', '\214', '\077', '\006', '\172', '\244', '\224',
+ '\022', '\336', '\057', '\361', '\262', '\341', '\363', '\272',
+ '\205', '\163', '\155', '\216', '\312', '\231', '\174', '\114',
+ '\215', '\370', '\110', '\314', '\046', '\203', '\317', '\147',
+ '\031', '\102', '\136', '\232', '\160', '\356', '\234', '\274',
+ '\257', '\345', '\275', '\220', '\341', '\060', '\313', '\114',
+ '\272', '\321', '\347', '\274', '\231', '\230', '\127', '\071',
+ '\071', '\022', '\147', '\337', '\202', '\367', '\116', '\336',
+ '\067', '\077', '\175', '\100', '\375', '\052', '\344', '\377',
+ '\264', '\120', '\144', '\234', '\226', '\237', '\046', '\172',
+ '\234', '\207', '\363', '\362', '\006', '\302', '\266', '\341',
+ '\056', '\334', '\377', '\006', '\367', '\233', '\063', '\305',
+ '\067', '\300', '\366', '\115', '\070', '\266', '\320', '\347',
+ '\223', '\356', '\137', '\320', '\064', '\206', '\365', '\270',
+ '\357', '\363', '\161', '\306', '\357', '\120', '\366', '\317',
+ '\244', '\370', '\373', '\211', '\353', '\201', '\237', '\355',
+ '\174', '\337', '\132', '\224', '\146', '\363', '\174', '\201',
+ '\234', '\005', '\171', '\135', '\032', '\337', '\161', '\021',
+ '\316', '\255', '\163', '\347', '\312', '\172', '\346', '\167',
+ '\312', '\234', '\337', '\274', '\167', '\344', '\063', '\045',
+ '\303', '\347', '\313', '\022', '\314', '\213', '\027', '\060',
+ '\271', '\322', '\043', '\230', '\122', '\035', '\122', '\026',
+ '\177', '\367', '\340', '\167', '\243', '\313', '\227', '\213',
+ '\377', '\311', '\147', '\113', '\316', '\307', '\276', '\016',
+ '\237', '\057', '\271', '\114', '\076', '\247', '\166', '\127',
+ '\312', '\371', '\223', '\357', '\346', '\334', '\152', '\316',
+ '\237', '\043', '\111', '\357', '\050', '\127', '\316', '\227',
+ '\162', '\370', '\254', '\372', '\032', '\306', '\250', '\352',
+ '\035', '\271', '\233', '\263', '\053', '\247', '\133', '\176',
+ '\154', '\172', '\352', '\357', '\070', '\154', '\063', '\123',
+ '\245', '\245', '\174', '\027', '\353', '\260', '\135', '\251',
+ '\164', '\314', '\226', '\271', '\112', '\327', '\244', '\365',
+ '\275', '\042', '\327', '\366', '\101', '\212', '\215', '\217',
+ '\310', '\357', '\327', '\170', '\001', '\263', '\361', '\050',
+ '\222', '\171', '\134', '\250', '\113', '\151', '\102', '\337',
+ '\223', '\106', '\325', '\316', '\133', '\066', '\137', '\333',
+ '\077', '\306', '\176', '\035', '\373', '\202', '\150', '\147',
+ '\204', '\035', '\230', '\010', '\131', '\016', '\214', '\071',
+ '\003', '\073', '\267', '\156', '\376', '\046', '\127', '\105',
+ '\362', '\215', '\216', '\277', '\325', '\131', '\337', '\354',
+ '\062', '\344', '\033', '\136', '\374', '\154', '\023', '\113',
+ '\204', '\353', '\356', '\374', '\046', '\147', '\175', '\243',
+ '\313', '\322', '\157', '\166', '\005', '\372', '\015', '\257',
+ '\330', '\161', '\346', '\321', '\347', '\072', '\035', '\300',
+ '\250', '\176', '\233', '\053', '\323', '\157', '\165', '\171',
+ '\372', '\355', '\056', '\303', '\361', '\255', '\156', '\322',
+ '\167', '\276', '\261', '\304', '\157', '\162', '\043', '\372',
+ '\255', '\256', '\121', '\277', '\335', '\361', '\067', '\274',
+ '\034', '\375', '\126', '\147', '\175', '\257', '\053', '\024',
+ '\110', '\307', '\214', '\273', '\201', '\277', '\311', '\361',
+ '\267', '\071', '\376', '\106', '\227', '\162', '\334', '\073',
+ '\047', '\217', '\143', '\362', '\373', '\157', '\236', '\263',
+ '\051', '\347', '\200', '\266', '\167', '\204', '\256', '\361',
+ '\235', '\056', '\251', '\175', '\327', '\372', '\136', '\227',
+ '\055', '\115', '\111', '\060', '\251', '\255', '\064', '\331',
+ '\336', '\177', '\213', '\344', '\147', '\150', '\033', '\110',
+ '\176', '\234', '\146', '\060', '\357', '\344', '\222', '\367',
+ '\002', '\247', '\315', '\177', '\071', '\111', '\376', '\226',
+ '\162', '\322', '\361', '\056', '\342', '\232', '\147', '\341',
+ '\353', '\074', '\323', '\033', '\302', '\074', '\317', '\161',
+ '\366', '\374', '\071', '\174', '\332', '\017', '\247', '\313',
+ '\357', '\124', '\326', '\344', '\247', '\030', '\037', '\265',
+ '\107', '\001', '\204', '\317', '\267', '\020', '\135', '\176',
+ '\233', '\350', '\112', '\251', '\356', '\371', '\352', '\223',
+ '\235', '\156', '\237', '\142', '\134', '\262', '\022', '\011',
+ '\134', '\217', '\137', '\153', '\374', '\337', '\353', '\364',
+ '\143', '\015', '\146', '\177', '\060', '\347', '\250', '\076',
+ '\264', '\245', '\033', '\363', '\071', '\210', '\011', '\370',
+ '\323', '\163', '\302', '\355', '\010', '\317', '\051', '\026',
+ '\133', '\037', '\235', '\042', '\217', '\341', '\132', '\347',
+ '\117', '\363', '\316', '\325', '\231', '\247', '\325', '\061',
+ '\027', '\256', '\207', '\002', '\235', '\107', '\243', '\216',
+ '\161', '\067', '\373', '\377', '\325', '\160', '\372', '\014',
+ '\234', '\127', '\176', '\107', '\370', '\035', '\062', '\177',
+ '\056', '\110', '\322', '\341', '\100', '\114', '\303', '\146',
+ '\226', '\205', '\047', '\115', '\247', '\031', '\164', '\023',
+ '\066', '\246', '\231', '\160', '\050', '\162', '\255', '\337',
+ '\023', '\176', '\206', '\346', '\300', '\143', '\231', '\107',
+ '\067', '\323', '\055', '\160', '\304', '\156', '\245', '\317',
+ '\322', '\347', '\120', '\233', '\333', '\340', '\074', '\024',
+ '\302', '\340', '\335', '\116', '\013', '\150', '\041', '\066',
+ '\366', '\317', '\323', '\035', '\330', '\337', '\026', '\323',
+ '\235', '\264', '\204', '\276', '\110', '\167', '\321', '\335',
+ '\364', '\045', '\372', '\062', '\014', '\304', '\122', '\034',
+ '\202', '\226', '\321', '\075', '\164', '\057', '\055', '\247',
+ '\373', '\120', '\243', '\025', '\164', '\077', '\075', '\000',
+ '\247', '\341', '\253', '\130', '\015', '\245', '\230', '\055',
+ '\253', '\351', '\101', '\132', '\103', '\153', '\151', '\035',
+ '\175', '\215', '\036', '\242', '\365', '\130', '\017', '\017',
+ '\323', '\237', '\321', '\043', '\364', '\165', '\332', '\110',
+ '\233', '\150', '\063', '\075', '\212', '\023', '\372', '\343',
+ '\124', '\116', '\133', '\350', '\033', '\264', '\225', '\266',
+ '\321', '\166', '\172', '\202', '\276', '\111', '\117', '\142',
+ '\375', '\074', '\105', '\025', '\124', '\111', '\156', '\332',
+ '\001', '\333', '\130', '\115', '\036', '\332', '\111', '\273',
+ '\250', '\206', '\152', '\351', '\317', '\261', '\256', '\274',
+ '\124', '\107', '\365', '\324', '\200', '\223', '\341', '\156',
+ '\362', '\121', '\023', '\371', '\251', '\231', '\132', '\320',
+ '\177', '\155', '\324', '\116', '\173', '\150', '\057', '\172',
+ '\145', '\037', '\355', '\307', '\232', '\014', '\120', '\220',
+ '\272', '\250', '\033', '\247', '\377', '\136', '\352', '\243',
+ '\020', '\205', '\351', '\000', '\365', '\323', '\101', '\234',
+ '\022', '\017', '\323', '\000', '\015', '\322', '\020', '\015',
+ '\323', '\137', '\320', '\323', '\364', '\014', '\375', '\045',
+ '\375', '\025', '\375', '\065', '\075', '\153', '\365', '\234',
+ '\371', '\175', '\330', '\242', '\264', '\077', '\361', '\047',
+ '\260', '\037', '\052', '\377', '\337', '\345', '\076', '\350',
+ '\022', '\322', '\310', '\376', '\075', '\042', '\377', '\316',
+ '\231', '\177', '\362', '\206', '\355', '\315', '\162', '\245',
+ '\127', '\200', '\115', '\044', '\357', '\260', '\174', '\152',
+ '\043', '\370', '\135', '\142', '\077', '\170', '\026', '\274',
+ '\004', '\136', '\003', '\157', '\221', '\154', '\271', '\374',
+ '\116', '\144', '\246', '\113', '\176', '\307', '\270', '\030',
+ '\054', '\003', '\153', '\300', '\106', '\360', '\024', '\360',
+ '\200', '\335', '\240', '\025', '\164', '\201', '\303', '\340',
+ '\273', '\340', '\373', '\340', '\357', '\301', '\011', '\227',
+ '\274', '\163', '\376', '\065', '\070', '\017', '\076', '\005',
+ '\323', '\121', '\301', '\231', '\340', '\146', '\160', '\033',
+ '\270', '\023', '\054', '\117', '\223', '\075', '\274', '\034',
+ '\170', '\300', '\156', '\320', '\005', '\016', '\203', '\357',
+ '\202', '\277', '\003', '\077', '\006', '\057', '\203', '\177',
+ '\002', '\277', '\004', '\377', '\001', '\042', '\340', '\175',
+ '\160', '\021', '\104', '\101', '\032', '\154', '\373', '\114',
+ '\060', '\207', '\337', '\273', '\200', '\205', '\340', '\356',
+ '\164', '\371', '\035', '\332', '\172', '\360', '\050', '\250',
+ '\000', '\265', '\240', '\015', '\004', '\323', '\345', '\175',
+ '\370', '\163', '\340', '\050', '\370', '\021', '\370', '\051',
+ '\370', '\005', '\070', '\003', '\316', '\202', '\377', '\002',
+ '\037', '\202', '\014', '\354', '\151', '\063', '\300', '\274',
+ '\014', '\371', '\155', '\346', '\142', '\360', '\145', '\360',
+ '\200', '\176', '\067', '\175', '\030', '\154', '\007', '\165',
+ '\240', '\025', '\364', '\201', '\141', '\360', '\267', '\340',
+ '\045', '\360', '\062', '\170', '\035', '\274', '\005', '\042',
+ '\340', '\002', '\270', '\004', '\246', '\361', '\267', '\063',
+ '\160', '\007', '\050', '\001', '\233', '\300', '\267', '\100',
+ '\043', '\350', '\004', '\117', '\203', '\027', '\300', '\061',
+ '\360', '\052', '\370', '\065', '\070', '\007', '\056', '\200',
+ '\117', '\200', '\213', '\177', '\373', '\011', '\346', '\202',
+ '\333', '\300', '\027', '\063', '\305', '\057', '\277', '\037',
+ '\254', '\006', '\137', '\007', '\345', '\374', '\035', '\010',
+ '\064', '\200', '\156', '\360', '\064', '\170', '\021', '\374',
+ '\003', '\070', '\015', '\316', '\200', '\337', '\202', '\013',
+ '\340', '\062', '\277', '\350', '\302', '\236', '\065', '\003',
+ '\314', '\001', '\267', '\203', '\045', '\354', '\267', '\203',
+ '\325', '\140', '\023', '\330', '\002', '\052', '\301', '\116',
+ '\260', '\033', '\154', '\253', '\320', '\337', '\256', '\233',
+ '\100', '\105', '\235', '\273', '\351', '\333', '\344', '\366',
+ '\371', '\032', '\132', '\345', '\052', '\202', '\035', '\356',
+ '\046', '\117', '\165', '\205', '\010', '\252', '\033', '\132',
+ '\353', '\047', '\011', '\046', '\253', '\065', '\067', '\046',
+ '\105', '\125', '\245', '\301', '\355', '\267', '\056', '\046',
+ '\272', '\253', '\241', '\251', '\326', '\337', '\036', '\017',
+ '\030', '\261', '\337', '\337', '\120', '\127', '\341', '\365',
+ '\354', '\364', '\127', '\124', '\065', '\370', '\352', '\075',
+ '\276', '\051', '\104', '\011', '\252', '\276', '\332', '\135',
+ '\065', '\311', '\272', '\116', '\131', '\202', '\162', '\123',
+ '\155', '\265', '\307', '\031', '\116', '\110', '\364', '\173',
+ '\074', '\216', '\240', '\111', '\152', '\253', '\150', '\152',
+ '\254', '\365', '\271', '\275', '\216', '\240', '\044', '\125',
+ '\171', '\352', '\375', '\050', '\276', '\321', '\357', '\163',
+ '\004', '\065', '\251', '\326', '\127', '\345', '\365', '\350',
+ '\115', '\105', '\336', '\206', '\052', '\275', '\252', '\240',
+ '\141', '\347', '\116', '\176', '\112', '\363', '\056', '\107',
+ '\120', '\223', '\174', '\015', '\115', '\115', '\162', '\165',
+ '\010', '\052', '\174', '\236', '\026', '\217', '\257', '\311',
+ '\223', '\030', '\163', '\050', '\324', '\270', '\153', '\175',
+ '\166', '\110', '\022', '\252', '\153', '\335', '\165', '\015',
+ '\365', '\325', '\025', '\122', '\144', '\102', '\114', '\025',
+ '\032', '\374', '\114', '\074', '\202', '\126', '\352', '\315',
+ '\210', '\232', '\167', '\240', '\015', '\062', '\061', '\234',
+ '\021', '\115', '\366', '\271', '\061', '\054', '\136', '\267',
+ '\157', '\227', '\307', '\031', '\166', '\046', '\066', '\325',
+ '\271', '\275', '\136', '\147', '\070', '\236', '\330', '\210',
+ '\111', '\142', '\075', '\057', '\036', '\224', '\044', '\117',
+ '\133', '\125', '\215', '\273', '\036', '\045', '\232', '\200',
+ '\210', '\167', '\172', '\075', '\315', '\076', '\271', '\212',
+ '\140', '\127', '\303', '\016', '\124', '\307', '\147', '\356',
+ '\052', '\154', '\256', '\333', '\321', '\056', '\127', '\021',
+ '\240', '\204', '\352', '\245', '\162', '\265', '\005', '\137',
+ '\221', '\253', '\012', '\074', '\156', '\237', '\137', '\256',
+ '\042', '\250', '\255', '\152', '\250', '\267', '\056', '\032',
+ '\365', '\041', '\044', '\075', '\150', '\007', '\045', '\311',
+ '\232', '\225', '\074', '\005', '\114', '\300', '\041', '\266',
+ '\046', '\133', '\074', '\344', '\110', '\340', '\211', '\146',
+ '\002', '\266', '\170', '\107', '\063', '\246', '\136', '\275',
+ '\043', '\250', '\111', '\336', '\012', '\164', '\001', '\146',
+ '\223', '\011', '\250', '\330', '\147', '\304', '\076', '\247',
+ '\270', '\316', '\135', '\317', '\150', '\244', '\266', '\272',
+ '\332', '\353', '\321', '\162', '\235', '\021', '\115', '\156',
+ '\150', '\306', '\154', '\262', '\256', '\042', '\150', '\364',
+ '\324', '\127', '\325', '\172', '\365', '\246', '\042', '\314',
+ '\167', '\277', '\107', '\157', '\052', '\362', '\066', '\067',
+ '\131', '\027', '\211', '\356', '\156', '\366', '\064', '\371',
+ '\153', '\121', '\246', '\114', '\221', '\304', '\250', '\250',
+ '\310', '\162', '\344', '\136', '\212', '\207', '\234', '\011',
+ '\126', '\077', '\331', '\101', '\147', '\022', '\367', '\124',
+ '\074', '\344', '\110', '\320', '\066', '\071', '\302', '\232',
+ '\350', '\367', '\126', '\170', '\141', '\120', '\342', '\001',
+ '\021', '\067', '\271', '\153', '\275', '\226', '\375', '\061',
+ '\001', '\025', '\357', '\020', '\023', '\046', '\065', '\117',
+ '\210', '\305', '\025', '\152', '\052', '\022', '\126', '\300',
+ '\044', '\111', '\134', '\321', '\032', '\320', '\270', '\222',
+ '\035', '\213', '\053', '\110', '\073', '\342', '\032', '\216',
+ '\150', '\134', '\005', '\266', '\062', '\236', '\156', '\302',
+ '\361', '\304', '\226', '\111', '\065', '\151', '\231', '\252',
+ '\046', '\065', '\350', '\016', '\114', '\013', '\275', '\253',
+ '\260', '\166', '\117', '\155', '\375', '\056', '\275', '\251',
+ '\250', '\021', '\135', '\355', '\323', '\233', '\021', '\371',
+ '\334', '\355', '\125', '\230', '\100', '\046', '\240', '\142',
+ '\277', '\333', '\147', '\135', '\044', '\352', '\347', '\365',
+ '\355', '\327', '\233', '\212', '\144', '\155', '\370', '\035',
+ '\353', '\302', '\337', '\320', '\350', '\354', '\221', '\304',
+ '\150', '\222', '\212', '\332', '\356', '\244', '\270', '\255',
+ '\224', '\140', '\341', '\223', '\005', '\266', '\232', '\065',
+ '\215', '\114', '\300', '\026', '\363', '\024', '\322', '\273',
+ '\012', '\175', '\036', '\271', '\110', '\264', '\331', '\254',
+ '\257', '\346', '\204', '\365', '\005', '\373', '\341', '\363',
+ '\170', '\275', '\356', '\170', '\100', '\305', '\146', '\331',
+ '\065', '\047', '\054', '\273', '\126', '\267', '\277', '\252',
+ '\106', '\256', '\042', '\150', '\303', '\176', '\120', '\047',
+ '\127', '\021', '\320', '\215', '\377', '\217', '\327', '\377',
+ '\001', '\226', '\047', '\030', '\162', '\200', '\067', '\000',
+ '\000',
+
+};
+
+static const char file_6x13[] = {
+ '\037', '\213', '\010', '\010', '\126', '\121', '\054', '\100',
+ '\000', '\003', '\066', '\170', '\061', '\063', '\055', '\111',
+ '\123', '\117', '\070', '\070', '\065', '\071', '\055', '\061',
+ '\056', '\160', '\143', '\146', '\000', '\355', '\234', '\177',
+ '\170', '\024', '\307', '\171', '\307', '\277', '\002', '\001',
+ '\002', '\013', '\020', '\106', '\004', '\141', '\203', '\045',
+ '\333', '\330', '\306', '\066', '\262', '\045', '\014', '\030',
+ '\073', '\330', '\346', '\054', '\035', '\240', '\104', '\110',
+ '\030', '\111', '\061', '\070', '\151', '\345', '\343', '\156',
+ '\045', '\155', '\270', '\037', '\362', '\375', '\300', '\222',
+ '\215', '\101', '\010', '\044', '\204', '\114', '\012', '\051',
+ '\216', '\103', '\034', '\222', '\100', '\203', '\123', '\334',
+ '\342', '\032', '\327', '\264', '\265', '\023', '\307', '\165',
+ '\152', '\047', '\301', '\055', '\165', '\150', '\202', '\133',
+ '\352', '\322', '\230', '\076', '\365', '\037', '\364', '\251',
+ '\363', '\074', '\116', '\037', '\047', '\161', '\373', '\270',
+ '\245', '\337', '\331', '\335', '\071', '\215', '\206', '\335',
+ '\273', '\225', '\340', '\111', '\237', '\247', '\017', '\003',
+ '\237', '\331', '\331', '\335', '\171', '\147', '\346', '\175',
+ '\347', '\335', '\231', '\331', '\071', '\335', '\025', '\264',
+ '\205', '\073', '\047', '\002', '\050', '\040', '\143', '\110',
+ '\007', '\243', '\175', '\116', '\172', '\014', '\057', '\106',
+ '\170', '\304', '\130', '\240', '\120', '\236', '\063', '\021',
+ '\341', '\171', '\221', '\223', '\347', '\154', '\025', '\160',
+ '\174', '\002', '\120', '\242', '\334', '\077', '\274', '\004',
+ '\250', '\160', '\356', '\227', '\060', '\052', '\276', '\007',
+ '\130', '\346', '\234', '\157', '\247', '\354', '\354', '\373',
+ '\200', '\036', '\347', '\174', '\037', '\053', '\077', '\160',
+ '\277', '\335', '\000', '\131', '\337', '\222', '\172', '\373',
+ '\336', '\247', '\140', '\207', '\202', '\053', '\031', '\115',
+ '\027', '\211', '\253', '\141', '\227', '\134', '\060', '\237',
+ '\321', '\002', '\221', '\270', '\227', '\121', '\120', '\044',
+ '\076', '\313', '\150', '\225', '\110', '\174', '\236', '\221',
+ '\051', '\022', '\135', '\214', '\272', '\205', '\374', '\144',
+ '\121', '\257', '\110', '\210', '\053', '\273', '\105', '\102',
+ '\144', '\336', '\057', '\023', '\317', '\211', '\314', '\057',
+ '\062', '\172', '\111', '\134', '\131', '\112', '\176', '\040',
+ '\256', '\374', '\224', '\321', '\273', '\042', '\361', '\357',
+ '\214', '\176', '\041', '\022', '\277', '\141', '\064', '\107',
+ '\030', '\112', '\030', '\154', '\236', '\110', '\214', '\047',
+ '\325', '\114', '\024', '\054', '\146', '\264', '\121', '\134',
+ '\231', '\104', '\236', '\020', '\211', '\166', '\062', '\040',
+ '\363', '\000', '\173', '\231', '\134', '\336', '\330', '\320',
+ '\334', '\020', '\130', '\025', '\154', '\135', '\023', '\134',
+ '\121', '\327', '\324', '\274', '\146', '\235', '\270', '\324',
+ '\322', '\120', '\313', '\304', '\052', '\063', '\025', '\306',
+ '\362', '\300', '\252', '\272', '\372', '\165', '\255', '\042',
+ '\013', '\226', '\233', '\135', '\106', '\004', '\017', '\006',
+ '\353', '\126', '\254', '\154', '\266', '\257', '\254', '\062',
+ '\042', '\146', '\046', '\206', '\246', '\372', '\100', '\103',
+ '\063', '\326', '\240', '\051', '\330', '\374', '\140', '\135',
+ '\155', '\363', '\112', '\373', '\146', '\223', '\021', '\063',
+ '\153', '\022', '\361', '\210', '\021', '\117', '\121', '\054',
+ '\120', '\133', '\333', '\332', '\324', '\274', '\256', '\076',
+ '\150', '\337', '\304', '\352', '\272', '\265', '\301', '\372',
+ '\326', '\246', '\272', '\207', '\202', '\130', '\335', '\130',
+ '\327', '\320', '\154', '\047', '\327', '\004', '\233', '\032',
+ '\353', '\133', '\232', '\353', '\032', '\033', '\132', '\327',
+ '\252', '\047', '\353', '\320', '\264', '\072', '\120', '\123',
+ '\327', '\260', '\002', '\065', '\010', '\174', '\056', '\270',
+ '\046', '\260', '\042', '\330', '\152', '\125', '\205', '\232',
+ '\225', '\201', '\065', '\254', '\167', '\250', '\375', '\165',
+ '\115', '\215', '\113', '\226', '\054', '\272', '\053', '\173',
+ '\043', '\330', '\120', '\323', '\130', '\053', '\044', '\253',
+ '\121', '\323', '\270', '\172', '\335', '\032', '\321', '\172',
+ '\254', '\316', '\254', '\217', '\232', '\341', '\212', '\110',
+ '\042', '\026', '\062', '\343', '\025', '\155', '\211', '\170',
+ '\372', '\266', '\212', '\212', '\246', '\216', '\120', '\322',
+ '\250', '\010', '\305', '\043', '\025', '\106', '\374', '\213',
+ '\211', '\356', '\333', '\120', '\023', '\130', '\335', '\272',
+ '\322', '\122', '\027', '\153', '\145', '\102', '\030', '\014',
+ '\225', '\302', '\066', '\225', '\226', '\075', '\052', '\155',
+ '\033', '\124', '\256', '\251', '\034', '\246', '\157', '\145',
+ '\145', '\365', '\035', '\225', '\325', '\013', '\252', '\052',
+ '\357', '\134', '\044', '\376', '\327', '\124', '\056', '\256',
+ '\252', '\164', '\132', '\126', '\131', '\355', '\330', '\120',
+ '\121', '\020', '\017', '\264', '\004', '\152', '\035', '\215',
+ '\054', '\237', '\053', '\260', '\002', '\160', '\205', '\343',
+ '\223', '\166', '\030', '\317', '\177', '\127', '\070', '\347',
+ '\152', '\132', '\234', '\235', '\077', '\377', '\353', '\363',
+ '\042', '\357', '\360', '\353', '\136', '\101', '\324', '\361',
+ '\036', '\172', '\372', '\373', '\237', '\354', '\275', '\034',
+ '\135', '\216', '\056', '\107', '\227', '\243', '\113', '\033',
+ '\071', '\343', '\326', '\173', '\316', '\170', '\263', '\120',
+ '\314', '\343', '\316', '\014', '\167', '\222', '\024', '\162',
+ '\374', '\131', '\102', '\242', '\344', '\000', '\071', '\105',
+ '\212', '\050', '\260', '\224', '\164', '\222', '\103', '\344',
+ '\264', '\230', '\247', '\071', '\067', '\057', '\043', '\151',
+ '\162', '\230', '\234', '\041', '\045', '\234', '\317', '\153',
+ '\111', '\027', '\071', '\102', '\316', '\222', '\322', '\161',
+ '\300', '\112', '\262', '\211', '\034', '\045', '\357', '\223',
+ '\062', '\116', '\163', '\365', '\244', '\207', '\034', '\043',
+ '\347', '\310', '\154', '\256', '\013', '\126', '\223', '\355',
+ '\344', '\145', '\362', '\001', '\251', '\340', '\302', '\241',
+ '\231', '\014', '\220', '\127', '\311', '\207', '\144', '\056',
+ '\347', '\323', '\265', '\144', '\027', '\171', '\235', '\174',
+ '\104', '\346', '\161', '\042', '\375', '\002', '\331', '\103',
+ '\336', '\044', '\037', '\223', '\371', '\034', '\240', '\037',
+ '\046', '\117', '\221', '\343', '\344', '\023', '\122', '\125',
+ '\314', '\065', '\003', '\331', '\107', '\116', '\024', '\333',
+ '\223', '\375', '\102', '\322', '\101', '\366', '\223', '\223',
+ '\244', '\160', '\012', '\365', '\047', '\121', '\162', '\200',
+ '\234', '\042', '\105', '\123', '\251', '\077', '\351', '\044',
+ '\207', '\310', '\151', '\122', '\314', '\105', '\314', '\062',
+ '\222', '\046', '\207', '\311', '\031', '\122', '\062', '\215',
+ '\372', '\223', '\056', '\162', '\204', '\234', '\045', '\245',
+ '\134', '\217', '\254', '\044', '\233', '\310', '\121', '\362',
+ '\076', '\051', '\343', '\372', '\244', '\236', '\364', '\220',
+ '\143', '\344', '\034', '\231', '\135', '\112', '\375', '\311',
+ '\166', '\362', '\062', '\371', '\200', '\124', '\314', '\240',
+ '\376', '\144', '\200', '\274', '\112', '\076', '\044', '\163',
+ '\271', '\320', '\131', '\113', '\166', '\221', '\327', '\311',
+ '\107', '\144', '\336', '\114', '\352', '\117', '\366', '\220',
+ '\067', '\311', '\307', '\144', '\176', '\031', '\365', '\047',
+ '\117', '\221', '\343', '\344', '\023', '\122', '\065', '\213',
+ '\372', '\223', '\175', '\344', '\004', '\301', '\125', '\324',
+ '\237', '\164', '\220', '\375', '\344', '\044', '\051', '\344',
+ '\262', '\151', '\011', '\211', '\222', '\003', '\344', '\024',
+ '\051', '\232', '\115', '\375', '\111', '\047', '\071', '\104',
+ '\116', '\223', '\342', '\071', '\324', '\237', '\244', '\311',
+ '\141', '\162', '\206', '\224', '\134', '\103', '\375', '\111',
+ '\027', '\071', '\102', '\316', '\222', '\322', '\162', '\352',
+ '\117', '\066', '\221', '\243', '\344', '\175', '\122', '\306',
+ '\145', '\131', '\075', '\351', '\041', '\307', '\310', '\071',
+ '\062', '\373', '\132', '\352', '\117', '\266', '\223', '\227',
+ '\311', '\007', '\244', '\342', '\072', '\352', '\117', '\006',
+ '\310', '\253', '\344', '\103', '\062', '\367', '\172', '\352',
+ '\117', '\166', '\221', '\327', '\311', '\107', '\144', '\336',
+ '\134', '\352', '\117', '\366', '\220', '\067', '\311', '\307',
+ '\144', '\376', '\015', '\324', '\237', '\074', '\105', '\216',
+ '\223', '\117', '\110', '\325', '\215', '\324', '\237', '\354',
+ '\043', '\047', '\010', '\156', '\242', '\376', '\244', '\203',
+ '\354', '\047', '\047', '\111', '\341', '\074', '\352', '\117',
+ '\242', '\344', '\000', '\071', '\105', '\212', '\156', '\246',
+ '\376', '\244', '\223', '\034', '\042', '\247', '\111', '\361',
+ '\055', '\324', '\237', '\244', '\311', '\141', '\162', '\206',
+ '\224', '\334', '\112', '\375', '\111', '\027', '\071', '\102',
+ '\316', '\222', '\122', '\256', '\076', '\127', '\222', '\115',
+ '\344', '\050', '\171', '\237', '\224', '\125', '\002', '\115',
+ '\364', '\307', '\357', '\260', '\357', '\352', '\231', '\336',
+ '\367', '\320', '\320', '\374', '\077', '\303', '\071', '\116',
+ '\363', '\070', '\316', '\200', '\167', '\020', '\353', '\156',
+ '\272', '\053', '\312', '\235', '\143', '\241', '\113', '\036',
+ '\041', '\177', '\313', '\010', '\217', '\062', '\214', '\163',
+ '\230', '\240', '\244', '\351', '\012', '\326', '\372', '\136',
+ '\242', '\007', '\221', '\127', '\254', '\154', '\307', '\072',
+ '\307', '\071', '\116', '\273', '\212', '\235', '\243', '\133',
+ '\033', '\307', '\073', '\171', '\345', '\212', '\130', '\344',
+ '\055', '\125', '\216', '\245', '\056', '\062', '\005', '\012',
+ '\023', '\234', '\166', '\345', '\253', '\107', '\334', '\273',
+ '\322', '\241', '\330', '\345', '\276', '\127', '\220', '\345',
+ '\225', '\153', '\145', '\227', '\173', '\344', '\027', '\257',
+ '\000', '\142', '\275', '\070', '\331', '\111', '\027', '\152',
+ '\314', '\166', '\221', '\031', '\247', '\060', '\306', '\301',
+ '\313', '\326', '\172', '\171', '\222', '\011', '\043', '\320',
+ '\111', '\206', '\011', '\071', '\312', '\363', '\012', '\113',
+ '\163', '\310', '\170', '\261', '\064', '\107', '\171', '\136',
+ '\062', '\367', '\345', '\271', '\167', '\061', '\341', '\377',
+ '\203', '\174', '\056', '\133', '\217', '\264', '\177', '\162',
+ '\371', '\301', '\245', '\354', '\203', '\134', '\355', '\036',
+ '\015', '\152', '\340', '\224', '\227', '\035', '\113', '\306',
+ '\073', '\347', '\042', '\170', '\075', '\247', '\042', '\210',
+ '\161', '\112', '\214', '\005', '\045', '\316', '\161', '\254',
+ '\017', '\031', '\031', '\104', '\236', '\111', '\056', '\344',
+ '\012', '\045', '\030', '\032', '\107', '\312', '\235', '\266',
+ '\272', '\005', '\071', '\126', '\311', '\261', '\140', '\202',
+ '\222', '\026', '\327', '\047', '\373', '\150', '\337', '\110',
+ '\306', '\270', '\221', '\204', '\174', '\375', '\341', '\066',
+ '\166', '\370', '\265', '\217', '\227', '\134', '\271', '\166',
+ '\364', '\052', '\107', '\324', '\315', '\145', '\110', '\166',
+ '\054', '\025', '\363', '\242', '\234', '\103', '\246', '\172',
+ '\264', '\115', '\330', '\163', '\206', '\123', '\146', '\221',
+ '\223', '\147', '\214', '\163', '\056', '\256', '\117', '\364',
+ '\250', '\153', '\014', '\206', '\217', '\331', '\342', '\070',
+ '\313', '\311', '\377', '\051', '\227', '\374', '\176', '\306',
+ '\126', '\065', '\310', '\266', '\310', '\366', '\350', '\310',
+ '\173', '\352', '\334', '\240', '\137', '\327', '\121', '\313',
+ '\323', '\333', '\046', '\164', '\235', '\342', '\034', '\375',
+ '\266', '\121', '\325', '\113', '\237', '\037', '\107', '\032',
+ '\344', '\334', '\235', '\157', '\317', '\304', '\317', '\263',
+ '\231', '\053', '\210', '\072', '\334', '\326', '\113', '\045',
+ '\016', '\252', '\255', '\244', '\255', '\345', '\132', '\303',
+ '\255', '\054', '\341', '\047', '\323', '\134', '\230', '\344',
+ '\122', '\207', '\224', '\021', '\343', '\323', '\070', '\270',
+ '\077', '\103', '\156', '\372', '\115', '\121', '\312', '\225',
+ '\155', '\224', '\355', '\053', '\360', '\220', '\051', '\327',
+ '\362', '\116', '\121', '\164', '\234', '\346', '\234', '\353',
+ '\101', '\352', '\136', '\214', '\241', '\347', '\154', '\242',
+ '\123', '\226', '\327', '\232', '\117', '\216', '\143', '\002',
+ '\061', '\056', '\115', '\367', '\121', '\217', '\324', '\107',
+ '\312', '\115', '\305', '\160', '\333', '\271', '\311', '\250',
+ '\372', '\170', '\075', '\033', '\136', '\365', '\250', '\345',
+ '\346', '\253', '\107', '\317', '\163', '\215', '\017', '\175',
+ '\144', '\160', '\363', '\055', '\057', '\177', '\313', '\165',
+ '\337', '\353', '\131', '\160', '\353', '\173', '\371', '\314',
+ '\027', '\071', '\367', '\163', '\205', '\162', '\217', '\264',
+ '\036', '\334', '\312', '\325', '\353', '\325', '\203', '\227',
+ '\217', '\346', '\232', '\027', '\124', '\031', '\061', '\166',
+ '\316', '\160', '\230', '\354', '\324', '\161', '\215', '\213',
+ '\214', '\333', '\063', '\127', '\256', '\235', '\353', '\101',
+ '\370', '\327', '\225', '\012', '\123', '\264', '\363', '\251',
+ '\071', '\332', '\126', '\340', '\202', '\227', '\037', '\350',
+ '\365', '\350', '\270', '\325', '\243', '\076', '\077', '\362',
+ '\131', '\120', '\317', '\275', '\236', '\355', '\134', '\062',
+ '\271', '\372', '\107', '\315', '\063', '\013', '\271', '\237',
+ '\005', '\175', '\114', '\323', '\355', '\354', '\146', '\153',
+ '\351', '\313', '\136', '\270', '\325', '\243', '\277', '\353',
+ '\250', '\210', '\361', '\147', '\174', '\216', '\266', '\211',
+ '\373', '\142', '\054', '\035', '\353', '\034', '\047', '\346',
+ '\150', '\233', '\133', '\137', '\346', '\263', '\265', '\054',
+ '\113', '\174', '\302', '\044', '\375', '\063', '\237', '\015',
+ '\304', '\265', '\351', '\016', '\122', '\146', '\026', '\206',
+ '\333', '\133', '\017', '\372', '\270', '\243', '\343', '\345',
+ '\157', '\152', '\236', '\221', '\370', '\201', '\033', '\162',
+ '\015', '\240', '\217', '\043', '\156', '\365', '\344', '\263',
+ '\265', '\356', '\157', '\176', '\346', '\037', '\165', '\015',
+ '\341', '\147', '\315', '\217', '\034', '\272', '\214', '\304',
+ '\257', '\325', '\365', '\251', '\337', '\172', '\146', '\150',
+ '\270', '\255', '\111', '\365', '\362', '\013', '\225', '\164',
+ '\056', '\337', '\321', '\145', '\362', '\331', '\300', '\155',
+ '\156', '\124', '\327', '\056', '\272', '\137', '\117', '\201',
+ '\373', '\232', '\122', '\107', '\267', '\235', '\354', '\113',
+ '\165', '\015', '\052', '\353', '\224', '\175', '\253', '\327',
+ '\343', '\365', '\134', '\253', '\350', '\365', '\250', '\143',
+ '\374', '\245', '\014', '\252', '\035', '\364', '\265', '\363',
+ '\150', '\202', '\364', '\151', '\061', '\117', '\311', '\071',
+ '\314', '\155', '\355', '\257', '\217', '\325', '\272', '\057',
+ '\271', '\315', '\013', '\172', '\075', '\352', '\263', '\344',
+ '\345', '\327', '\045', '\012', '\262', '\115', '\372', '\132',
+ '\306', '\117', '\075', '\162', '\176', '\361', '\252', '\107',
+ '\177', '\077', '\235', '\212', '\013', '\175', '\307', '\117',
+ '\075', '\372', '\032', '\113', '\257', '\117', '\265', '\233',
+ '\134', '\133', '\346', '\033', '\173', '\105', '\220', '\317',
+ '\310', '\170', '\370', '\233', '\177', '\104', '\220', '\276',
+ '\120', '\014', '\367', '\071', '\110', '\237', '\207', '\324',
+ '\266', '\171', '\315', '\101', '\172', '\160', '\153', '\217',
+ '\237', '\266', '\311', '\040', '\366', '\025', '\365', '\161',
+ '\047', '\337', '\063', '\062', '\022', '\273', '\311', '\340',
+ '\066', '\107', '\344', '\153', '\133', '\276', '\271', '\310',
+ '\055', '\350', '\076', '\252', '\256', '\265', '\275', '\326',
+ '\262', '\122', '\237', '\174', '\363', '\234', '\233', '\076',
+ '\302', '\376', '\105', '\171', '\364', '\361', '\362', '\151',
+ '\077', '\373', '\306', '\272', '\315', '\274', '\306', '\003',
+ '\057', '\031', '\165', '\314', '\367', '\043', '\223', '\157',
+ '\376', '\321', '\145', '\324', '\371', '\304', '\317', '\370',
+ '\352', '\246', '\113', '\276', '\367', '\040', '\371', '\256',
+ '\230', '\353', '\375', '\264', '\014', '\027', '\372', '\376',
+ '\130', '\227', '\153', '\145', '\232', '\334', '\110', '\367',
+ '\004', '\275', '\312', '\164', '\253', '\133', '\015', '\162',
+ '\117', '\310', '\153', '\357', '\347', '\122', '\005', '\365',
+ '\335', '\310', '\357', '\172', '\107', '\216', '\023', '\242',
+ '\175', '\162', '\377', '\111', '\256', '\333', '\274', '\374',
+ '\346', '\142', '\366', '\023', '\145', '\137', '\113', '\337',
+ '\224', '\317', '\222', '\127', '\136', '\325', '\217', '\325',
+ '\275', '\316', '\134', '\372', '\350', '\372', '\346', '\262',
+ '\201', '\252', '\213', '\376', '\231', '\116', '\011', '\334',
+ '\237', '\323', '\321', '\354', '\075', '\112', '\075', '\205',
+ '\155', '\305', '\332', '\177', '\072', '\206', '\336', '\001',
+ '\162', '\371', '\277', '\276', '\046', '\220', '\163', '\256',
+ '\237', '\175', '\253', '\122', '\247', '\235', '\262', '\137',
+ '\047', '\301', '\375', '\363', '\057', '\267', '\040', '\327',
+ '\200', '\371', '\366', '\000', '\364', '\266', '\346', '\273',
+ '\057', '\164', '\230', '\011', '\133', '\367', '\253', '\225',
+ '\164', '\276', '\061', '\140', '\244', '\341', '\267', '\361',
+ '\371', '\234', '\334', '\247', '\225', '\143', '\223', '\237',
+ '\317', '\314', '\244', '\214', '\134', '\357', '\352', '\143',
+ '\205', '\133', '\220', '\343', '\337', '\305', '\004', '\267',
+ '\271', '\104', '\330', '\136', '\237', '\357', '\256', '\161',
+ '\256', '\253', '\210', '\161', '\272', '\024', '\336', '\237',
+ '\237', '\352', '\341', '\122', '\175', '\126', '\240', '\352',
+ '\055', '\354', '\065', '\026', '\303', '\307', '\034', '\077',
+ '\301', '\153', '\217', '\316', '\217', '\117', '\251', '\317',
+ '\214', '\372', '\054', '\351', '\301', '\255', '\155', '\342',
+ '\271', '\051', '\163', '\344', '\146', '\343', '\302', '\347',
+ '\310', '\115', '\246', '\310', '\311', '\057', '\337', '\275',
+ '\364', '\317', '\166', '\165', '\337', '\021', '\351', '\053',
+ '\363', '\324', '\003', '\134', '\070', '\016', '\312', '\171',
+ '\324', '\153', '\055', '\066', '\106', '\223', '\121', '\337',
+ '\057', '\325', '\075', '\033', '\065', '\024', '\215', '\102',
+ '\106', '\076', '\243', '\043', '\221', '\221', '\375', '\060',
+ '\022', '\231', '\111', '\243', '\220', '\221', '\371', '\364',
+ '\365', '\115', '\056', '\031', '\021', '\256', '\302', '\360',
+ '\317', '\337', '\305', '\134', '\250', '\376', '\315', '\303',
+ '\034', '\027', '\031', '\077', '\173', '\203', '\352', '\376',
+ '\255', '\332', '\077', '\352', '\336', '\235', '\272', '\106',
+ '\326', '\375', '\273', '\150', '\024', '\062', '\152', '\377',
+ '\370', '\225', '\121', '\155', '\355', '\127', '\106', '\325',
+ '\307', '\153', '\277', '\117', '\367', '\321', '\242', '\121',
+ '\310', '\250', '\372', '\370', '\225', '\121', '\365', '\361',
+ '\053', '\003', '\134', '\270', '\167', '\073', '\023', '\271',
+ '\367', '\156', '\125', '\277', '\226', '\276', '\045', '\367',
+ '\373', '\274', '\366', '\371', '\164', '\273', '\371', '\331',
+ '\257', '\322', '\355', '\346', '\107', '\106', '\267', '\233',
+ '\037', '\031', '\125', '\037', '\277', '\062', '\272', '\255',
+ '\375', '\310', '\350', '\101', '\175', '\057', '\361', '\172',
+ '\047', '\051', '\161', '\312', '\221', '\173', '\250', '\352',
+ '\173', '\217', '\334', '\147', '\025', '\367', '\325', '\171',
+ '\121', '\265', '\265', '\133', '\273', '\362', '\331', '\332',
+ '\257', '\214', '\152', '\153', '\277', '\062', '\252', '\335',
+ '\056', '\246', '\155', '\156', '\373', '\203', '\172', '\160',
+ '\333', '\163', '\312', '\367', '\156', '\056', '\336', '\223',
+ '\345', '\236', '\207', '\034', '\007', '\325', '\275', '\136',
+ '\267', '\367', '\005', '\335', '\267', '\375', '\354', '\213',
+ '\351', '\276', '\355', '\107', '\106', '\367', '\155', '\077',
+ '\062', '\272', '\157', '\373', '\221', '\321', '\175', '\073',
+ '\237', '\214', '\154', '\127', '\361', '\010', '\144', '\364',
+ '\040', '\377', '\136', '\101', '\034', '\345', '\173', '\135',
+ '\276', '\367', '\026', '\257', '\275', '\101', '\165', '\376',
+ '\001', '\334', '\307', '\236', '\174', '\373', '\174', '\156',
+ '\143', '\217', '\337', '\275', '\301', '\221', '\310', '\270',
+ '\215', '\043', '\371', '\144', '\124', '\175', '\374', '\356',
+ '\363', '\025', '\215', '\102', '\106', '\325', '\307', '\257',
+ '\214', '\252', '\217', '\037', '\031', '\371', '\034', '\313',
+ '\375', '\051', '\277', '\373', '\157', '\252', '\137', '\373',
+ '\335', '\347', '\313', '\067', '\007', '\371', '\365', '\203',
+ '\174', '\062', '\371', '\346', '\240', '\174', '\372', '\370',
+ '\225', '\311', '\067', '\007', '\171', '\315', '\077', '\156',
+ '\357', '\212', '\136', '\143', '\250', '\032', '\324', '\271',
+ '\110', '\235', '\203', '\364', '\371', '\107', '\204', '\134',
+ '\163', '\220', '\237', '\061', '\321', '\257', '\114', '\256',
+ '\071', '\310', '\317', '\370', '\166', '\261', '\155', '\313',
+ '\267', '\067', '\350', '\265', '\207', '\077', '\035', '\103',
+ '\237', '\365', '\253', '\266', '\363', '\152', '\233', '\133',
+ '\075', '\316', '\167', '\250', '\372', '\372', '\167', '\366',
+ '\060', '\332', '\261', '\331', '\376', '\362', '\203', '\163',
+ '\252', '\106', '\133', '\031', '\075', '\316', '\324', '\300',
+ '\026', '\345', '\306', '\266', '\376', '\047', '\067', '\061',
+ '\352', '\353', '\355', '\355', '\267', '\043', '\236', '\312',
+ '\157', '\117', '\154', '\144', '\064', '\320', '\315', '\250',
+ '\117', '\134', '\353', '\335', '\302', '\150', '\213', '\225',
+ '\245', '\127', '\210', '\131', '\131', '\304', '\015', '\212',
+ '\155', '\263', '\253', '\264', '\112', '\266', '\242', '\176',
+ '\121', '\174', '\277', '\135', '\121', '\357', '\166', '\121',
+ '\100', '\017', '\057', '\061', '\037', '\233', '\261', '\275',
+ '\177', '\347', '\143', '\172', '\063', '\170', '\152', '\335',
+ '\175', '\214', '\167', '\007', '\267', '\132', '\221', '\270',
+ '\261', '\311', '\322', '\210', '\247', '\275', '\342', '\264',
+ '\157', '\223', '\114', '\135', '\240', '\233', '\217', '\210',
+ '\262', '\073', '\266', '\132', '\221', '\274', '\326', '\277',
+ '\171', '\364', '\105', '\371', '\316', '\074', '\262', '\346',
+ '\146', '\065', '\037', '\112', '\011', '\133', '\365', '\154',
+ '\245', '\021', '\007', '\273', '\244', '\141', '\355', '\326',
+ '\273', '\245', '\172', '\245', '\354', '\100', '\117', '\017',
+ '\243', '\336', '\141', '\315', '\355', '\327', '\242', '\336',
+ '\154', '\224', '\275', '\066', '\340', '\226', '\257', '\147',
+ '\130', '\276', '\301', '\255', '\126', '\067', '\132', '\051',
+ '\273', '\175', '\331', '\256', '\025', '\247', '\331', '\136',
+ '\335', '\341', '\364', '\376', '\066', '\333', '\365', '\006',
+ '\055', '\215', '\204', '\012', '\203', '\326', '\215', '\315',
+ '\062', '\113', '\237', '\350', '\337', '\276', '\115', '\331',
+ '\033', '\135', '\212', '\237', '\156', '\353', '\037', '\174',
+ '\334', '\212', '\262', '\352', '\367', '\016', '\271', '\024',
+ '\243', '\236', '\136', '\073', '\213', '\132', '\336', '\140',
+ '\317', '\260', '\150', '\147', '\317', '\205', '\327', '\334',
+ '\262', '\354', '\354', '\165', '\273', '\053', '\332', '\354',
+ '\104', '\331', '\123', '\177', '\205', '\132', '\316', '\157',
+ '\131', '\050', '\117', '\275', '\071', '\243', '\301', '\341',
+ '\035', '\340', '\356', '\211', '\166', '\244', '\366', '\264',
+ '\217', '\342', '\255', '\307', '\157', '\207', '\247', '\167',
+ '\132', '\217', '\263', '\125', '\245', '\374', '\016', '\025',
+ '\160', '\136', '\031', '\317', '\306', '\140', '\054', '\107',
+ '\302', '\161', '\234', '\261', '\047', '\160', '\124', '\234',
+ '\310', '\321', '\352', '\012', '\216', '\302', '\223', '\071',
+ '\042', '\115', '\345', '\350', '\064', '\215', '\243', '\361',
+ '\164', '\316', '\146', '\063', '\070', '\132', '\315', '\104',
+ '\031', '\307', '\255', '\253', '\160', '\065', '\146', '\143',
+ '\016', '\127', '\203', '\345', '\250', '\300', '\265', '\270',
+ '\016', '\327', '\143', '\056', '\156', '\300', '\215', '\270',
+ '\011', '\363', '\160', '\063', '\156', '\301', '\255', '\230',
+ '\217', '\112', '\334', '\206', '\333', '\121', '\205', '\152',
+ '\054', '\300', '\035', '\130', '\210', '\105', '\130', '\214',
+ '\073', '\261', '\004', '\167', '\341', '\156', '\174', '\032',
+ '\113', '\161', '\017', '\356', '\305', '\175', '\130', '\206',
+ '\000', '\356', '\107', '\015', '\152', '\021', '\304', '\162',
+ '\254', '\300', '\112', '\324', '\341', '\063', '\370', '\054',
+ '\352', '\261', '\012', '\015', '\150', '\304', '\152', '\074',
+ '\040', '\276', '\006', '\214', '\146', '\264', '\340', '\163',
+ '\170', '\020', '\153', '\261', '\016', '\017', '\341', '\363',
+ '\370', '\002', '\176', '\007', '\277', '\213', '\126', '\074',
+ '\214', '\020', '\326', '\043', '\214', '\010', '\014', '\264',
+ '\241', '\035', '\035', '\060', '\361', '\105', '\154', '\100',
+ '\024', '\061', '\304', '\221', '\100', '\047', '\036', '\101',
+ '\022', '\051', '\244', '\221', '\301', '\106', '\074', '\212',
+ '\056', '\164', '\343', '\061', '\074', '\216', '\115', '\170',
+ '\002', '\233', '\161', '\376', '\242', '\303', '\026', '\364',
+ '\140', '\053', '\172', '\261', '\015', '\333', '\321', '\207',
+ '\176', '\354', '\300', '\000', '\166', '\142', '\020', '\117',
+ '\142', '\027', '\276', '\204', '\337', '\303', '\156', '\354',
+ '\301', '\227', '\361', '\373', '\330', '\213', '\247', '\360',
+ '\025', '\074', '\215', '\257', '\142', '\037', '\276', '\206',
+ '\147', '\360', '\165', '\354', '\307', '\067', '\360', '\115',
+ '\174', '\013', '\007', '\160', '\020', '\177', '\200', '\157',
+ '\343', '\020', '\236', '\305', '\167', '\360', '\207', '\070',
+ '\214', '\347', '\360', '\107', '\370', '\143', '\034', '\301',
+ '\363', '\370', '\023', '\274', '\200', '\243', '\170', '\021',
+ '\177', '\212', '\227', '\160', '\014', '\177', '\206', '\077',
+ '\307', '\137', '\340', '\145', '\274', '\202', '\357', '\342',
+ '\173', '\170', '\025', '\337', '\307', '\153', '\370', '\113',
+ '\274', '\216', '\037', '\340', '\257', '\360', '\006', '\336',
+ '\304', '\017', '\361', '\043', '\374', '\030', '\307', '\361',
+ '\026', '\376', '\032', '\177', '\203', '\023', '\370', '\133',
+ '\274', '\215', '\237', '\340', '\044', '\376', '\016', '\077',
+ '\305', '\317', '\160', '\012', '\357', '\340', '\357', '\361',
+ '\017', '\070', '\215', '\177', '\304', '\273', '\370', '\047',
+ '\234', '\301', '\077', '\343', '\347', '\030', '\372', '\116',
+ '\335', '\331', '\202', '\313', '\134', '\346', '\062', '\377',
+ '\027', '\250', '\337', '\153', '\225', '\337', '\025', '\023',
+ '\173', '\271', '\327', '\301', '\376', '\056', '\233', '\370',
+ '\021', '\210', '\273', '\111', '\000', '\366', '\217', '\071',
+ '\064', '\021', '\361', '\013', '\020', '\021', '\022', '\043',
+ '\033', '\311', '\026', '\062', '\100', '\366', '\300', '\376',
+ '\155', '\213', '\203', '\260', '\177', '\364', '\341', '\105',
+ '\362', '\135', '\362', '\006', '\071', '\101', '\336', '\041',
+ '\342', '\271', '\077', '\107', '\176', '\105', '\076', '\026',
+ '\163', '\000', '\333', '\060', '\211', '\314', '\042', '\345',
+ '\344', '\106', '\162', '\073', '\271', '\233', '\004', '\110',
+ '\035', '\151', '\042', '\255', '\304', '\044', '\351', '\002',
+ '\373', '\367', '\037', '\172', '\013', '\354', '\237', '\177',
+ '\330', '\115', '\236', '\046', '\373', '\311', '\101', '\362',
+ '\054', '\171', '\216', '\274', '\100', '\216', '\221', '\127',
+ '\310', '\367', '\311', '\033', '\344', '\055', '\362', '\166',
+ '\201', '\375', '\375', '\334', '\237', '\223', '\177', '\045',
+ '\377', '\106', '\176', '\111', '\376', '\213', '\374', '\067',
+ '\071', '\117', '\012', '\150', '\224', '\261', '\144', '\034',
+ '\231', '\100', '\046', '\222', '\053', '\310', '\144', '\062',
+ '\225', '\114', '\043', '\323', '\311', '\014', '\062', '\223',
+ '\314', '\042', '\127', '\223', '\071', '\244', '\234', '\134',
+ '\113', '\256', '\047', '\067', '\220', '\233', '\310', '\315',
+ '\344', '\126', '\122', '\111', '\156', '\047', '\325', '\344',
+ '\036', '\262', '\202', '\064', '\223', '\207', '\311', '\006',
+ '\362', '\010', '\111', '\221', '\014', '\171', '\224', '\164',
+ '\223', '\307', '\311', '\023', '\144', '\013', '\331', '\112',
+ '\266', '\221', '\076', '\262', '\203', '\354', '\044', '\117',
+ '\222', '\057', '\221', '\335', '\344', '\313', '\144', '\057',
+ '\371', '\012', '\371', '\052', '\371', '\032', '\371', '\072',
+ '\371', '\006', '\371', '\026', '\071', '\110', '\276', '\115',
+ '\236', '\045', '\057', '\220', '\227', '\310', '\153', '\344',
+ '\055', '\362', '\023', '\362', '\056', '\171', '\217', '\234',
+ '\043', '\277', '\044', '\277', '\042', '\347', '\205', '\015',
+ '\304', '\367', '\224', '\311', '\125', '\344', '\106', '\262',
+ '\220', '\334', '\107', '\226', '\223', '\007', '\310', '\132',
+ '\322', '\112', '\114', '\222', '\041', '\333', '\310', '\116',
+ '\262', '\213', '\074', '\115', '\236', '\045', '\317', '\223',
+ '\127', '\310', '\217', '\310', '\073', '\344', '\054', '\071',
+ '\107', '\176', '\115', '\306', '\362', '\145', '\150', '\022',
+ '\231', '\106', '\346', '\220', '\271', '\344', '\066', '\262',
+ '\220', '\334', '\111', '\226', '\221', '\025', '\244', '\201',
+ '\074', '\124', '\150', '\377', '\006', '\312', '\006', '\222',
+ '\044', '\233', '\311', '\000', '\331', '\105', '\366', '\222',
+ '\147', '\310', '\101', '\362', '\074', '\071', '\106', '\136',
+ '\043', '\077', '\046', '\157', '\223', '\167', '\310', '\031',
+ '\162', '\216', '\374', '\007', '\371', '\117', '\162', '\136',
+ '\324', '\075', '\216', '\165', '\213', '\357', '\130', '\223',
+ '\271', '\344', '\126', '\262', '\210', '\174', '\232', '\334',
+ '\113', '\126', '\220', '\006', '\322', '\102', '\102', '\144',
+ '\003', '\111', '\222', '\156', '\322', '\107', '\166', '\223',
+ '\275', '\344', '\031', '\162', '\220', '\034', '\046', '\307',
+ '\310', '\367', '\310', '\017', '\311', '\011', '\362', '\063',
+ '\362', '\056', '\371', '\027', '\362', '\013', '\362', '\033',
+ '\362', '\077', '\244', '\160', '\074', '\337', '\277', '\110',
+ '\304', '\150', '\013', '\145', '\242', '\351', '\160', '\107',
+ '\050', '\211', '\114', '\334', '\134', '\260', '\250', '\146',
+ '\061', '\122', '\035', '\241', '\210', '\141', '\235', '\055',
+ '\254', '\272', '\313', '\071', '\326', '\070', '\307', '\132',
+ '\347', '\030', '\240', '\144', '\173', '\322', '\060', '\320',
+ '\031', '\315', '\244', '\142', '\146', '\074', '\223', '\262',
+ '\157', '\054', '\130', '\350', '\144', '\270', '\037', '\115',
+ '\313', '\253', '\026', '\126', '\061', '\210', '\304', '\035',
+ '\062', '\121', '\055', '\023', '\013', '\144', '\142', '\221',
+ '\225', '\020', '\102', '\167', '\334', '\037', '\160', '\216',
+ '\102', '\330', '\312', '\051', '\157', '\324', '\070', '\307',
+ '\132', '\041', '\261', '\104', '\212', '\336', '\045', '\023',
+ '\167', '\312', '\304', '\142', '\047', '\121', '\155', '\327',
+ '\023', '\065', '\122', '\051', '\343', '\221', '\114', '\050',
+ '\012', '\266', '\065', '\224', '\066', '\222', '\366', '\111',
+ '\247', '\211', '\170', '\042', '\155', '\247', '\123', '\274',
+ '\032', '\065', '\343', '\355', '\350', '\064', '\222', '\146',
+ '\042', '\022', '\066', '\342', '\042', '\133', '\004', '\251',
+ '\316', '\120', '\330', '\200', '\321', '\025', '\216', '\206',
+ '\142', '\170', '\044', '\303', '\354', '\221', '\365', '\121',
+ '\304', '\063', '\261', '\365', '\106', '\062', '\145', '\266',
+ '\307', '\021', '\111', '\104', '\243', '\064', '\032', '\305',
+ '\204', '\014', '\102', '\061', '\246', '\122', '\241', '\170',
+ '\304', '\316', '\234', '\142', '\221', '\121', '\132', '\047',
+ '\224', '\064', '\342', '\121', '\243', '\055', '\155', '\247',
+ '\222', '\146', '\173', '\007', '\263', '\212', '\072', '\315',
+ '\324', '\006', '\313', '\166', '\010', '\047', '\142', '\261',
+ '\020', '\072', '\272', '\073', '\073', '\214', '\270', '\323',
+ '\010', '\244', '\242', '\241', '\124', '\007', '\036', '\063',
+ '\222', '\011', '\044', '\342', '\006', '\322', '\217', '\046',
+ '\220', '\356', '\020', '\326', '\156', '\113', '\144', '\222',
+ '\150', '\063', '\067', '\032', '\110', '\231', '\135', '\110',
+ '\031', '\033', '\051', '\143', '\130', '\205', '\306', '\115',
+ '\146', '\014', '\047', '\242', '\211', '\070', '\057', '\307',
+ '\114', '\073', '\045', '\364', '\307', '\060', '\003', '\260',
+ '\165', '\106', '\052', '\155', '\362', '\136', '\050', '\075',
+ '\252', '\205', '\350', '\372', '\144', '\050', '\274', '\301',
+ '\110', '\133', '\072', '\255', '\147', '\322', '\156', '\252',
+ '\163', '\125', '\352', '\027', '\066', '\315', '\260', '\231',
+ '\014', '\147', '\142', '\354', '\266', '\010', '\315', '\022',
+ '\116', '\044', '\015', '\266', '\040', '\304', '\166', '\217',
+ '\146', '\361', '\052', '\112', '\067', '\234', '\032', '\223',
+ '\366', '\231', '\122', '\123', '\332', '\214', '\322', '\135',
+ '\325', '\376', '\212', '\044', '\036', '\215', '\303', '\352',
+ '\225', '\154', '\357', '\206', '\063', '\111', '\332', '\077',
+ '\334', '\215', '\156', '\132', '\154', '\175', '\062', '\261',
+ '\301', '\210', '\213', '\262', '\122', '\106', '\330', '\062',
+ '\106', '\304', '\144', '\247', '\247', '\114', '\321', '\033',
+ '\235', '\335', '\166', '\331', '\211', '\144', '\244', '\215',
+ '\206', '\264', '\354', '\332', '\236', '\061', '\243', '\121',
+ '\043', '\226', '\260', '\325', '\216', '\046', '\332', '\315',
+ '\160', '\050', '\112', '\027', '\222', '\335', '\226', '\064',
+ '\332', '\315', '\224', '\355', '\067', '\261', '\120', '\070',
+ '\051', '\012', '\324', '\237', '\016', '\366', '\141', '\052',
+ '\143', '\165', '\157', '\322', '\356', '\313', '\354', '\131',
+ '\050', '\234', '\111', '\033', '\210', '\145', '\204', '\213',
+ '\204', '\150', '\244', '\316', '\016', '\335', '\027', '\303',
+ '\106', '\204', '\365', '\207', '\204', '\057', '\144', '\245',
+ '\330', '\274', '\030', '\325', '\317', '\104', '\207', '\265',
+ '\317', '\151', '\172', '\134', '\364', '\171', '\122', '\164',
+ '\067', '\223', '\035', '\241', '\150', '\233', '\135', '\245',
+ '\163', '\061', '\225', '\165', '\002', '\313', '\120', '\001',
+ '\273', '\143', '\002', '\166', '\073', '\002', '\166', '\307',
+ '\265', '\105', '\215', '\056', '\004', '\154', '\323', '\006',
+ '\262', '\326', '\011', '\044', '\205', '\055', '\003', '\101',
+ '\324', '\310', '\046', '\005', '\155', '\341', '\240', '\055',
+ '\034', '\124', '\204', '\203', '\131', '\251', '\072', '\073',
+ '\117', '\235', '\235', '\247', '\116', '\311', '\123', '\227',
+ '\315', '\023', '\114', '\167', '\240', '\301', '\256', '\256',
+ '\321', '\316', '\336', '\150', '\147', '\157', '\124', '\262',
+ '\067', '\072', '\031', '\262', '\122', '\061', '\016', '\135',
+ '\146', '\147', '\264', '\033', '\215', '\266', '\033', '\266',
+ '\330', '\242', '\055', '\266', '\150', '\213', '\042', '\332',
+ '\222', '\225', '\131', '\147', '\337', '\154', '\356', '\110',
+ '\044', '\343', '\150', '\067', '\222', '\061', '\076', '\263',
+ '\353', '\243', '\051', '\204', '\034', '\377', '\264', '\157',
+ '\207', '\024', '\331', '\220', '\135', '\155', '\050', '\133',
+ '\104', '\310', '\062', '\103', '\210', '\317', '\233', '\064',
+ '\203', '\141', '\013', '\033', '\266', '\260', '\241', '\010',
+ '\033', '\131', '\051', '\323', '\316', '\143', '\332', '\171',
+ '\114', '\045', '\217', '\231', '\315', '\143', '\320', '\014',
+ '\161', '\273', '\272', '\204', '\235', '\075', '\141', '\147',
+ '\117', '\050', '\331', '\023', '\116', '\206', '\254', '\124',
+ '\304', '\334', '\150', '\212', '\013', '\266', '\021', '\062',
+ '\266', '\140', '\306', '\026', '\314', '\050', '\202', '\231',
+ '\254', '\104', '\267', '\175', '\063', '\155', '\031', '\241',
+ '\073', '\173', '\371', '\322', '\375', '\156', '\322', '\377',
+ '\002', '\174', '\155', '\142', '\140', '\200', '\114', '\000',
+ '\000',
+
+};
+
+static char name_6x13[] = "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1";
+static char name_cursor[] = "cursor";
+
+const BuiltinFileRec builtin_files[] = {
+ { "6x13.builtin", sizeof file_6x13, file_6x13, },
+ { "cursor.builtin", sizeof file_cursor, file_cursor, }
+};
+
+const int builtin_files_count = sizeof (builtin_files) / sizeof (builtin_files[0]);
+
+const BuiltinDirRec builtin_dir[] = {
+ { "6x13.builtin", name_6x13, },
+ { "cursor.builtin", name_cursor, }
+};
+
+const int builtin_dir_count = sizeof (builtin_dir) / sizeof (builtin_dir[0]);
+
+static char alias_fixed[] = "fixed";
+static char alias_6x13[] = "6x13";
+static char alias_6x13_100[] = "-misc-fixed-medium-r-semicondensed--13-100-100-100-c-60-iso8859-1";
+
+const BuiltinAliasRec builtin_alias[] = {
+ { alias_fixed, name_6x13, },
+ { alias_6x13, name_6x13, },
+ { alias_6x13_100, name_6x13, }
+};
+
+const int builtin_alias_count = sizeof (builtin_alias) / sizeof (builtin_alias[0]);
diff --git a/libXfont/src/builtins/fpe.c b/libXfont/src/builtins/fpe.c index 403dbb7db..5e8f05f5f 100644 --- a/libXfont/src/builtins/fpe.c +++ b/libXfont/src/builtins/fpe.c @@ -1,91 +1,91 @@ -/* - * Copyright 1999 SuSE, Inc. - * - * 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, and that the name of SuSE not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. SuSE makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE - * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Keith Packard, SuSE, Inc. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fntfilst.h> -#include "builtin.h" - -static int font_file_type; - -static const char builtin_fonts[] = "built-ins"; - -static int -BuiltinNameCheck (char *name) -{ - return (strcmp (name, builtin_fonts) == 0); -} - -static int -BuiltinInitFPE (FontPathElementPtr fpe) -{ - int status; - FontDirectoryPtr dir; - - status = BuiltinReadDirectory (fpe->name, &dir); - - if (status == Successful) - fpe->private = (pointer) dir; - return status; -} - -/* ARGSUSED */ -static int -BuiltinResetFPE (FontPathElementPtr fpe) -{ - FontDirectoryPtr dir; - - dir = (FontDirectoryPtr) fpe->private; - /* builtins can't change! */ - return Successful; -} - -static int -BuiltinFreeFPE (FontPathElementPtr fpe) -{ - FontFileFreeDir ((FontDirectoryPtr) fpe->private); - return Successful; -} - -void -BuiltinRegisterFpeFunctions(void) -{ - BuiltinRegisterFontFileFunctions (); - - font_file_type = RegisterFPEFunctions(BuiltinNameCheck, - BuiltinInitFPE, - BuiltinFreeFPE, - BuiltinResetFPE, - FontFileOpenFont, - FontFileCloseFont, - FontFileListFonts, - FontFileStartListFontsWithInfo, - FontFileListNextFontWithInfo, - (WakeupFpeFunc) 0, - (ClientDiedFunc) 0, - (LoadGlyphsFunc) 0, - (StartLaFunc) 0, - (NextLaFunc) 0, - (SetPathFunc) 0); -} +/*
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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, and that the name of SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fntfilst.h>
+#include "builtin.h"
+
+static int font_file_type;
+
+static const char builtin_fonts[] = "built-ins";
+
+static int
+BuiltinNameCheck (char *name)
+{
+ return (strcmp (name, builtin_fonts) == 0);
+}
+
+static int
+BuiltinInitFPE (FontPathElementPtr fpe)
+{
+ int status;
+ FontDirectoryPtr dir;
+
+ status = BuiltinReadDirectory (fpe->name, &dir);
+
+ if (status == Successful)
+ fpe->private = (pointer) dir;
+ return status;
+}
+
+/* ARGSUSED */
+static int
+BuiltinResetFPE (FontPathElementPtr fpe)
+{
+ FontDirectoryPtr dir;
+
+ dir = (FontDirectoryPtr) fpe->private;
+ /* builtins can't change! */
+ return Successful;
+}
+
+static int
+BuiltinFreeFPE (FontPathElementPtr fpe)
+{
+ FontFileFreeDir ((FontDirectoryPtr) fpe->private);
+ return Successful;
+}
+
+void
+BuiltinRegisterFpeFunctions(void)
+{
+ BuiltinRegisterFontFileFunctions ();
+
+ font_file_type = RegisterFPEFunctions(BuiltinNameCheck,
+ BuiltinInitFPE,
+ BuiltinFreeFPE,
+ BuiltinResetFPE,
+ FontFileOpenFont,
+ FontFileCloseFont,
+ FontFileListFonts,
+ FontFileStartListFontsWithInfo,
+ FontFileListNextFontWithInfo,
+ (WakeupFpeFunc) 0,
+ (ClientDiedFunc) 0,
+ (LoadGlyphsFunc) 0,
+ (StartLaFunc) 0,
+ (NextLaFunc) 0,
+ (SetPathFunc) 0);
+}
diff --git a/libXfont/src/builtins/makefile b/libXfont/src/builtins/makefile new file mode 100644 index 000000000..dac4fcf8c --- /dev/null +++ b/libXfont/src/builtins/makefile @@ -0,0 +1,10 @@ +LIBRARY = libbuiltins + +CSRCS = dir.c \ + file.c \ + fonts.c \ + fpe.c \ + render.c + +INCLUDES := ../.. $(INCLUDES) + diff --git a/libXfont/src/builtins/render.c b/libXfont/src/builtins/render.c index 4d1048394..19cfd4f75 100644 --- a/libXfont/src/builtins/render.c +++ b/libXfont/src/builtins/render.c @@ -1,132 +1,132 @@ -/* - * Copyright 1999 SuSE, Inc. - * - * 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, and that the name of SuSE not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. SuSE makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE - * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Keith Packard, SuSE, Inc. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fntfilst.h> -#include <X11/fonts/fontutil.h> -#include <X11/fonts/pcf.h> -#include "builtin.h" - -static int -BuiltinOpenBitmap (FontPathElementPtr fpe, FontPtr *ppFont, int flags, - FontEntryPtr entry, char *fileName, fsBitmapFormat format, - fsBitmapFormatMask fmask, FontPtr unused) -{ - FontFilePtr file; - FontPtr pFont; - int ret; - int bit, - byte, - glyph, - scan, - image; - - file = BuiltinFileOpen (fileName); - if (!file) - return BadFontName; - pFont = malloc(sizeof(FontRec)); - if (!pFont) { - BuiltinFileClose (file, 0); - return AllocError; - } - /* set up default values */ - FontDefaultFormat(&bit, &byte, &glyph, &scan); - /* get any changes made from above */ - ret = CheckFSFormat(format, fmask, &bit, &byte, &scan, &glyph, &image); - - /* Fill in font record. Data format filled in by reader. */ - pFont->refcnt = 0; - pFont->maxPrivate = -1; - pFont->devPrivates = (pointer *) 0; - - ret = pcfReadFont (pFont, file, bit, byte, glyph, scan); - - BuiltinFileClose (file, 0); - if (ret != Successful) - free(pFont); - else - *ppFont = pFont; - return ret; -} - -static int -BuiltinGetInfoBitmap (FontPathElementPtr fpe, FontInfoPtr pFontInfo, - FontEntryPtr entry, char *fileName) -{ - FontFilePtr file; - int ret; - - file = BuiltinFileOpen (fileName); - if (!file) - return BadFontName; - ret = pcfReadFontInfo (pFontInfo, file); - BuiltinFileClose (file, 0); - return ret; -} - -static int -BuiltinOpenScalable (FontPathElementPtr fpe, - FontPtr *pFont, - int flags, - FontEntryPtr entry, - char *fileName, - FontScalablePtr vals, - fsBitmapFormat format, - fsBitmapFormatMask fmask, - FontPtr non_cachable_font) /* We don't do licensing */ -{ - return BadFontName; -} - -static int -BuiltinGetInfoScalable (FontPathElementPtr fpe, - FontInfoPtr pFontInfo, - FontEntryPtr entry, - FontNamePtr fontName, - char *fileName, - FontScalablePtr vals) -{ - return BadFontName; -} - -static FontRendererRec renderers[] = { - { ".builtin", 8, - BuiltinOpenBitmap, - BuiltinOpenScalable, - BuiltinGetInfoBitmap, - BuiltinGetInfoScalable, - 0 } -}; - -#define numRenderers (sizeof renderers / sizeof renderers[0]) - -void -BuiltinRegisterFontFileFunctions(void) -{ - int i; - for (i = 0; i < numRenderers; i++) - FontFileRegisterRenderer ((FontRendererRec *) &renderers[i]); -} - +/*
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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, and that the name of SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fntfilst.h>
+#include <X11/fonts/fontutil.h>
+#include <X11/fonts/pcf.h>
+#include "builtin.h"
+
+static int
+BuiltinOpenBitmap (FontPathElementPtr fpe, FontPtr *ppFont, int flags,
+ FontEntryPtr entry, char *fileName, fsBitmapFormat format,
+ fsBitmapFormatMask fmask, FontPtr unused)
+{
+ FontFilePtr file;
+ FontPtr pFont;
+ int ret;
+ int bit,
+ byte,
+ glyph,
+ scan,
+ image;
+
+ file = BuiltinFileOpen (fileName);
+ if (!file)
+ return BadFontName;
+ pFont = malloc(sizeof(FontRec));
+ if (!pFont) {
+ BuiltinFileClose (file, 0);
+ return AllocError;
+ }
+ /* set up default values */
+ FontDefaultFormat(&bit, &byte, &glyph, &scan);
+ /* get any changes made from above */
+ ret = CheckFSFormat(format, fmask, &bit, &byte, &scan, &glyph, &image);
+
+ /* Fill in font record. Data format filled in by reader. */
+ pFont->refcnt = 0;
+ pFont->maxPrivate = -1;
+ pFont->devPrivates = (pointer *) 0;
+
+ ret = pcfReadFont (pFont, file, bit, byte, glyph, scan);
+
+ BuiltinFileClose (file, 0);
+ if (ret != Successful)
+ free(pFont);
+ else
+ *ppFont = pFont;
+ return ret;
+}
+
+static int
+BuiltinGetInfoBitmap (FontPathElementPtr fpe, FontInfoPtr pFontInfo,
+ FontEntryPtr entry, char *fileName)
+{
+ FontFilePtr file;
+ int ret;
+
+ file = BuiltinFileOpen (fileName);
+ if (!file)
+ return BadFontName;
+ ret = pcfReadFontInfo (pFontInfo, file);
+ BuiltinFileClose (file, 0);
+ return ret;
+}
+
+static int
+BuiltinOpenScalable (FontPathElementPtr fpe,
+ FontPtr *pFont,
+ int flags,
+ FontEntryPtr entry,
+ char *fileName,
+ FontScalablePtr vals,
+ fsBitmapFormat format,
+ fsBitmapFormatMask fmask,
+ FontPtr non_cachable_font) /* We don't do licensing */
+{
+ return BadFontName;
+}
+
+static int
+BuiltinGetInfoScalable (FontPathElementPtr fpe,
+ FontInfoPtr pFontInfo,
+ FontEntryPtr entry,
+ FontNamePtr fontName,
+ char *fileName,
+ FontScalablePtr vals)
+{
+ return BadFontName;
+}
+
+static FontRendererRec renderers[] = {
+ { ".builtin", 8,
+ BuiltinOpenBitmap,
+ BuiltinOpenScalable,
+ BuiltinGetInfoBitmap,
+ BuiltinGetInfoScalable,
+ 0 }
+};
+
+#define numRenderers (sizeof renderers / sizeof renderers[0])
+
+void
+BuiltinRegisterFontFileFunctions(void)
+{
+ int i;
+ for (i = 0; i < numRenderers; i++)
+ FontFileRegisterRenderer ((FontRendererRec *) &renderers[i]);
+}
+
diff --git a/libXfont/src/fc/fsconvert.c b/libXfont/src/fc/fsconvert.c index 15c5e4200..5c979fc23 100644 --- a/libXfont/src/fc/fsconvert.c +++ b/libXfont/src/fc/fsconvert.c @@ -1,719 +1,719 @@ -/* - * Copyright 1990 Network Computing Devices - * - * 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, and that the name of Network Computing Devices not be used - * in advertising or publicity pertaining to distribution of the software - * without specific, written prior permission. Network Computing Devices - * makes no representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, - * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE - * OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Dave Lemke, Network Computing Devices, Inc - */ -/* - * FS data conversion - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/X.h> -#include <X11/Xtrans/Xtrans.h> -#include <X11/Xpoll.h> -#include <X11/fonts/FS.h> -#include <X11/fonts/FSproto.h> -#include <X11/fonts/fontmisc.h> -#include <X11/fonts/fontstruct.h> -#include "fservestr.h" -#include <X11/fonts/fontutil.h> -#include "fslibos.h" - -extern char _fs_glyph_undefined; -extern char _fs_glyph_requested; - -/* - * converts data from font server form to X server form - */ - -void -_fs_convert_char_info(fsXCharInfo *src, xCharInfo *dst) -{ - dst->ascent = src->ascent; - dst->descent = src->descent; - dst->leftSideBearing = src->left; - dst->rightSideBearing = src->right; - dst->characterWidth = src->width; - dst->attributes = src->attributes; -} - -void -_fs_init_fontinfo(FSFpePtr conn, FontInfoPtr pfi) -{ - if (conn->fsMajorVersion == 1) { - unsigned short n; - n = pfi->firstCol; - pfi->firstCol = pfi->firstRow; - pfi->firstRow = n; - n = pfi->lastCol; - pfi->lastCol = pfi->lastRow; - pfi->lastRow = n; - pfi->defaultCh = ((pfi->defaultCh >> 8) & 0xff) - + ((pfi->defaultCh & 0xff) << 8); - } - - if (FontCouldBeTerminal (pfi)) - { - pfi->terminalFont = TRUE; - pfi->minbounds.ascent = pfi->fontAscent; - pfi->minbounds.descent = pfi->fontDescent; - pfi->minbounds.leftSideBearing = 0; - pfi->minbounds.rightSideBearing = pfi->minbounds.characterWidth; - pfi->maxbounds = pfi->minbounds; - } - - FontComputeInfoAccelerators (pfi); -} - -int -_fs_convert_props(fsPropInfo *pi, fsPropOffset *po, pointer pd, - FontInfoPtr pfi) -{ - FontPropPtr dprop; - int i, - nprops; - char *is_str; - fsPropOffset local_off; - char *off_adr; - char *pdc = pd; - -/* stolen from server/include/resource.h */ -#define BAD_RESOURCE 0xe0000000 - - nprops = pfi->nprops = pi->num_offsets; - - if (nprops < 0 - || nprops > SIZE_MAX/(sizeof(FontPropRec) + sizeof(char))) - return -1; - - dprop = malloc(sizeof(FontPropRec) * nprops + sizeof (char) * nprops); - if (!dprop) - return -1; - - is_str = (char *) (dprop + nprops); - pfi->props = dprop; - pfi->isStringProp = is_str; - - off_adr = (char *)po; - for (i = 0; i < nprops; i++, dprop++, is_str++) - { - memcpy(&local_off, off_adr, SIZEOF(fsPropOffset)); - dprop->name = MakeAtom(&pdc[local_off.name.position], - local_off.name.length, 1); - if (local_off.type != PropTypeString) { - *is_str = FALSE; - dprop->value = local_off.value.position; - } else { - *is_str = TRUE; - dprop->value = (INT32) MakeAtom(&pdc[local_off.value.position], - local_off.value.length, 1); - if (dprop->value == BAD_RESOURCE) - { - free (pfi->props); - pfi->nprops = 0; - pfi->props = 0; - pfi->isStringProp = 0; - return -1; - } - } - off_adr += SIZEOF(fsPropOffset); - } - - return nprops; -} - -void -_fs_free_props (FontInfoPtr pfi) -{ - if (pfi->props) - { - free (pfi->props); - pfi->nprops = 0; - pfi->props = 0; - } -} - -int -_fs_convert_lfwi_reply(FSFpePtr conn, FontInfoPtr pfi, - fsListFontsWithXInfoReply *fsrep, - fsPropInfo *pi, fsPropOffset *po, pointer pd) -{ - fsUnpack_XFontInfoHeader(fsrep, pfi); - _fs_init_fontinfo(conn, pfi); - - if (_fs_convert_props(pi, po, pd, pfi) == -1) - return AllocError; - - return Successful; -} - - -#define ENCODING_UNDEFINED(enc) \ - ((enc)->bits == &_fs_glyph_undefined ? \ - TRUE : \ - (access_done = access_done && (enc)->bits != &_fs_glyph_requested, \ - FALSE)) - -#define GLYPH_UNDEFINED(loc) ENCODING_UNDEFINED(encoding + (loc)) - -/* - * figures out what glyphs to request - * - * Includes logic to attempt to reduce number of round trips to the font - * server: when a glyph is requested, fs_build_range() requests a - * 16-glyph range of glyphs that contains the requested glyph. This is - * predicated on the belief that using a glyph increases the chances - * that nearby glyphs will be used: a good assumption for phonetic - * alphabets, but a questionable one for ideographic/pictographic ones. - */ -/* ARGSUSED */ -int -fs_build_range(FontPtr pfont, Bool range_flag, unsigned int count, - int item_size, unsigned char *data, int *nranges, - fsRange **ranges) -{ - FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate); - FSFontPtr fsfont = (FSFontPtr) (pfont->fontPrivate); - register CharInfoPtr encoding = fsfont->encoding; - FontInfoPtr pfi = &(pfont->info); - fsRange range; - int access_done = TRUE; - int err; - register unsigned long firstrow, lastrow, firstcol, lastcol; - register unsigned long row; - register unsigned long col; - register unsigned long loc; - - if (!fsd->glyphs_to_get) - return AccessDone; - - firstrow = pfi->firstRow; - lastrow = pfi->lastRow; - firstcol = pfi->firstCol; - lastcol = pfi->lastCol; - - /* Make sure we have default char */ - if (fsfont->pDefault && ENCODING_UNDEFINED(fsfont->pDefault)) - { - loc = fsfont->pDefault - encoding; - row = loc / (lastcol - firstcol + 1) + firstrow; - col = loc % (lastcol - firstcol + 1) + firstcol; - - range.min_char_low = range.max_char_low = col; - range.min_char_high = range.max_char_high = row; - - if ((err = add_range(&range, nranges, ranges, FALSE)) != - Successful) return err; - encoding[loc].bits = &_fs_glyph_requested; - access_done = FALSE; - } - - if (!range_flag && item_size == 1) - { - if (firstrow != 0) return AccessDone; - while (count--) - { - col = *data++; - if (col >= firstcol && col <= lastcol && - GLYPH_UNDEFINED(col - firstcol)) - { - int col1, col2; - col1 = col & 0xf0; - col2 = col1 + 15; - if (col1 < firstcol) col1 = firstcol; - if (col2 > lastcol) col2 = lastcol; - /* Collect a 16-glyph neighborhood containing the requested - glyph... should in most cases reduce the number of round - trips to the font server. */ - for (col = col1; col <= col2; col++) - { - if (!GLYPH_UNDEFINED(col - firstcol)) continue; - range.min_char_low = range.max_char_low = col; - range.min_char_high = range.max_char_high = 0; - if ((err = add_range(&range, nranges, ranges, FALSE)) != - Successful) return err; - encoding[col - firstcol].bits = &_fs_glyph_requested; - access_done = FALSE; - } - } - } - } - else - { - fsRange fullrange[1]; - - if (range_flag && count == 0) - { - count = 2; - data = (unsigned char *)fullrange; - fullrange[0].min_char_high = firstrow; - fullrange[0].min_char_low = firstcol; - fullrange[0].max_char_high = lastrow; - fullrange[0].max_char_low = lastcol; - } - - while (count--) - { - int row1, col1, row2, col2; - row1 = row2 = *data++; - col1 = col2 = *data++; - if (range_flag) - { - if (count) - { - row2 = *data++; - col2 = *data++; - count--; - } - else - { - row2 = lastrow; - col2 = lastcol; - } - if (row1 < firstrow) row1 = firstrow; - if (row2 > lastrow) row2 = lastrow; - if (col1 < firstcol) col1 = firstcol; - if (col2 > lastcol) col2 = lastcol; - } - else - { - if (row1 < firstrow || row1 > lastrow || - col1 < firstcol || col1 > lastcol) - continue; - } - for (row = row1; row <= row2; row++) - { - expand_glyph_range: ; - loc = (row - firstrow) * (lastcol + 1 - firstcol) + - (col1 - firstcol); - for (col = col1; col <= col2; col++, loc++) - { - if (GLYPH_UNDEFINED(loc)) - { - if (row1 == row2 && - (((col1 & 0xf) && col1 > firstcol) || - (col2 & 0xf) != 0xf) && (col2 < lastcol)) - { - /* If we're loading from a single row, expand - range of glyphs loaded to a multiple of - a 16-glyph range -- attempt to reduce number - of round trips to the font server. */ - col1 &= 0xf0; - col2 = (col2 & 0xf0) + 15; - if (col1 < firstcol) col1 = firstcol; - if (col2 > lastcol) col2 = lastcol; - goto expand_glyph_range; - } - range.min_char_low = range.max_char_low = col; - range.min_char_high = range.max_char_high = row; - if ((err = add_range(&range, nranges, ranges, FALSE)) != - Successful) return err; - encoding[loc].bits = &_fs_glyph_requested; - access_done = FALSE; - } - } - } - } - } - - return access_done ? - AccessDone : - Successful; -} - -#undef GLYPH_UNDEFINED -#undef ENCODING_UNDEFINED - - -/* _fs_clean_aborted_loadglyphs(): Undoes the changes to the encoding array - performed by fs_build_range(); for use if the associated LoadGlyphs - requests needs to be cancelled. */ - -void -_fs_clean_aborted_loadglyphs(FontPtr pfont, int num_expected_ranges, - fsRange *expected_ranges) -{ - register FSFontPtr fsfont; - register int i; - - fsfont = (FSFontPtr) pfont->fontPrivate; - if (fsfont->encoding) - { - fsRange full_range[1]; - if (!num_expected_ranges) - { - full_range[0].min_char_low = pfont->info.firstCol; - full_range[0].min_char_high = pfont->info.firstRow; - full_range[0].max_char_low = pfont->info.lastCol; - full_range[0].max_char_high = pfont->info.lastRow; - num_expected_ranges = 1; - expected_ranges = full_range; - } - - for (i = 0; i < num_expected_ranges; i++) - { - int row, col; - for (row = expected_ranges[i].min_char_high; - row <= expected_ranges[i].max_char_high; - row++) - { - register CharInfoPtr encoding = fsfont->encoding + - ((row - pfont->info.firstRow) * - (pfont->info.lastCol - - pfont->info.firstCol + 1) + - expected_ranges[i].min_char_low - - pfont->info.firstCol); - for (col = expected_ranges[i].min_char_low; - col <= expected_ranges[i].max_char_low; - encoding++, col++) - { - if (encoding->bits == &_fs_glyph_requested) - encoding->bits = &_fs_glyph_undefined; - } - } - } - } -} - -static int -_fs_get_glyphs(FontPtr pFont, unsigned long count, unsigned char *chars, - FontEncoding charEncoding, - unsigned long *glyphCount, /* RETURN */ - CharInfoPtr *glyphs) /* RETURN */ -{ - FSFontPtr fsdata; - unsigned int firstCol; - register unsigned int numCols; - unsigned int firstRow; - unsigned int numRows; - CharInfoPtr *glyphsBase; - register unsigned int c; - register CharInfoPtr pci; - unsigned int r; - CharInfoPtr encoding; - CharInfoPtr pDefault; - FSFontDataPtr fsd = (FSFontDataPtr) pFont->fpePrivate; - int err = Successful; - - fsdata = (FSFontPtr) pFont->fontPrivate; - encoding = fsdata->encoding; - pDefault = fsdata->pDefault; - firstCol = pFont->info.firstCol; - numCols = pFont->info.lastCol - firstCol + 1; - glyphsBase = glyphs; - - /* In this age of glyph caching, any glyphs gotten through this - procedure should already be loaded. If they are not, we are - dealing with someone (perhaps a ddx driver optimizing a font) - that doesn't understand the finer points of glyph caching. The - CHECK_ENCODING macro checks for this condition... if found, it - calls fs_load_all_glyphs(), which corrects it. Since the caller - of this code will not know how to handle a return value of - Suspended, the fs_load_all_glyphs() procedure will block and - freeze the server until the load operation is done. Moral: the - glyphCachingMode flag really must indicate the capabilities of - the ddx drivers. */ - -#define CHECK_ENCODING(cnum) \ - ( pci = encoding + (cnum), \ - fsd->glyphs_to_get ? \ - ( pci->bits == &_fs_glyph_undefined || pci->bits == &_fs_glyph_requested ? \ - ((err = fs_load_all_glyphs(pFont)), pci) : \ - pci ) : \ - pci ) - - switch (charEncoding) { - - case Linear8Bit: - case TwoD8Bit: - if (pFont->info.firstRow > 0) - break; - if (pFont->info.allExist && pDefault) { - while (err == Successful && count--) { - c = (*chars++) - firstCol; - if (c < numCols) - *glyphs++ = CHECK_ENCODING(c); - else - *glyphs++ = pDefault; - } - } else { - while (err == Successful && count--) { - c = (*chars++) - firstCol; - if (c < numCols && CHECK_ENCODING(c)->bits) - *glyphs++ = pci; - else if (pDefault) - *glyphs++ = pDefault; - } - } - break; - case Linear16Bit: - if (pFont->info.allExist && pDefault) { - while (err == Successful && count--) { - c = *chars++ << 8; - c = (c | *chars++) - firstCol; - if (c < numCols) - *glyphs++ = CHECK_ENCODING(c); - else - *glyphs++ = pDefault; - } - } else { - while (err == Successful && count--) { - c = *chars++ << 8; - c = (c | *chars++) - firstCol; - if (c < numCols && CHECK_ENCODING(c)->bits) - *glyphs++ = pci; - else if (pDefault) - *glyphs++ = pDefault; - } - } - break; - - case TwoD16Bit: - firstRow = pFont->info.firstRow; - numRows = pFont->info.lastRow - firstRow + 1; - while (err == Successful && count--) { - r = (*chars++) - firstRow; - c = (*chars++) - firstCol; - if (r < numRows && c < numCols && - CHECK_ENCODING(r * numCols + c)->bits) - *glyphs++ = pci; - else if (pDefault) - *glyphs++ = pDefault; - } - break; - } - *glyphCount = glyphs - glyphsBase; - return err; -} - - -static int -_fs_get_metrics(FontPtr pFont, unsigned long count, unsigned char *chars, - FontEncoding charEncoding, - unsigned long *glyphCount, /* RETURN */ - xCharInfo **glyphs) /* RETURN */ -{ - FSFontPtr fsdata; - unsigned int firstCol; - register unsigned int numCols; - unsigned int firstRow; - unsigned int numRows; - xCharInfo **glyphsBase; - register unsigned int c; - unsigned int r; - CharInfoPtr encoding; - CharInfoPtr pDefault; - - fsdata = (FSFontPtr) pFont->fontPrivate; - encoding = fsdata->inkMetrics; - pDefault = fsdata->pDefault; - /* convert default bitmap metric to default ink metric */ - if (pDefault) - pDefault = encoding + (pDefault - fsdata->encoding); - firstCol = pFont->info.firstCol; - numCols = pFont->info.lastCol - firstCol + 1; - glyphsBase = glyphs; - - - /* XXX - this should be much smarter */ - /* make sure the glyphs are there */ - switch (charEncoding) { - - case Linear8Bit: - case TwoD8Bit: - if (pFont->info.firstRow > 0) - break; - if (pFont->info.allExist && pDefault) { - while (count--) { - c = (*chars++) - firstCol; - if (c < numCols) - *glyphs++ = (xCharInfo *)&encoding[c]; - else - *glyphs++ = (xCharInfo *)pDefault; - } - } else { - while (count--) { - c = (*chars++) - firstCol; - if (c < numCols) - *glyphs++ = (xCharInfo *)(encoding + c); - else if (pDefault) - *glyphs++ = (xCharInfo *)pDefault; - } - } - break; - case Linear16Bit: - if (pFont->info.allExist && pDefault) { - while (count--) { - c = *chars++ << 8; - c = (c | *chars++) - firstCol; - if (c < numCols) - *glyphs++ = (xCharInfo *)(encoding + c); - else - *glyphs++ = (xCharInfo *)pDefault; - } - } else { - while (count--) { - c = *chars++ << 8; - c = (c | *chars++) - firstCol; - if (c < numCols) - *glyphs++ = (xCharInfo *)(encoding + c); - else if (pDefault) - *glyphs++ = (xCharInfo *)pDefault; - } - } - break; - - case TwoD16Bit: - firstRow = pFont->info.firstRow; - numRows = pFont->info.lastRow - firstRow + 1; - while (count--) { - r = (*chars++) - firstRow; - c = (*chars++) - firstCol; - if (r < numRows && c < numCols) - *glyphs++ = (xCharInfo *)(encoding + (r * numCols + c)); - else if (pDefault) - *glyphs++ = (xCharInfo *)pDefault; - } - break; - } - *glyphCount = glyphs - glyphsBase; - return Successful; -} - - -static void -_fs_unload_font(FontPtr pfont) -{ - FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate; - FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate; - CharInfoPtr encoding = fsdata->encoding; - FSGlyphPtr glyphs; - - /* - * fsdata points at FSFontRec, FSFontDataRec and name - */ - if (encoding) - free(encoding); - - while ((glyphs = fsdata->glyphs)) - { - fsdata->glyphs = glyphs->next; - free (glyphs); - } - - /* XXX we may get called after the resource DB has been cleaned out */ - if (find_old_font(fsd->fontid)) - DeleteFontClientID (fsd->fontid); - - _fs_free_props (&pfont->info); - - free(fsdata); - - DestroyFontRec(pfont); -} - -FontPtr -fs_create_font (FontPathElementPtr fpe, - char *name, - int namelen, - fsBitmapFormat format, - fsBitmapFormatMask fmask) -{ - FontPtr pfont; - FSFontPtr fsfont; - FSFontDataPtr fsd; - int bit, byte, scan, glyph; - - pfont = CreateFontRec (); - if (!pfont) - return 0; - fsfont = malloc (sizeof (FSFontRec) + sizeof (FSFontDataRec) + namelen + 1); - if (!fsfont) - { - DestroyFontRec (pfont); - return 0; - } - fsd = (FSFontDataPtr) (fsfont + 1); - bzero((char *) fsfont, sizeof(FSFontRec)); - bzero((char *) fsd, sizeof(FSFontDataRec)); - - pfont->fpe = fpe; - pfont->fontPrivate = (pointer) fsfont; - pfont->fpePrivate = (pointer) fsd; - - /* These font components will be needed in packGlyphs */ - CheckFSFormat(format, BitmapFormatMaskBit | - BitmapFormatMaskByte | - BitmapFormatMaskScanLineUnit | - BitmapFormatMaskScanLinePad, - &bit, - &byte, - &scan, - &glyph, - NULL); - pfont->format = format; - pfont->bit = bit; - pfont->byte = byte; - pfont->scan = scan; - pfont->glyph = glyph; - - pfont->info.nprops = 0; - pfont->info.props = 0; - pfont->info.isStringProp = 0; - - /* set font function pointers */ - pfont->get_glyphs = _fs_get_glyphs; - pfont->get_metrics = _fs_get_metrics; - pfont->unload_font = _fs_unload_font; - pfont->unload_glyphs = NULL; - - /* set the FPE private information */ - fsd->format = format; - fsd->fmask = fmask; - fsd->name = (char *) (fsd + 1); - memcpy (fsd->name, name, namelen); - fsd->name[namelen] = '\0'; - fsd->fontid = GetNewFontClientID (); - - /* save the ID */ - if (!StoreFontClientFont(pfont, fsd->fontid)) - { - free (fsfont); - DestroyFontRec (pfont); - return 0; - } - - return pfont; -} - -pointer -fs_alloc_glyphs (FontPtr pFont, int size) -{ - FSGlyphPtr glyphs; - FSFontPtr fsfont = (FSFontPtr) pFont->fontPrivate; - - glyphs = malloc (sizeof (FSGlyphRec) + size); - glyphs->next = fsfont->glyphs; - fsfont->glyphs = glyphs; - return (pointer) (glyphs + 1); -} +/*
+ * Copyright 1990 Network Computing Devices
+ *
+ * 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, and that the name of Network Computing Devices not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Network Computing Devices
+ * makes no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+ * OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Dave Lemke, Network Computing Devices, Inc
+ */
+/*
+ * FS data conversion
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/X.h>
+#include <X11/Xtrans/Xtrans.h>
+#include <X11/Xpoll.h>
+#include <X11/fonts/FS.h>
+#include <X11/fonts/FSproto.h>
+#include <X11/fonts/fontmisc.h>
+#include <X11/fonts/fontstruct.h>
+#include "fservestr.h"
+#include <X11/fonts/fontutil.h>
+#include "fslibos.h"
+
+extern char _fs_glyph_undefined;
+extern char _fs_glyph_requested;
+
+/*
+ * converts data from font server form to X server form
+ */
+
+void
+_fs_convert_char_info(fsXCharInfo *src, xCharInfo *dst)
+{
+ dst->ascent = src->ascent;
+ dst->descent = src->descent;
+ dst->leftSideBearing = src->left;
+ dst->rightSideBearing = src->right;
+ dst->characterWidth = src->width;
+ dst->attributes = src->attributes;
+}
+
+void
+_fs_init_fontinfo(FSFpePtr conn, FontInfoPtr pfi)
+{
+ if (conn->fsMajorVersion == 1) {
+ unsigned short n;
+ n = pfi->firstCol;
+ pfi->firstCol = pfi->firstRow;
+ pfi->firstRow = n;
+ n = pfi->lastCol;
+ pfi->lastCol = pfi->lastRow;
+ pfi->lastRow = n;
+ pfi->defaultCh = ((pfi->defaultCh >> 8) & 0xff)
+ + ((pfi->defaultCh & 0xff) << 8);
+ }
+
+ if (FontCouldBeTerminal (pfi))
+ {
+ pfi->terminalFont = TRUE;
+ pfi->minbounds.ascent = pfi->fontAscent;
+ pfi->minbounds.descent = pfi->fontDescent;
+ pfi->minbounds.leftSideBearing = 0;
+ pfi->minbounds.rightSideBearing = pfi->minbounds.characterWidth;
+ pfi->maxbounds = pfi->minbounds;
+ }
+
+ FontComputeInfoAccelerators (pfi);
+}
+
+int
+_fs_convert_props(fsPropInfo *pi, fsPropOffset *po, pointer pd,
+ FontInfoPtr pfi)
+{
+ FontPropPtr dprop;
+ int i,
+ nprops;
+ char *is_str;
+ fsPropOffset local_off;
+ char *off_adr;
+ char *pdc = pd;
+
+/* stolen from server/include/resource.h */
+#define BAD_RESOURCE 0xe0000000
+
+ nprops = pfi->nprops = pi->num_offsets;
+
+ if (nprops < 0
+ || nprops > SIZE_MAX/(sizeof(FontPropRec) + sizeof(char)))
+ return -1;
+
+ dprop = malloc(sizeof(FontPropRec) * nprops + sizeof (char) * nprops);
+ if (!dprop)
+ return -1;
+
+ is_str = (char *) (dprop + nprops);
+ pfi->props = dprop;
+ pfi->isStringProp = is_str;
+
+ off_adr = (char *)po;
+ for (i = 0; i < nprops; i++, dprop++, is_str++)
+ {
+ memcpy(&local_off, off_adr, SIZEOF(fsPropOffset));
+ dprop->name = MakeAtom(&pdc[local_off.name.position],
+ local_off.name.length, 1);
+ if (local_off.type != PropTypeString) {
+ *is_str = FALSE;
+ dprop->value = local_off.value.position;
+ } else {
+ *is_str = TRUE;
+ dprop->value = (INT32) MakeAtom(&pdc[local_off.value.position],
+ local_off.value.length, 1);
+ if (dprop->value == BAD_RESOURCE)
+ {
+ free (pfi->props);
+ pfi->nprops = 0;
+ pfi->props = 0;
+ pfi->isStringProp = 0;
+ return -1;
+ }
+ }
+ off_adr += SIZEOF(fsPropOffset);
+ }
+
+ return nprops;
+}
+
+void
+_fs_free_props (FontInfoPtr pfi)
+{
+ if (pfi->props)
+ {
+ free (pfi->props);
+ pfi->nprops = 0;
+ pfi->props = 0;
+ }
+}
+
+int
+_fs_convert_lfwi_reply(FSFpePtr conn, FontInfoPtr pfi,
+ fsListFontsWithXInfoReply *fsrep,
+ fsPropInfo *pi, fsPropOffset *po, pointer pd)
+{
+ fsUnpack_XFontInfoHeader(fsrep, pfi);
+ _fs_init_fontinfo(conn, pfi);
+
+ if (_fs_convert_props(pi, po, pd, pfi) == -1)
+ return AllocError;
+
+ return Successful;
+}
+
+
+#define ENCODING_UNDEFINED(enc) \
+ ((enc)->bits == &_fs_glyph_undefined ? \
+ TRUE : \
+ (access_done = access_done && (enc)->bits != &_fs_glyph_requested, \
+ FALSE))
+
+#define GLYPH_UNDEFINED(loc) ENCODING_UNDEFINED(encoding + (loc))
+
+/*
+ * figures out what glyphs to request
+ *
+ * Includes logic to attempt to reduce number of round trips to the font
+ * server: when a glyph is requested, fs_build_range() requests a
+ * 16-glyph range of glyphs that contains the requested glyph. This is
+ * predicated on the belief that using a glyph increases the chances
+ * that nearby glyphs will be used: a good assumption for phonetic
+ * alphabets, but a questionable one for ideographic/pictographic ones.
+ */
+/* ARGSUSED */
+int
+fs_build_range(FontPtr pfont, Bool range_flag, unsigned int count,
+ int item_size, unsigned char *data, int *nranges,
+ fsRange **ranges)
+{
+ FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate);
+ FSFontPtr fsfont = (FSFontPtr) (pfont->fontPrivate);
+ register CharInfoPtr encoding = fsfont->encoding;
+ FontInfoPtr pfi = &(pfont->info);
+ fsRange range;
+ int access_done = TRUE;
+ int err;
+ register unsigned long firstrow, lastrow, firstcol, lastcol;
+ register unsigned long row;
+ register unsigned long col;
+ register unsigned long loc;
+
+ if (!fsd->glyphs_to_get)
+ return AccessDone;
+
+ firstrow = pfi->firstRow;
+ lastrow = pfi->lastRow;
+ firstcol = pfi->firstCol;
+ lastcol = pfi->lastCol;
+
+ /* Make sure we have default char */
+ if (fsfont->pDefault && ENCODING_UNDEFINED(fsfont->pDefault))
+ {
+ loc = fsfont->pDefault - encoding;
+ row = loc / (lastcol - firstcol + 1) + firstrow;
+ col = loc % (lastcol - firstcol + 1) + firstcol;
+
+ range.min_char_low = range.max_char_low = col;
+ range.min_char_high = range.max_char_high = row;
+
+ if ((err = add_range(&range, nranges, ranges, FALSE)) !=
+ Successful) return err;
+ encoding[loc].bits = &_fs_glyph_requested;
+ access_done = FALSE;
+ }
+
+ if (!range_flag && item_size == 1)
+ {
+ if (firstrow != 0) return AccessDone;
+ while (count--)
+ {
+ col = *data++;
+ if (col >= firstcol && col <= lastcol &&
+ GLYPH_UNDEFINED(col - firstcol))
+ {
+ int col1, col2;
+ col1 = col & 0xf0;
+ col2 = col1 + 15;
+ if (col1 < firstcol) col1 = firstcol;
+ if (col2 > lastcol) col2 = lastcol;
+ /* Collect a 16-glyph neighborhood containing the requested
+ glyph... should in most cases reduce the number of round
+ trips to the font server. */
+ for (col = col1; col <= col2; col++)
+ {
+ if (!GLYPH_UNDEFINED(col - firstcol)) continue;
+ range.min_char_low = range.max_char_low = col;
+ range.min_char_high = range.max_char_high = 0;
+ if ((err = add_range(&range, nranges, ranges, FALSE)) !=
+ Successful) return err;
+ encoding[col - firstcol].bits = &_fs_glyph_requested;
+ access_done = FALSE;
+ }
+ }
+ }
+ }
+ else
+ {
+ fsRange fullrange[1];
+
+ if (range_flag && count == 0)
+ {
+ count = 2;
+ data = (unsigned char *)fullrange;
+ fullrange[0].min_char_high = firstrow;
+ fullrange[0].min_char_low = firstcol;
+ fullrange[0].max_char_high = lastrow;
+ fullrange[0].max_char_low = lastcol;
+ }
+
+ while (count--)
+ {
+ int row1, col1, row2, col2;
+ row1 = row2 = *data++;
+ col1 = col2 = *data++;
+ if (range_flag)
+ {
+ if (count)
+ {
+ row2 = *data++;
+ col2 = *data++;
+ count--;
+ }
+ else
+ {
+ row2 = lastrow;
+ col2 = lastcol;
+ }
+ if (row1 < firstrow) row1 = firstrow;
+ if (row2 > lastrow) row2 = lastrow;
+ if (col1 < firstcol) col1 = firstcol;
+ if (col2 > lastcol) col2 = lastcol;
+ }
+ else
+ {
+ if (row1 < firstrow || row1 > lastrow ||
+ col1 < firstcol || col1 > lastcol)
+ continue;
+ }
+ for (row = row1; row <= row2; row++)
+ {
+ expand_glyph_range: ;
+ loc = (row - firstrow) * (lastcol + 1 - firstcol) +
+ (col1 - firstcol);
+ for (col = col1; col <= col2; col++, loc++)
+ {
+ if (GLYPH_UNDEFINED(loc))
+ {
+ if (row1 == row2 &&
+ (((col1 & 0xf) && col1 > firstcol) ||
+ (col2 & 0xf) != 0xf) && (col2 < lastcol))
+ {
+ /* If we're loading from a single row, expand
+ range of glyphs loaded to a multiple of
+ a 16-glyph range -- attempt to reduce number
+ of round trips to the font server. */
+ col1 &= 0xf0;
+ col2 = (col2 & 0xf0) + 15;
+ if (col1 < firstcol) col1 = firstcol;
+ if (col2 > lastcol) col2 = lastcol;
+ goto expand_glyph_range;
+ }
+ range.min_char_low = range.max_char_low = col;
+ range.min_char_high = range.max_char_high = row;
+ if ((err = add_range(&range, nranges, ranges, FALSE)) !=
+ Successful) return err;
+ encoding[loc].bits = &_fs_glyph_requested;
+ access_done = FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ return access_done ?
+ AccessDone :
+ Successful;
+}
+
+#undef GLYPH_UNDEFINED
+#undef ENCODING_UNDEFINED
+
+
+/* _fs_clean_aborted_loadglyphs(): Undoes the changes to the encoding array
+ performed by fs_build_range(); for use if the associated LoadGlyphs
+ requests needs to be cancelled. */
+
+void
+_fs_clean_aborted_loadglyphs(FontPtr pfont, int num_expected_ranges,
+ fsRange *expected_ranges)
+{
+ register FSFontPtr fsfont;
+ register int i;
+
+ fsfont = (FSFontPtr) pfont->fontPrivate;
+ if (fsfont->encoding)
+ {
+ fsRange full_range[1];
+ if (!num_expected_ranges)
+ {
+ full_range[0].min_char_low = pfont->info.firstCol;
+ full_range[0].min_char_high = pfont->info.firstRow;
+ full_range[0].max_char_low = pfont->info.lastCol;
+ full_range[0].max_char_high = pfont->info.lastRow;
+ num_expected_ranges = 1;
+ expected_ranges = full_range;
+ }
+
+ for (i = 0; i < num_expected_ranges; i++)
+ {
+ int row, col;
+ for (row = expected_ranges[i].min_char_high;
+ row <= expected_ranges[i].max_char_high;
+ row++)
+ {
+ register CharInfoPtr encoding = fsfont->encoding +
+ ((row - pfont->info.firstRow) *
+ (pfont->info.lastCol -
+ pfont->info.firstCol + 1) +
+ expected_ranges[i].min_char_low -
+ pfont->info.firstCol);
+ for (col = expected_ranges[i].min_char_low;
+ col <= expected_ranges[i].max_char_low;
+ encoding++, col++)
+ {
+ if (encoding->bits == &_fs_glyph_requested)
+ encoding->bits = &_fs_glyph_undefined;
+ }
+ }
+ }
+ }
+}
+
+static int
+_fs_get_glyphs(FontPtr pFont, unsigned long count, unsigned char *chars,
+ FontEncoding charEncoding,
+ unsigned long *glyphCount, /* RETURN */
+ CharInfoPtr *glyphs) /* RETURN */
+{
+ FSFontPtr fsdata;
+ unsigned int firstCol;
+ register unsigned int numCols;
+ unsigned int firstRow;
+ unsigned int numRows;
+ CharInfoPtr *glyphsBase;
+ register unsigned int c;
+ register CharInfoPtr pci;
+ unsigned int r;
+ CharInfoPtr encoding;
+ CharInfoPtr pDefault;
+ FSFontDataPtr fsd = (FSFontDataPtr) pFont->fpePrivate;
+ int err = Successful;
+
+ fsdata = (FSFontPtr) pFont->fontPrivate;
+ encoding = fsdata->encoding;
+ pDefault = fsdata->pDefault;
+ firstCol = pFont->info.firstCol;
+ numCols = pFont->info.lastCol - firstCol + 1;
+ glyphsBase = glyphs;
+
+ /* In this age of glyph caching, any glyphs gotten through this
+ procedure should already be loaded. If they are not, we are
+ dealing with someone (perhaps a ddx driver optimizing a font)
+ that doesn't understand the finer points of glyph caching. The
+ CHECK_ENCODING macro checks for this condition... if found, it
+ calls fs_load_all_glyphs(), which corrects it. Since the caller
+ of this code will not know how to handle a return value of
+ Suspended, the fs_load_all_glyphs() procedure will block and
+ freeze the server until the load operation is done. Moral: the
+ glyphCachingMode flag really must indicate the capabilities of
+ the ddx drivers. */
+
+#define CHECK_ENCODING(cnum) \
+ ( pci = encoding + (cnum), \
+ fsd->glyphs_to_get ? \
+ ( pci->bits == &_fs_glyph_undefined || pci->bits == &_fs_glyph_requested ? \
+ ((err = fs_load_all_glyphs(pFont)), pci) : \
+ pci ) : \
+ pci )
+
+ switch (charEncoding) {
+
+ case Linear8Bit:
+ case TwoD8Bit:
+ if (pFont->info.firstRow > 0)
+ break;
+ if (pFont->info.allExist && pDefault) {
+ while (err == Successful && count--) {
+ c = (*chars++) - firstCol;
+ if (c < numCols)
+ *glyphs++ = CHECK_ENCODING(c);
+ else
+ *glyphs++ = pDefault;
+ }
+ } else {
+ while (err == Successful && count--) {
+ c = (*chars++) - firstCol;
+ if (c < numCols && CHECK_ENCODING(c)->bits)
+ *glyphs++ = pci;
+ else if (pDefault)
+ *glyphs++ = pDefault;
+ }
+ }
+ break;
+ case Linear16Bit:
+ if (pFont->info.allExist && pDefault) {
+ while (err == Successful && count--) {
+ c = *chars++ << 8;
+ c = (c | *chars++) - firstCol;
+ if (c < numCols)
+ *glyphs++ = CHECK_ENCODING(c);
+ else
+ *glyphs++ = pDefault;
+ }
+ } else {
+ while (err == Successful && count--) {
+ c = *chars++ << 8;
+ c = (c | *chars++) - firstCol;
+ if (c < numCols && CHECK_ENCODING(c)->bits)
+ *glyphs++ = pci;
+ else if (pDefault)
+ *glyphs++ = pDefault;
+ }
+ }
+ break;
+
+ case TwoD16Bit:
+ firstRow = pFont->info.firstRow;
+ numRows = pFont->info.lastRow - firstRow + 1;
+ while (err == Successful && count--) {
+ r = (*chars++) - firstRow;
+ c = (*chars++) - firstCol;
+ if (r < numRows && c < numCols &&
+ CHECK_ENCODING(r * numCols + c)->bits)
+ *glyphs++ = pci;
+ else if (pDefault)
+ *glyphs++ = pDefault;
+ }
+ break;
+ }
+ *glyphCount = glyphs - glyphsBase;
+ return err;
+}
+
+
+static int
+_fs_get_metrics(FontPtr pFont, unsigned long count, unsigned char *chars,
+ FontEncoding charEncoding,
+ unsigned long *glyphCount, /* RETURN */
+ xCharInfo **glyphs) /* RETURN */
+{
+ FSFontPtr fsdata;
+ unsigned int firstCol;
+ register unsigned int numCols;
+ unsigned int firstRow;
+ unsigned int numRows;
+ xCharInfo **glyphsBase;
+ register unsigned int c;
+ unsigned int r;
+ CharInfoPtr encoding;
+ CharInfoPtr pDefault;
+
+ fsdata = (FSFontPtr) pFont->fontPrivate;
+ encoding = fsdata->inkMetrics;
+ pDefault = fsdata->pDefault;
+ /* convert default bitmap metric to default ink metric */
+ if (pDefault)
+ pDefault = encoding + (pDefault - fsdata->encoding);
+ firstCol = pFont->info.firstCol;
+ numCols = pFont->info.lastCol - firstCol + 1;
+ glyphsBase = glyphs;
+
+
+ /* XXX - this should be much smarter */
+ /* make sure the glyphs are there */
+ switch (charEncoding) {
+
+ case Linear8Bit:
+ case TwoD8Bit:
+ if (pFont->info.firstRow > 0)
+ break;
+ if (pFont->info.allExist && pDefault) {
+ while (count--) {
+ c = (*chars++) - firstCol;
+ if (c < numCols)
+ *glyphs++ = (xCharInfo *)&encoding[c];
+ else
+ *glyphs++ = (xCharInfo *)pDefault;
+ }
+ } else {
+ while (count--) {
+ c = (*chars++) - firstCol;
+ if (c < numCols)
+ *glyphs++ = (xCharInfo *)(encoding + c);
+ else if (pDefault)
+ *glyphs++ = (xCharInfo *)pDefault;
+ }
+ }
+ break;
+ case Linear16Bit:
+ if (pFont->info.allExist && pDefault) {
+ while (count--) {
+ c = *chars++ << 8;
+ c = (c | *chars++) - firstCol;
+ if (c < numCols)
+ *glyphs++ = (xCharInfo *)(encoding + c);
+ else
+ *glyphs++ = (xCharInfo *)pDefault;
+ }
+ } else {
+ while (count--) {
+ c = *chars++ << 8;
+ c = (c | *chars++) - firstCol;
+ if (c < numCols)
+ *glyphs++ = (xCharInfo *)(encoding + c);
+ else if (pDefault)
+ *glyphs++ = (xCharInfo *)pDefault;
+ }
+ }
+ break;
+
+ case TwoD16Bit:
+ firstRow = pFont->info.firstRow;
+ numRows = pFont->info.lastRow - firstRow + 1;
+ while (count--) {
+ r = (*chars++) - firstRow;
+ c = (*chars++) - firstCol;
+ if (r < numRows && c < numCols)
+ *glyphs++ = (xCharInfo *)(encoding + (r * numCols + c));
+ else if (pDefault)
+ *glyphs++ = (xCharInfo *)pDefault;
+ }
+ break;
+ }
+ *glyphCount = glyphs - glyphsBase;
+ return Successful;
+}
+
+
+static void
+_fs_unload_font(FontPtr pfont)
+{
+ FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate;
+ FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate;
+ CharInfoPtr encoding = fsdata->encoding;
+ FSGlyphPtr glyphs;
+
+ /*
+ * fsdata points at FSFontRec, FSFontDataRec and name
+ */
+ if (encoding)
+ free(encoding);
+
+ while ((glyphs = fsdata->glyphs))
+ {
+ fsdata->glyphs = glyphs->next;
+ free (glyphs);
+ }
+
+ /* XXX we may get called after the resource DB has been cleaned out */
+ if (find_old_font(fsd->fontid))
+ DeleteFontClientID (fsd->fontid);
+
+ _fs_free_props (&pfont->info);
+
+ free(fsdata);
+
+ DestroyFontRec(pfont);
+}
+
+FontPtr
+fs_create_font (FontPathElementPtr fpe,
+ char *name,
+ int namelen,
+ fsBitmapFormat format,
+ fsBitmapFormatMask fmask)
+{
+ FontPtr pfont;
+ FSFontPtr fsfont;
+ FSFontDataPtr fsd;
+ int bit, byte, scan, glyph;
+
+ pfont = CreateFontRec ();
+ if (!pfont)
+ return 0;
+ fsfont = malloc (sizeof (FSFontRec) + sizeof (FSFontDataRec) + namelen + 1);
+ if (!fsfont)
+ {
+ DestroyFontRec (pfont);
+ return 0;
+ }
+ fsd = (FSFontDataPtr) (fsfont + 1);
+ bzero((char *) fsfont, sizeof(FSFontRec));
+ bzero((char *) fsd, sizeof(FSFontDataRec));
+
+ pfont->fpe = fpe;
+ pfont->fontPrivate = (pointer) fsfont;
+ pfont->fpePrivate = (pointer) fsd;
+
+ /* These font components will be needed in packGlyphs */
+ CheckFSFormat(format, BitmapFormatMaskBit |
+ BitmapFormatMaskByte |
+ BitmapFormatMaskScanLineUnit |
+ BitmapFormatMaskScanLinePad,
+ &bit,
+ &byte,
+ &scan,
+ &glyph,
+ NULL);
+ pfont->format = format;
+ pfont->bit = bit;
+ pfont->byte = byte;
+ pfont->scan = scan;
+ pfont->glyph = glyph;
+
+ pfont->info.nprops = 0;
+ pfont->info.props = 0;
+ pfont->info.isStringProp = 0;
+
+ /* set font function pointers */
+ pfont->get_glyphs = _fs_get_glyphs;
+ pfont->get_metrics = _fs_get_metrics;
+ pfont->unload_font = _fs_unload_font;
+ pfont->unload_glyphs = NULL;
+
+ /* set the FPE private information */
+ fsd->format = format;
+ fsd->fmask = fmask;
+ fsd->name = (char *) (fsd + 1);
+ memcpy (fsd->name, name, namelen);
+ fsd->name[namelen] = '\0';
+ fsd->fontid = GetNewFontClientID ();
+
+ /* save the ID */
+ if (!StoreFontClientFont(pfont, fsd->fontid))
+ {
+ free (fsfont);
+ DestroyFontRec (pfont);
+ return 0;
+ }
+
+ return pfont;
+}
+
+pointer
+fs_alloc_glyphs (FontPtr pFont, int size)
+{
+ FSGlyphPtr glyphs;
+ FSFontPtr fsfont = (FSFontPtr) pFont->fontPrivate;
+
+ glyphs = malloc (sizeof (FSGlyphRec) + size);
+ glyphs->next = fsfont->glyphs;
+ fsfont->glyphs = glyphs;
+ return (pointer) (glyphs + 1);
+}
diff --git a/libXfont/src/fc/fserve.c b/libXfont/src/fc/fserve.c index b02b0b749..f59dbcc9f 100644 --- a/libXfont/src/fc/fserve.c +++ b/libXfont/src/fc/fserve.c @@ -1,3198 +1,3198 @@ -/* - -Copyright 1990, 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. - -*/ - -/* - * Copyright 1990 Network Computing Devices - * - * 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, and that the names of Network Computing Devices, or Digital - * not be used in advertising or publicity pertaining to distribution - * of the software without specific, written prior permission. - * - * NETWORK COMPUTING DEVICES, AND DIGITAL AND DISCLAIM ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, - * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - * THIS SOFTWARE. - * - * Author: Dave Lemke, Network Computing Devices, Inc - */ -/* - * font server specific font access - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef WIN32 -#define _WILLWINSOCK_ -#endif -#define FONT_t -#define TRANS_CLIENT -#include "X11/Xtrans/Xtrans.h" -#include "X11/Xpoll.h" -#include <X11/fonts/FS.h> -#include <X11/fonts/FSproto.h> -#include <X11/X.h> -#include <X11/Xos.h> -#include <X11/fonts/fontmisc.h> -#include <X11/fonts/fontstruct.h> -#include "fservestr.h" -#include <X11/fonts/fontutil.h> -#include <errno.h> - -#include <time.h> -#define Time_t time_t - -#ifdef NCD -#include <ncd/nvram.h> -#endif - -#include <stddef.h> - -#ifndef MIN -#define MIN(a,b) ((a)<(b)?(a):(b)) -#endif -#define TimeCmp(a,c,b) ((int) ((a) - (b)) c 0) - -#define NONZEROMETRICS(pci) ((pci)->leftSideBearing || \ - (pci)->rightSideBearing || \ - (pci)->ascent || \ - (pci)->descent || \ - (pci)->characterWidth) - -extern void ErrorF(const char *f, ...); - -static int fs_read_glyphs ( FontPathElementPtr fpe, FSBlockDataPtr blockrec ); -static int fs_read_list ( FontPathElementPtr fpe, FSBlockDataPtr blockrec ); -static int fs_read_list_info ( FontPathElementPtr fpe, - FSBlockDataPtr blockrec ); - -extern fd_set _fs_fd_mask; - -static void fs_block_handler ( pointer data, OSTimePtr wt, - pointer LastSelectMask ); -static int fs_wakeup ( FontPathElementPtr fpe, unsigned long *mask ); - -/* - * List of all FPEs - */ -static FSFpePtr fs_fpes; -/* - * Union of all FPE blockStates - */ -static CARD32 fs_blockState; - -static int _fs_restart_connection ( FSFpePtr conn ); -static void fs_send_query_bitmaps ( FontPathElementPtr fpe, - FSBlockDataPtr blockrec ); -static int fs_send_close_font ( FontPathElementPtr fpe, Font id ); -static void fs_client_died ( pointer client, FontPathElementPtr fpe ); -static void _fs_client_access ( FSFpePtr conn, pointer client, Bool sync ); -static void _fs_client_resolution ( FSFpePtr conn ); -static fsGenericReply *fs_get_reply (FSFpePtr conn, int *error); -static int fs_await_reply (FSFpePtr conn); -static void _fs_do_blocked (FSFpePtr conn); -static void fs_cleanup_bfont (FSBlockedFontPtr bfont); - -char _fs_glyph_undefined; -char _fs_glyph_requested; -static char _fs_glyph_zero_length; - -static int generationCount; - -static int FontServerRequestTimeout = 30 * 1000; - -static void -_fs_close_server (FSFpePtr conn); - -static FSFpePtr -_fs_init_conn (char *servername); - -static int -_fs_wait_connect (FSFpePtr conn); - -static int -_fs_send_init_packets (FSFpePtr conn); - -static void -_fs_check_reconnect (FSFpePtr conn); - -static void -_fs_start_reconnect (FSFpePtr conn); - -static void -_fs_free_conn (FSFpePtr conn); - -static int -fs_free_fpe(FontPathElementPtr fpe); - -/* - * Font server access - * - * the basic idea for the non-blocking access is to have the function - * called multiple times until the actual data is returned, instead - * of ClientBlocked. - * - * the first call to the function will cause the request to be sent to - * the font server, and a block record to be stored in the fpe's list - * of outstanding requests. the FS block handler also sticks the - * proper set of fd's into the select mask. when data is ready to be - * read in, the FS wakup handler will be hit. this will read the - * data off the wire into the proper block record, and then signal the - * client that caused the block so that it can restart. it will then - * call the access function again, which will realize that the data has - * arrived and return it. - */ - - -#ifdef DEBUG -static void -_fs_add_req_log(FSFpePtr conn, int opcode) -{ - conn->current_seq++; - fprintf (stderr, "\t\tRequest: %5d Opcode: %2d\n", - conn->current_seq, opcode); - conn->reqbuffer[conn->reqindex].opcode = opcode; - conn->reqbuffer[conn->reqindex].sequence = conn->current_seq; - conn->reqindex++; - if (conn->reqindex == REQUEST_LOG_SIZE) - conn->reqindex = 0; -} - -static void -_fs_add_rep_log (FSFpePtr conn, fsGenericReply *rep) -{ - int i; - - for (i = 0; i < REQUEST_LOG_SIZE; i++) - if (conn->reqbuffer[i].sequence == rep->sequenceNumber) - break; - if (i == REQUEST_LOG_SIZE) - fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: unknown\n", - rep->sequenceNumber); - else - fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: %d\n", - rep->sequenceNumber, - conn->reqbuffer[i].opcode); -} -#else -#define _fs_add_req_log(conn,op) ((conn)->current_seq++) -#define _fs_add_rep_log(conn,rep) -#endif - -static Bool -fs_name_check(char *name) -{ - /* Just make sure there is a protocol/ prefix */ - return (name && *name != '/' && strchr(name, '/')); -} - -static void -_fs_client_resolution(FSFpePtr conn) -{ - fsSetResolutionReq srreq; - int num_res; - FontResolutionPtr res; - - res = GetClientResolutions(&num_res); - - if (num_res) { - srreq.reqType = FS_SetResolution; - srreq.num_resolutions = num_res; - srreq.length = (SIZEOF(fsSetResolutionReq) + - (num_res * SIZEOF(fsResolution)) + 3) >> 2; - - _fs_add_req_log(conn, FS_SetResolution); - if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != -1) - (void)_fs_write_pad(conn, (char *) res, - (num_res * SIZEOF(fsResolution))); - } -} - -/* - * close font server and remove any state associated with - * this connection - this includes any client records. - */ - -static void -fs_close_conn(FSFpePtr conn) -{ - FSClientPtr client, nclient; - - _fs_close_server (conn); - - for (client = conn->clients; client; client = nclient) - { - nclient = client->next; - free (client); - } - conn->clients = NULL; -} - -/* - * the wakeup handlers have to be set when the FPE is open, and not - * removed until it is freed, in order to handle unexpected data, like - * events - */ -/* ARGSUSED */ -static int -fs_init_fpe(FontPathElementPtr fpe) -{ - FSFpePtr conn; - char *name; - int err; - int ret; - - /* open font server */ - /* create FS specific fpe info */ - name = fpe->name; - - /* hack for old style names */ - if (*name == ':') - name++; /* skip ':' */ - - conn = _fs_init_conn (name); - if (!conn) - err = AllocError; - else - { - err = init_fs_handlers (fpe, fs_block_handler); - if (err != Successful) - { - _fs_free_conn (conn); - err = AllocError; - } - else - { - fpe->private = conn; - conn->next = fs_fpes; - fs_fpes = conn; - ret = _fs_wait_connect (conn); - if (ret != FSIO_READY) - { - fs_free_fpe (fpe); - err = BadFontPath; - } - else - err = Successful; - } - } - - if (err == Successful) - { -#ifdef NCD - if (configData.ExtendedFontDiags) - printf("Connected to font server \"%s\"\n", name); -#endif -#ifdef DEBUG - fprintf (stderr, "connected to FS \"%s\"\n", name); -#endif - } - else - { -#ifdef DEBUG - fprintf(stderr, "failed to connect to FS \"%s\" %d\n", name, err); -#endif -#ifdef NCD - if (configData.ExtendedFontDiags) - printf("Failed to connect to font server \"%s\"\n", name); -#endif - ; - } - return err; -} - -static int -fs_reset_fpe(FontPathElementPtr fpe) -{ - (void) _fs_send_init_packets((FSFpePtr) fpe->private); - return Successful; -} - -/* - * this shouldn't be called till all refs to the FPE are gone - */ - -static int -fs_free_fpe(FontPathElementPtr fpe) -{ - FSFpePtr conn = (FSFpePtr) fpe->private, *prev; - - /* unhook from chain of all font servers */ - for (prev = &fs_fpes; *prev; prev = &(*prev)->next) - { - if (*prev == conn) - { - *prev = conn->next; - break; - } - } - _fs_unmark_block (conn, conn->blockState); - fs_close_conn(conn); - remove_fs_handlers(fpe, fs_block_handler, fs_fpes == 0); - _fs_free_conn (conn); - fpe->private = (pointer) 0; - -#ifdef NCD - if (configData.ExtendedFontDiags) - printf("Disconnected from font server \"%s\"\n", fpe->name); -#endif -#ifdef DEBUG - fprintf (stderr, "disconnect from FS \"%s\"\n", fpe->name); -#endif - - return Successful; -} - -static FSBlockDataPtr -fs_new_block_rec(FontPathElementPtr fpe, pointer client, int type) -{ - FSBlockDataPtr blockrec, - *prev; - FSFpePtr conn = (FSFpePtr) fpe->private; - int size; - - switch (type) { - case FS_OPEN_FONT: - size = sizeof(FSBlockedFontRec); - break; - case FS_LOAD_GLYPHS: - size = sizeof(FSBlockedGlyphRec); - break; - case FS_LIST_FONTS: - size = sizeof(FSBlockedListRec); - break; - case FS_LIST_WITH_INFO: - size = sizeof(FSBlockedListInfoRec); - break; - default: - size = 0; - break; - } - blockrec = malloc(sizeof(FSBlockDataRec) + size); - if (!blockrec) - return (FSBlockDataPtr) 0; - blockrec->data = (pointer) (blockrec + 1); - blockrec->client = client; - blockrec->sequenceNumber = -1; - blockrec->errcode = StillWorking; - blockrec->type = type; - blockrec->depending = 0; - blockrec->next = (FSBlockDataPtr) 0; - - /* stick it on the end of the list (since its expected last) */ - for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next) - ; - *prev = blockrec; - - return blockrec; -} - -static void -_fs_set_pending_reply (FSFpePtr conn) -{ - FSBlockDataPtr blockrec; - - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - if (blockrec->errcode == StillWorking) - break; - if (blockrec) - { - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - _fs_mark_block (conn, FS_PENDING_REPLY); - } - else - _fs_unmark_block (conn, FS_PENDING_REPLY); -} - -static void -_fs_remove_block_rec(FSFpePtr conn, FSBlockDataPtr blockrec) -{ - FSBlockDataPtr *prev; - - for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next) - if (*prev == blockrec) - { - *prev = blockrec->next; - break; - } - if (blockrec->type == FS_LOAD_GLYPHS) - { - FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data; - if (bglyph->num_expected_ranges) - free(bglyph->expected_ranges); - } - free(blockrec); - _fs_set_pending_reply (conn); -} - -static void -_fs_signal_clients_depending(FSClientsDependingPtr *clients_depending) -{ - FSClientsDependingPtr p; - - while ((p = *clients_depending)) - { - *clients_depending = p->next; - ClientSignal(p->client); - free(p); - } -} - -static int -_fs_add_clients_depending(FSClientsDependingPtr *clients_depending, pointer client) -{ - FSClientsDependingPtr new, cd; - - for (; (cd = *clients_depending); - clients_depending = &(*clients_depending)->next) - { - if (cd->client == client) - return Suspended; - } - - new = malloc (sizeof (FSClientsDependingRec)); - if (!new) - return BadAlloc; - - new->client = client; - new->next = 0; - *clients_depending = new; - return Suspended; -} - -/* - * When a request is aborted due to a font server failure, - * signal any depending clients to restart their dependant - * requests - */ -static void -_fs_clean_aborted_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec) -{ - switch(blockrec->type) { - case FS_OPEN_FONT: { - FSBlockedFontPtr bfont = (FSBlockedFontPtr)blockrec->data; - - fs_cleanup_bfont (bfont); - _fs_signal_clients_depending(&bfont->clients_depending); - break; - } - case FS_LOAD_GLYPHS: { - FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data; - - _fs_clean_aborted_loadglyphs(bglyph->pfont, - bglyph->num_expected_ranges, - bglyph->expected_ranges); - _fs_signal_clients_depending(&bglyph->clients_depending); - break; - } - case FS_LIST_FONTS: - break; - case FS_LIST_WITH_INFO: { - FSBlockedListInfoPtr binfo; - binfo = (FSBlockedListInfoPtr) blockrec->data; - if (binfo->status == FS_LFWI_REPLY) - FD_SET(conn->fs_fd, &_fs_fd_mask); - _fs_free_props (&binfo->info); - } - default: - break; - } -} - -static void -fs_abort_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec) -{ - _fs_clean_aborted_blockrec (conn, blockrec); - _fs_remove_block_rec (conn, blockrec); -} - -/* - * Tell the font server we've failed to complete an open and - * then unload the partially created font - */ -static void -fs_cleanup_bfont (FSBlockedFontPtr bfont) -{ - FSFontDataRec *fsd; - - if (bfont->pfont) - { - fsd = (FSFontDataRec *) bfont->pfont->fpePrivate; - - /* make sure the FS knows we choked on it */ - fs_send_close_font(bfont->pfont->fpe, bfont->fontid); - - /* - * Either unload the font if it's being opened for - * the first time, or smash the generation field to - * mark this font as an orphan - */ - if (!(bfont->flags & FontReopen)) - { - if (bfont->freeFont) - (*bfont->pfont->unload_font) (bfont->pfont); -#ifdef DEBUG - else - fprintf (stderr, "Not freeing other font in cleanup_bfont\n"); -#endif - bfont->pfont = 0; - } - else - fsd->generation = -1; - } -} - -/* - * Check to see if a complete reply is waiting - */ -static fsGenericReply * -fs_get_reply (FSFpePtr conn, int *error) -{ - char *buf; - fsGenericReply *rep; - int ret; - - /* block if the connection is down or paused in lfwi */ - if (conn->fs_fd == -1 || !FD_ISSET (conn->fs_fd, &_fs_fd_mask)) - { - *error = FSIO_BLOCK; - return 0; - } - - ret = _fs_start_read (conn, sizeof (fsGenericReply), &buf); - if (ret != FSIO_READY) - { - *error = FSIO_BLOCK; - return 0; - } - - rep = (fsGenericReply *) buf; - - ret = _fs_start_read (conn, rep->length << 2, &buf); - if (ret != FSIO_READY) - { - *error = FSIO_BLOCK; - return 0; - } - - *error = FSIO_READY; - - return (fsGenericReply *) buf; -} - -static Bool -fs_reply_ready (FSFpePtr conn) -{ - fsGenericReply *rep; - - if (conn->fs_fd == -1 || !FD_ISSET (conn->fs_fd, &_fs_fd_mask)) - return FALSE; - if (fs_data_read (conn) < sizeof (fsGenericReply)) - return FALSE; - rep = (fsGenericReply *) (conn->inBuf.buf + conn->inBuf.remove); - if (fs_data_read (conn) < rep->length << 2) - return FALSE; - return TRUE; -} - -static void -_fs_pending_reply (FSFpePtr conn) -{ - if (!(conn->blockState & FS_PENDING_REPLY)) - { - _fs_mark_block (conn, FS_PENDING_REPLY); - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - } -} - -static void -_fs_prepare_for_reply (FSFpePtr conn) -{ - _fs_pending_reply (conn); - _fs_flush (conn); -} - -/* - * Block (for a while) awaiting a complete reply - */ -static int -fs_await_reply (FSFpePtr conn) -{ - int ret; - - if (conn->blockState & FS_COMPLETE_REPLY) - return FSIO_READY; - - while (!fs_get_reply (conn, &ret)) - { - if (ret != FSIO_BLOCK) - return ret; - if (_fs_wait_for_readable (conn, FontServerRequestTimeout) != FSIO_READY) - { - _fs_connection_died (conn); - return FSIO_ERROR; - } - } - return FSIO_READY; -} - -/* - * Process the reply to an OpenBitmapFont request - */ -static int -fs_read_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - fsOpenBitmapFontReply *rep; - FSBlockDataPtr blockOrig; - FSBlockedFontPtr origBfont; - int ret; - - rep = (fsOpenBitmapFontReply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error) - { - if (ret == FSIO_BLOCK) - return StillWorking; - if (rep) - _fs_done_read (conn, rep->length << 2); - fs_cleanup_bfont (bfont); - return BadFontName; - } - - /* If we're not reopening a font and FS detected a duplicate font - open request, replace our reference to the new font with a - reference to an existing font (possibly one not finished - opening). If this is a reopen, keep the new font reference... - it's got the metrics and extents we read when the font was opened - before. This also gives us the freedom to easily close the font - if we we decide (in fs_read_query_info()) that we don't like what - we got. */ - - if (rep->otherid && !(bfont->flags & FontReopen)) - { - fs_cleanup_bfont (bfont); - - /* Find old font if we're completely done getting it from server. */ - bfont->pfont = find_old_font(rep->otherid); - bfont->freeFont = FALSE; - bfont->fontid = rep->otherid; - bfont->state = FS_DONE_REPLY; - /* - * look for a blocked request to open the same font - */ - for (blockOrig = conn->blockedRequests; - blockOrig; - blockOrig = blockOrig->next) - { - if (blockOrig != blockrec && blockOrig->type == FS_OPEN_FONT) - { - origBfont = (FSBlockedFontPtr) blockOrig->data; - if (origBfont->fontid == rep->otherid) - { - blockrec->depending = blockOrig->depending; - blockOrig->depending = blockrec; - bfont->state = FS_DEPENDING; - bfont->pfont = origBfont->pfont; - break; - } - } - } - if (bfont->pfont == NULL) - { - /* XXX - something nasty happened */ - ret = BadFontName; - } - else - ret = AccessDone; - } - else - { - bfont->pfont->info.cachable = rep->cachable != 0; - bfont->state = FS_INFO_REPLY; - /* - * Reset the blockrec for the next reply - */ - blockrec->sequenceNumber = bfont->queryInfoSequence; - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - ret = StillWorking; - } - _fs_done_read (conn, rep->length << 2); - return ret; -} - -static Bool -fs_fonts_match (FontInfoPtr pInfo1, FontInfoPtr pInfo2) -{ - int i; - - if (pInfo1->firstCol != pInfo2->firstCol || - pInfo1->lastCol != pInfo2->lastCol || - pInfo1->firstRow != pInfo2->firstRow || - pInfo1->lastRow != pInfo2->lastRow || - pInfo1->defaultCh != pInfo2->defaultCh || - pInfo1->noOverlap != pInfo2->noOverlap || - pInfo1->terminalFont != pInfo2->terminalFont || - pInfo1->constantMetrics != pInfo2->constantMetrics || - pInfo1->constantWidth != pInfo2->constantWidth || - pInfo1->inkInside != pInfo2->inkInside || - pInfo1->inkMetrics != pInfo2->inkMetrics || - pInfo1->allExist != pInfo2->allExist || - pInfo1->drawDirection != pInfo2->drawDirection || - pInfo1->cachable != pInfo2->cachable || - pInfo1->anamorphic != pInfo2->anamorphic || - pInfo1->maxOverlap != pInfo2->maxOverlap || - pInfo1->fontAscent != pInfo2->fontAscent || - pInfo1->fontDescent != pInfo2->fontDescent || - pInfo1->nprops != pInfo2->nprops) - return FALSE; - -#define MATCH(xci1, xci2) \ - (((xci1).leftSideBearing == (xci2).leftSideBearing) && \ - ((xci1).rightSideBearing == (xci2).rightSideBearing) && \ - ((xci1).characterWidth == (xci2).characterWidth) && \ - ((xci1).ascent == (xci2).ascent) && \ - ((xci1).descent == (xci2).descent) && \ - ((xci1).attributes == (xci2).attributes)) - - if (!MATCH(pInfo1->maxbounds, pInfo2->maxbounds) || - !MATCH(pInfo1->minbounds, pInfo2->minbounds) || - !MATCH(pInfo1->ink_maxbounds, pInfo2->ink_maxbounds) || - !MATCH(pInfo1->ink_minbounds, pInfo2->ink_minbounds)) - return FALSE; - -#undef MATCH - - for (i = 0; i < pInfo1->nprops; i++) - if (pInfo1->isStringProp[i] != - pInfo2->isStringProp[i] || - pInfo1->props[i].name != - pInfo2->props[i].name || - pInfo1->props[i].value != - pInfo2->props[i].value) - { - return FALSE; - } - return TRUE; -} - -static int -fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - FSFpePtr conn = (FSFpePtr) fpe->private; - fsQueryXInfoReply *rep; - char *buf; - fsPropInfo *pi; - fsPropOffset *po; - pointer pd; - FontInfoPtr pInfo; - FontInfoRec tempInfo; - int err; - int ret; - - rep = (fsQueryXInfoReply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error) - { - if (ret == FSIO_BLOCK) - return StillWorking; - if (rep) - _fs_done_read (conn, rep->length << 2); - fs_cleanup_bfont (bfont); - return BadFontName; - } - - /* If this is a reopen, accumulate the query info into a dummy - font and compare to our original data. */ - if (bfont->flags & FontReopen) - pInfo = &tempInfo; - else - pInfo = &bfont->pfont->info; - - buf = (char *) rep; - buf += SIZEOF(fsQueryXInfoReply); - - /* move the data over */ - fsUnpack_XFontInfoHeader(rep, pInfo); - - /* compute accelerators */ - _fs_init_fontinfo(conn, pInfo); - - /* Compute offsets into the reply */ - pi = (fsPropInfo *) buf; - buf += SIZEOF (fsPropInfo); - - po = (fsPropOffset *) buf; - buf += pi->num_offsets * SIZEOF(fsPropOffset); - - pd = (pointer) buf; - buf += pi->data_len; - - /* convert the properties and step over the reply */ - ret = _fs_convert_props(pi, po, pd, pInfo); - _fs_done_read (conn, rep->length << 2); - - if (ret == -1) - { - fs_cleanup_bfont (bfont); - return AllocError; - } - - if (bfont->flags & FontReopen) - { - /* We're reopening a font that we lost because of a downed - connection. In the interest of avoiding corruption from - opening a different font than the old one (we already have - its metrics, extents, and probably some of its glyphs), - verify that the metrics and properties all match. */ - - if (fs_fonts_match (pInfo, &bfont->pfont->info)) - { - err = Successful; - bfont->state = FS_DONE_REPLY; - } - else - { - fs_cleanup_bfont (bfont); - err = BadFontName; - } - _fs_free_props (pInfo); - - return err; - } - - /* - * Ask for terminal format fonts if possible - */ - if (bfont->pfont->info.terminalFont) - bfont->format = ((bfont->format & ~ (BitmapFormatImageRectMask)) | - BitmapFormatImageRectMax); - - /* - * Figure out if the whole font should get loaded right now. - */ - if (glyphCachingMode == CACHING_OFF || - (glyphCachingMode == CACHE_16_BIT_GLYPHS - && !bfont->pfont->info.lastRow)) - { - bfont->flags |= FontLoadAll; - } - - /* - * Ready to send the query bitmaps; the terminal font bit has - * been computed and glyphCaching has been considered - */ - if (bfont->flags & FontLoadBitmaps) - { - fs_send_query_bitmaps (fpe, blockrec); - _fs_flush (conn); - } - - bfont->state = FS_EXTENT_REPLY; - - /* - * Reset the blockrec for the next reply - */ - blockrec->sequenceNumber = bfont->queryExtentsSequence; - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - - return StillWorking; -} - -static int -fs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - FSFontDataPtr fsd = (FSFontDataPtr) bfont->pfont->fpePrivate; - FSFontPtr fsfont = (FSFontPtr) bfont->pfont->fontPrivate; - fsQueryXExtents16Reply *rep; - char *buf; - int i; - int numExtents; - int numInfos; - int ret; - Bool haveInk = FALSE; /* need separate ink metrics? */ - CharInfoPtr ci, pCI; - char *fsci; - fsXCharInfo fscilocal; - FontInfoRec *fi = &bfont->pfont->info; - - rep = (fsQueryXExtents16Reply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error) - { - if (ret == FSIO_BLOCK) - return StillWorking; - if (rep) - _fs_done_read (conn, rep->length << 2); - fs_cleanup_bfont (bfont); - return BadFontName; - } - - /* move the data over */ - /* need separate inkMetrics for fixed font server protocol version */ - numExtents = rep->num_extents; - numInfos = numExtents; - if (bfont->pfont->info.terminalFont && conn->fsMajorVersion > 1) - { - numInfos *= 2; - haveInk = TRUE; - } - ci = pCI = malloc(sizeof(CharInfoRec) * numInfos); - - if (!pCI) - { - _fs_done_read (conn, rep->length << 2); - fs_cleanup_bfont(bfont); - return AllocError; - } - fsfont->encoding = pCI; - if (haveInk) - fsfont->inkMetrics = pCI + numExtents; - else - fsfont->inkMetrics = pCI; - - buf = (char *) rep; - buf += SIZEOF (fsQueryXExtents16Reply); - fsci = buf; - - fsd->glyphs_to_get = 0; - ci = fsfont->inkMetrics; - for (i = 0; i < numExtents; i++) - { - memcpy(&fscilocal, fsci, SIZEOF(fsXCharInfo)); /* align it */ - _fs_convert_char_info(&fscilocal, &ci->metrics); - /* Bounds check. */ - if (ci->metrics.ascent > fi->maxbounds.ascent) - { - ErrorF("fserve: warning: %s %s ascent (%d) > maxascent (%d)\n", - fpe->name, fsd->name, - ci->metrics.ascent, fi->maxbounds.ascent); - ci->metrics.ascent = fi->maxbounds.ascent; - } - if (ci->metrics.descent > fi->maxbounds.descent) - { - ErrorF("fserve: warning: %s %s descent (%d) > maxdescent (%d)\n", - fpe->name, fsd->name, - ci->metrics.descent, fi->maxbounds.descent); - ci->metrics.descent = fi->maxbounds.descent; - } - fsci = fsci + SIZEOF(fsXCharInfo); - /* Initialize the bits field for later glyph-caching use */ - if (NONZEROMETRICS(&ci->metrics)) - { - if (!haveInk && - (ci->metrics.leftSideBearing == ci->metrics.rightSideBearing || - ci->metrics.ascent == -ci->metrics.descent)) - pCI[i].bits = &_fs_glyph_zero_length; - else - { - pCI[i].bits = &_fs_glyph_undefined; - fsd->glyphs_to_get++; - } - } - else - pCI[i].bits = (char *)0; - ci++; - } - - /* Done with reply */ - _fs_done_read (conn, rep->length << 2); - - /* build bitmap metrics, ImageRectMax style */ - if (haveInk) - { - CharInfoPtr ii; - - ci = fsfont->encoding; - ii = fsfont->inkMetrics; - for (i = 0; i < numExtents; i++, ci++, ii++) - { - if (NONZEROMETRICS(&ii->metrics)) - { - ci->metrics.leftSideBearing = FONT_MIN_LEFT(fi); - ci->metrics.rightSideBearing = FONT_MAX_RIGHT(fi); - ci->metrics.ascent = FONT_MAX_ASCENT(fi); - ci->metrics.descent = FONT_MAX_DESCENT(fi); - ci->metrics.characterWidth = FONT_MAX_WIDTH(fi); - ci->metrics.attributes = ii->metrics.attributes; - } - else - { - ci->metrics = ii->metrics; - } - /* Bounds check. */ - if (ci->metrics.ascent > fi->maxbounds.ascent) - { - ErrorF("fserve: warning: %s %s ascent (%d) " - "> maxascent (%d)\n", - fpe->name, fsd->name, - ci->metrics.ascent, fi->maxbounds.ascent); - ci->metrics.ascent = fi->maxbounds.ascent; - } - if (ci->metrics.descent > fi->maxbounds.descent) - { - ErrorF("fserve: warning: %s %s descent (%d) " - "> maxdescent (%d)\n", - fpe->name, fsd->name, - ci->metrics.descent, fi->maxbounds.descent); - ci->metrics.descent = fi->maxbounds.descent; - } - } - } - { - unsigned int r, c, numCols, firstCol; - - firstCol = bfont->pfont->info.firstCol; - numCols = bfont->pfont->info.lastCol - firstCol + 1; - c = bfont->pfont->info.defaultCh; - fsfont->pDefault = 0; - if (bfont->pfont->info.lastRow) - { - r = c >> 8; - r -= bfont->pfont->info.firstRow; - c &= 0xff; - c -= firstCol; - if (r < bfont->pfont->info.lastRow-bfont->pfont->info.firstRow+1 && - c < numCols) - fsfont->pDefault = &pCI[r * numCols + c]; - } - else - { - c -= firstCol; - if (c < numCols) - fsfont->pDefault = &pCI[c]; - } - } - bfont->state = FS_GLYPHS_REPLY; - - if (bfont->flags & FontLoadBitmaps) - { - /* - * Reset the blockrec for the next reply - */ - blockrec->sequenceNumber = bfont->queryBitmapsSequence; - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - return StillWorking; - } - return Successful; -} - -#ifdef DEBUG -static char *fs_open_states[] = { - "OPEN_REPLY ", - "INFO_REPLY ", - "EXTENT_REPLY", - "GLYPHS_REPLY", - "DONE_REPLY ", - "DEPENDING ", -}; -#endif - -static int -fs_do_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - int err; - -#ifdef DEBUG - fprintf (stderr, "fs_do_open_font state %s %s\n", - fs_open_states[bfont->state], - ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name); -#endif - err = BadFontName; - switch (bfont->state) { - case FS_OPEN_REPLY: - err = fs_read_open_font(fpe, blockrec); - if (err != StillWorking) { /* already loaded, or error */ - /* if font's already loaded, massage error code */ - switch (bfont->state) { - case FS_DONE_REPLY: - err = Successful; - break; - case FS_DEPENDING: - err = StillWorking; - break; - } - } - break; - case FS_INFO_REPLY: - err = fs_read_query_info(fpe, blockrec); - break; - case FS_EXTENT_REPLY: - err = fs_read_extent_info(fpe, blockrec); - break; - case FS_GLYPHS_REPLY: - if (bfont->flags & FontLoadBitmaps) - err = fs_read_glyphs(fpe, blockrec); - break; - case FS_DEPENDING: /* can't happen */ - default: - break; - } -#ifdef DEBUG - fprintf (stderr, "fs_do_open_font err %d\n", err); -#endif - if (err != StillWorking) - { - bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */ - while ((blockrec = blockrec->depending)) - { - bfont = (FSBlockedFontPtr) blockrec->data; - bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */ - } - } - return err; -} - -void -_fs_mark_block (FSFpePtr conn, CARD32 mask) -{ - conn->blockState |= mask; - fs_blockState |= mask; -} - -void -_fs_unmark_block (FSFpePtr conn, CARD32 mask) -{ - FSFpePtr c; - - if (conn->blockState & mask) - { - conn->blockState &= ~mask; - fs_blockState = 0; - for (c = fs_fpes; c; c = c->next) - fs_blockState |= c->blockState; - } -} - -/* ARGSUSED */ -static void -fs_block_handler(pointer data, OSTimePtr wt, pointer LastSelectMask) -{ - static struct timeval block_timeout; - CARD32 now, earliest, wakeup; - int soonest; - FSFpePtr conn; - - XFD_ORSET((fd_set *)LastSelectMask, (fd_set *)LastSelectMask, - &_fs_fd_mask); - /* - * Flush all pending output - */ - if (fs_blockState & FS_PENDING_WRITE) - for (conn = fs_fpes; conn; conn = conn->next) - if (conn->blockState & FS_PENDING_WRITE) - _fs_flush (conn); - /* - * Check for any fpe with a complete reply, set sleep time to zero - */ - if (fs_blockState & FS_COMPLETE_REPLY) - { - block_timeout.tv_sec = 0; - block_timeout.tv_usec = 0; - if (*wt == NULL) - *wt = &block_timeout; - else - **wt = block_timeout; - } - /* - * Walk through fpe list computing sleep time - */ - else if (fs_blockState & (FS_BROKEN_WRITE| - FS_BROKEN_CONNECTION| - FS_PENDING_REPLY| - FS_RECONNECTING)) - { - now = GetTimeInMillis (); - earliest = now + 10000000; - for (conn = fs_fpes; conn; conn = conn->next) - { - if (conn->blockState & FS_RECONNECTING) - { - wakeup = conn->blockedConnectTime; - if (TimeCmp (wakeup, <, earliest)) - earliest = wakeup; - } - if (conn->blockState & FS_BROKEN_CONNECTION) - { - wakeup = conn->brokenConnectionTime; - if (TimeCmp (wakeup, <, earliest)) - earliest = wakeup; - } - if (conn->blockState & FS_BROKEN_WRITE) - { - wakeup = conn->brokenWriteTime; - if (TimeCmp (wakeup, <, earliest)) - earliest = wakeup; - } - if (conn->blockState & FS_PENDING_REPLY) - { - wakeup = conn->blockedReplyTime; - if (TimeCmp (wakeup, <, earliest)) - earliest = wakeup; - } - } - soonest = earliest - now; - if (soonest < 0) - soonest = 0; - block_timeout.tv_sec = soonest / 1000; - block_timeout.tv_usec = (soonest % 1000) * 1000; - if (*wt == NULL) - *wt = &block_timeout; - else if (soonest < (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000) - **wt = block_timeout; - } -} - -static void -fs_handle_unexpected(FSFpePtr conn, fsGenericReply *rep) -{ - if (rep->type == FS_Event && rep->data1 == KeepAlive) - { - fsNoopReq req; - - /* ping it back */ - req.reqType = FS_Noop; - req.length = SIZEOF(fsNoopReq) >> 2; - _fs_add_req_log(conn, FS_Noop); - _fs_write(conn, (char *) &req, SIZEOF(fsNoopReq)); - } - /* this should suck up unexpected replies and events */ - _fs_done_read (conn, rep->length << 2); -} - -static void -fs_read_reply (FontPathElementPtr fpe, pointer client) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - int ret; - int err; - fsGenericReply *rep; - - if ((rep = fs_get_reply (conn, &ret))) - { - _fs_add_rep_log (conn, rep); - for (blockrec = conn->blockedRequests; - blockrec; - blockrec = blockrec->next) - { - if (blockrec->sequenceNumber == rep->sequenceNumber) - break; - } - err = Successful; - if (!blockrec) - { - fs_handle_unexpected(conn, rep); - } - else - { - /* - * go read it, and if we're done, - * wake up the appropriate client - */ - switch (blockrec->type) { - case FS_OPEN_FONT: - blockrec->errcode = fs_do_open_font(fpe, blockrec); - break; - case FS_LOAD_GLYPHS: - blockrec->errcode = fs_read_glyphs(fpe, blockrec); - break; - case FS_LIST_FONTS: - blockrec->errcode = fs_read_list(fpe, blockrec); - break; - case FS_LIST_WITH_INFO: - blockrec->errcode = fs_read_list_info(fpe, blockrec); - break; - default: - break; - } - err = blockrec->errcode; - if (err != StillWorking) - { - while (blockrec) - { - blockrec->errcode = err; - if (client != blockrec->client) - ClientSignal(blockrec->client); - blockrec = blockrec->depending; - } - _fs_unmark_block (conn, FS_PENDING_REPLY); - } - } - if (fs_reply_ready (conn)) - _fs_mark_block (conn, FS_COMPLETE_REPLY); - else - _fs_unmark_block (conn, FS_COMPLETE_REPLY); - } -} - -static int -fs_wakeup(FontPathElementPtr fpe, unsigned long *mask) -{ - fd_set *LastSelectMask = (fd_set *) mask; - FSFpePtr conn = (FSFpePtr) fpe->private; - - /* - * Don't continue if the fd is -1 (which will be true when the - * font server terminates - */ - if ((conn->blockState & FS_RECONNECTING)) - _fs_check_reconnect (conn); - else if ((conn->blockState & FS_COMPLETE_REPLY) || - (conn->fs_fd != -1 && FD_ISSET(conn->fs_fd, LastSelectMask))) - fs_read_reply (fpe, 0); - if (conn->blockState & (FS_PENDING_REPLY|FS_BROKEN_CONNECTION|FS_BROKEN_WRITE)) - _fs_do_blocked (conn); -#ifdef DEBUG - { - FSBlockDataPtr blockrec; - FSBlockedFontPtr bfont; - FSBlockedListPtr blist; - static CARD32 lastState; - static FSBlockDataPtr lastBlock; - - if (conn->blockState || conn->blockedRequests || lastState || lastBlock) - { - fprintf (stderr, " Block State 0x%x\n", (int) conn->blockState); - lastState = conn->blockState; - lastBlock = conn->blockedRequests; - } - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - { - switch (blockrec->type) { - case FS_OPEN_FONT: - bfont = (FSBlockedFontPtr) blockrec->data; - fprintf (stderr, " Blocked font errcode %d sequence %d state %s %s\n", - blockrec->errcode, - blockrec->sequenceNumber, - fs_open_states[bfont->state], - bfont->pfont ? - ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name : - "<freed>"); - break; - case FS_LIST_FONTS: - blist = (FSBlockedListPtr) blockrec->data; - fprintf (stderr, " Blocked list errcode %d sequence %d\n", - blockrec->errcode, blockrec->sequenceNumber); - break; - default: - fprintf (stderr, " Blocked type %d errcode %d sequence %d\n", - blockrec->type, - blockrec->errcode, - blockrec->sequenceNumber); - break; - } - } - } -#endif - return FALSE; -} - -/* - * Notice a dead connection and prepare for reconnect - */ - -void -_fs_connection_died(FSFpePtr conn) -{ - if (conn->blockState & FS_BROKEN_CONNECTION) - return; - fs_close_conn(conn); - conn->brokenConnectionTime = GetTimeInMillis (); - _fs_mark_block (conn, FS_BROKEN_CONNECTION); - _fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE|FS_RECONNECTING); -} - -/* - * Signal clients that the connection has come back up - */ -static int -_fs_restart_connection(FSFpePtr conn) -{ - FSBlockDataPtr block; - - _fs_unmark_block (conn, FS_GIVE_UP); - while ((block = (FSBlockDataPtr) conn->blockedRequests)) - { - if (block->errcode == StillWorking) - { - ClientSignal(block->client); - fs_abort_blockrec(conn, block); - } - } - return TRUE; -} - -/* - * Declare this font server connection useless - */ -static void -_fs_giveup (FSFpePtr conn) -{ - FSBlockDataPtr block; - - if (conn->blockState & FS_GIVE_UP) - return; -#ifdef DEBUG - fprintf (stderr, "give up on FS \"%s\"\n", conn->servername); -#endif - _fs_mark_block (conn, FS_GIVE_UP); - while ((block = (FSBlockDataPtr) conn->blockedRequests)) - { - if (block->errcode == StillWorking) - { - ClientSignal (block->client); - fs_abort_blockrec (conn, block); - } - } - if (conn->fs_fd >= 0) - _fs_connection_died (conn); -} - -static void -_fs_do_blocked (FSFpePtr conn) -{ - CARD32 now; - - now = GetTimeInMillis (); - if ((conn->blockState & FS_PENDING_REPLY) && - TimeCmp (conn->blockedReplyTime, <=, now)) - { - _fs_giveup (conn); - } - else - { - if (conn->blockState & FS_BROKEN_CONNECTION) - { - /* Try to reconnect broken connections */ - if (TimeCmp (conn->brokenConnectionTime, <=, now)) - _fs_start_reconnect (conn); - } - else if (conn->blockState & FS_BROKEN_WRITE) - { - /* Try to flush blocked connections */ - if (TimeCmp (conn->brokenWriteTime, <=, now)) - _fs_flush (conn); - } - } -} - -/* - * sends the actual request out - */ -/* ARGSUSED */ -static int -fs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags, - char *name, int namelen, - fsBitmapFormat format, fsBitmapFormatMask fmask, - XID id, FontPtr *ppfont) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FontPtr font; - FSBlockDataPtr blockrec = NULL; - FSBlockedFontPtr bfont; - FSFontDataPtr fsd; - fsOpenBitmapFontReq openreq; - fsQueryXInfoReq inforeq; - fsQueryXExtents16Req extreq; - int err; - unsigned char buf[1024]; - - if (conn->blockState & FS_GIVE_UP) - return BadFontName; - - if (namelen <= 0 || namelen > sizeof (buf) - 1) - return BadFontName; - - /* - * Get the font structure put together, either by reusing - * the existing one or creating a new one - */ - if (flags & FontReopen) - { - Atom nameatom, fn = None; - int i; - - font = *ppfont; - fsd = (FSFontDataPtr)font->fpePrivate; - /* This is an attempt to reopen a font. Did the font have a - NAME property? */ - if ((nameatom = MakeAtom("FONT", 4, 0)) != None) - { - for (i = 0; i < font->info.nprops; i++) - if (font->info.props[i].name == nameatom && - font->info.isStringProp[i]) - { - fn = font->info.props[i].value; - break; - } - } - if (fn == None || !(name = NameForAtom(fn))) - { - name = fsd->name; - namelen = fsd->namelen; - } - else - namelen = strlen(name); - } - else - { - font = fs_create_font (fpe, name, namelen, format, fmask); - if (!font) - return AllocError; - - fsd = (FSFontDataPtr)font->fpePrivate; - } - - /* make a new block record, and add it to the end of the list */ - blockrec = fs_new_block_rec(font->fpe, client, FS_OPEN_FONT); - if (!blockrec) - { - if (!(flags & FontReopen)) - (*font->unload_font) (font); - return AllocError; - } - - /* - * Must check this before generating any protocol, otherwise we'll - * mess up a reconnect in progress - */ - if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) - { - _fs_pending_reply (conn); - return Suspended; - } - - fsd->generation = conn->generation; - - bfont = (FSBlockedFontPtr) blockrec->data; - bfont->fontid = fsd->fontid; - bfont->pfont = font; - bfont->state = FS_OPEN_REPLY; - bfont->flags = flags; - bfont->format = fsd->format; - bfont->clients_depending = (FSClientsDependingPtr)0; - bfont->freeFont = (flags & FontReopen) == 0; - - _fs_client_access (conn, client, (flags & FontOpenSync) != 0); - _fs_client_resolution(conn); - - /* do an FS_OpenFont, FS_QueryXInfo and FS_QueryXExtents */ - buf[0] = (unsigned char) namelen; - memcpy(&buf[1], name, namelen); - openreq.reqType = FS_OpenBitmapFont; - openreq.pad = 0; - openreq.fid = fsd->fontid; - openreq.format_hint = fsd->format; - openreq.format_mask = fsd->fmask; - openreq.length = (SIZEOF(fsOpenBitmapFontReq) + namelen + 4) >> 2; - - _fs_add_req_log(conn, FS_OpenBitmapFont); - _fs_write(conn, (char *) &openreq, SIZEOF(fsOpenBitmapFontReq)); - _fs_write_pad(conn, (char *) buf, namelen + 1); - - blockrec->sequenceNumber = conn->current_seq; - - inforeq.reqType = FS_QueryXInfo; - inforeq.pad = 0; - inforeq.id = fsd->fontid; - inforeq.length = SIZEOF(fsQueryXInfoReq) >> 2; - - bfont->queryInfoSequence = conn->current_seq + 1; - - _fs_add_req_log(conn, FS_QueryXInfo); - _fs_write(conn, (char *) &inforeq, SIZEOF(fsQueryXInfoReq)); - - if (!(bfont->flags & FontReopen)) - { - extreq.reqType = FS_QueryXExtents16; - extreq.range = fsTrue; - extreq.fid = fsd->fontid; - extreq.num_ranges = 0; - extreq.length = SIZEOF(fsQueryXExtents16Req) >> 2; - - bfont->queryExtentsSequence = conn->current_seq + 1; - - _fs_add_req_log(conn, FS_QueryXExtents16); - _fs_write(conn, (char *) &extreq, SIZEOF(fsQueryXExtents16Req)); - } - -#ifdef NCD - if (configData.ExtendedFontDiags) - { - memcpy(buf, name, MIN(256, namelen)); - buf[MIN(256, namelen)] = '\0'; - printf("Requesting font \"%s\" from font server \"%s\"\n", - buf, font->fpe->name); - } -#endif - _fs_prepare_for_reply (conn); - - err = blockrec->errcode; - if (bfont->flags & FontOpenSync) - { - while (blockrec->errcode == StillWorking) - { - if (fs_await_reply (conn) != FSIO_READY) - { - blockrec->errcode = BadFontName; - break; - } - fs_read_reply (font->fpe, client); - } - err = blockrec->errcode; - if (err == Successful) - *ppfont = bfont->pfont; - else - fs_cleanup_bfont (bfont); - bfont->freeFont = FALSE; - _fs_remove_block_rec (conn, blockrec); - } - return err == StillWorking ? Suspended : err; -} - -static void -fs_send_query_bitmaps(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - fsQueryXBitmaps16Req bitreq; - - /* send the request */ - bitreq.reqType = FS_QueryXBitmaps16; - bitreq.fid = bfont->fontid; - bitreq.format = bfont->format; - bitreq.range = TRUE; - bitreq.length = SIZEOF(fsQueryXBitmaps16Req) >> 2; - bitreq.num_ranges = 0; - - bfont->queryBitmapsSequence = conn->current_seq + 1; - - _fs_add_req_log(conn, FS_QueryXBitmaps16); - _fs_write(conn, (char *) &bitreq, SIZEOF(fsQueryXBitmaps16Req)); -} - -/* ARGSUSED */ -static int -fs_open_font(pointer client, FontPathElementPtr fpe, Mask flags, - char *name, int namelen, - fsBitmapFormat format, fsBitmapFormatMask fmask, - XID id, FontPtr *ppfont, - char **alias, FontPtr non_cachable_font) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - FSBlockedFontPtr bfont; - int err; - - /* libfont interface expects ImageRectMin glyphs */ - format = (format & ~BitmapFormatImageRectMask) | BitmapFormatImageRectMin; - - *alias = (char *) 0; - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - { - if (blockrec->type == FS_OPEN_FONT && blockrec->client == client) - { - err = blockrec->errcode; - if (err == StillWorking) - return Suspended; - - bfont = (FSBlockedFontPtr) blockrec->data; - if (err == Successful) - *ppfont = bfont->pfont; - else - fs_cleanup_bfont (bfont); - _fs_remove_block_rec (conn, blockrec); - return err; - } - } - return fs_send_open_font(client, fpe, flags, name, namelen, format, fmask, - id, ppfont); -} - -/* ARGSUSED */ -static int -fs_send_close_font(FontPathElementPtr fpe, Font id) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - fsCloseReq req; - - if (conn->blockState & FS_GIVE_UP) - return Successful; - /* tell the font server to close the font */ - req.reqType = FS_CloseFont; - req.pad = 0; - req.length = SIZEOF(fsCloseReq) >> 2; - req.id = id; - _fs_add_req_log(conn, FS_CloseFont); - _fs_write(conn, (char *) &req, SIZEOF(fsCloseReq)); - - return Successful; -} - -/* ARGSUSED */ -static void -fs_close_font(FontPathElementPtr fpe, FontPtr pfont) -{ - FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate; - FSFpePtr conn = (FSFpePtr) fpe->private; - - if (conn->generation == fsd->generation) - fs_send_close_font(fpe, fsd->fontid); - -#ifdef DEBUG - { - FSBlockDataPtr blockrec; - FSBlockedFontPtr bfont; - - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - { - if (blockrec->type == FS_OPEN_FONT) - { - bfont = (FSBlockedFontPtr) blockrec->data; - if (bfont->pfont == pfont) - fprintf (stderr, "closing font which hasn't been opened\n"); - } - } - } -#endif - (*pfont->unload_font) (pfont); -} - -static int -fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr) blockrec->data; - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - FSFpePtr conn = (FSFpePtr) fpe->private; - FontPtr pfont = bglyph->pfont; - /* works for either blocked font - or glyph rec... pfont is at - the very beginning of both - blockrec->data structures */ - FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate); - FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate; - FontInfoPtr pfi = &pfont->info; - fsQueryXBitmaps16Reply *rep; - char *buf; - fsOffset32 *ppbits; - fsOffset32 local_off; - char *off_adr; - pointer pbitmaps; - char *bits, *allbits; -#ifdef DEBUG - char *origallbits; -#endif - int i, - err; - int nranges = 0; - int ret; - fsRange *nextrange = 0; - unsigned long minchar, maxchar; - - rep = (fsQueryXBitmaps16Reply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error) - { - if (ret == FSIO_BLOCK) - return StillWorking; - if (rep) - _fs_done_read (conn, rep->length << 2); - err = AllocError; - goto bail; - } - - buf = (char *) rep; - buf += SIZEOF (fsQueryXBitmaps16Reply); - - ppbits = (fsOffset32 *) buf; - buf += SIZEOF (fsOffset32) * (rep->num_chars); - - pbitmaps = (pointer ) buf; - - if (blockrec->type == FS_LOAD_GLYPHS) - { - nranges = bglyph->num_expected_ranges; - nextrange = bglyph->expected_ranges; - } - - /* place the incoming glyphs */ - if (nranges) - { - /* We're operating under the assumption that the ranges - requested in the LoadGlyphs call were all legal for this - font, and that individual ranges do not cover multiple - rows... fs_build_range() is designed to ensure this. */ - minchar = (nextrange->min_char_high - pfi->firstRow) * - (pfi->lastCol - pfi->firstCol + 1) + - nextrange->min_char_low - pfi->firstCol; - maxchar = (nextrange->max_char_high - pfi->firstRow) * - (pfi->lastCol - pfi->firstCol + 1) + - nextrange->max_char_low - pfi->firstCol; - nextrange++; - } - else - { - minchar = 0; - maxchar = rep->num_chars; - } - - off_adr = (char *)ppbits; - - allbits = fs_alloc_glyphs (pfont, rep->nbytes); - - if (!allbits) - { - err = AllocError; - goto bail; - } - -#ifdef DEBUG - origallbits = allbits; - fprintf (stderr, "Reading %d glyphs in %d bytes for %s\n", - (int) rep->num_chars, (int) rep->nbytes, fsd->name); -#endif - - for (i = 0; i < rep->num_chars; i++) - { - memcpy(&local_off, off_adr, SIZEOF(fsOffset32)); /* align it */ - if (blockrec->type == FS_OPEN_FONT || - fsdata->encoding[minchar].bits == &_fs_glyph_requested) - { - /* - * Broken X font server returns bits for missing characters - * when font is padded - */ - if (NONZEROMETRICS(&fsdata->encoding[minchar].metrics)) - { - if (local_off.length) - { - bits = allbits; - allbits += local_off.length; - memcpy(bits, (char *)pbitmaps + local_off.position, - local_off.length); - } - else - bits = &_fs_glyph_zero_length; - } - else - bits = 0; - if (fsdata->encoding[minchar].bits == &_fs_glyph_requested) - fsd->glyphs_to_get--; - fsdata->encoding[minchar].bits = bits; - } - if (minchar++ == maxchar) - { - if (!--nranges) break; - minchar = (nextrange->min_char_high - pfi->firstRow) * - (pfi->lastCol - pfi->firstCol + 1) + - nextrange->min_char_low - pfi->firstCol; - maxchar = (nextrange->max_char_high - pfi->firstRow) * - (pfi->lastCol - pfi->firstCol + 1) + - nextrange->max_char_low - pfi->firstCol; - nextrange++; - } - off_adr += SIZEOF(fsOffset32); - } -#ifdef DEBUG - fprintf (stderr, "Used %d bytes instead of %d\n", - (int) (allbits - origallbits), (int) rep->nbytes); -#endif - - if (blockrec->type == FS_OPEN_FONT) - { - fsd->glyphs_to_get = 0; - bfont->state = FS_DONE_REPLY; - } - err = Successful; - -bail: - _fs_done_read (conn, rep->length << 2); - return err; -} - -static int -fs_send_load_glyphs(pointer client, FontPtr pfont, - int nranges, fsRange *ranges) -{ - FontPathElementPtr fpe = pfont->fpe; - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockedGlyphPtr blockedglyph; - fsQueryXBitmaps16Req req; - FSBlockDataPtr blockrec; - - if (conn->blockState & FS_GIVE_UP) - return BadCharRange; - - /* make a new block record, and add it to the end of the list */ - blockrec = fs_new_block_rec(fpe, client, FS_LOAD_GLYPHS); - if (!blockrec) - return AllocError; - blockedglyph = (FSBlockedGlyphPtr) blockrec->data; - blockedglyph->pfont = pfont; - blockedglyph->num_expected_ranges = nranges; - /* Assumption: it's our job to free ranges */ - blockedglyph->expected_ranges = ranges; - blockedglyph->clients_depending = (FSClientsDependingPtr)0; - - if (conn->blockState & (FS_BROKEN_CONNECTION|FS_RECONNECTING)) - { - _fs_pending_reply (conn); - return Suspended; - } - - /* send the request */ - req.reqType = FS_QueryXBitmaps16; - req.fid = ((FSFontDataPtr) pfont->fpePrivate)->fontid; - req.format = pfont->format; - if (pfont->info.terminalFont) - req.format = (req.format & ~(BitmapFormatImageRectMask)) | - BitmapFormatImageRectMax; - req.range = TRUE; - /* each range takes up 4 bytes */ - req.length = (SIZEOF(fsQueryXBitmaps16Req) >> 2) + nranges; - req.num_ranges = nranges * 2; /* protocol wants count of fsChar2bs */ - _fs_add_req_log(conn, FS_QueryXBitmaps16); - _fs_write(conn, (char *) &req, SIZEOF(fsQueryXBitmaps16Req)); - - blockrec->sequenceNumber = conn->current_seq; - - /* Send ranges to the server... pack into a char array by hand - to avoid structure-packing portability problems and to - handle swapping for version1 protocol */ - if (nranges) - { -#define RANGE_BUFFER_SIZE 64 -#define RANGE_BUFFER_SIZE_MASK 63 - int i; - char range_buffer[RANGE_BUFFER_SIZE * 4]; - char *range_buffer_p; - - range_buffer_p = range_buffer; - for (i = 0; i < nranges;) - { - if (conn->fsMajorVersion > 1) - { - *range_buffer_p++ = ranges[i].min_char_high; - *range_buffer_p++ = ranges[i].min_char_low; - *range_buffer_p++ = ranges[i].max_char_high; - *range_buffer_p++ = ranges[i].max_char_low; - } - else - { - *range_buffer_p++ = ranges[i].min_char_low; - *range_buffer_p++ = ranges[i].min_char_high; - *range_buffer_p++ = ranges[i].max_char_low; - *range_buffer_p++ = ranges[i].max_char_high; - } - - if (!(++i & RANGE_BUFFER_SIZE_MASK)) - { - _fs_write(conn, range_buffer, RANGE_BUFFER_SIZE * 4); - range_buffer_p = range_buffer; - } - } - if (i &= RANGE_BUFFER_SIZE_MASK) - _fs_write(conn, range_buffer, i * 4); - } - - _fs_prepare_for_reply (conn); - return Suspended; -} - - -extern pointer serverClient; /* This could be any number that - doesn't conflict with existing - client values. */ - -static int -_fs_load_glyphs(pointer client, FontPtr pfont, Bool range_flag, - unsigned int nchars, int item_size, unsigned char *data) -{ - FSFpePtr conn = (FSFpePtr) pfont->fpe->private; - int nranges = 0; - fsRange *ranges = NULL; - int res; - FSBlockDataPtr blockrec; - FSBlockedGlyphPtr blockedglyph; - FSClientsDependingPtr *clients_depending = NULL; - int err; - - /* see if the result is already there */ - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - { - if (blockrec->type == FS_LOAD_GLYPHS) - { - blockedglyph = (FSBlockedGlyphPtr) blockrec->data; - if (blockedglyph->pfont == pfont) - { - /* Look for this request */ - if (blockrec->client == client) - { - err = blockrec->errcode; - if (err == StillWorking) - return Suspended; - _fs_signal_clients_depending(&blockedglyph->clients_depending); - _fs_remove_block_rec(conn, blockrec); - return err; - } - /* We've found an existing LoadGlyphs blockrec for this - font but for another client. Rather than build a - blockrec for it now (which entails some complex - maintenance), we'll add it to a queue of clients to - be signalled when the existing LoadGlyphs is - completed. */ - clients_depending = &blockedglyph->clients_depending; - break; - } - } - else if (blockrec->type == FS_OPEN_FONT) - { - FSBlockedFontPtr bfont; - bfont = (FSBlockedFontPtr) blockrec->data; - if (bfont->pfont == pfont) - { - /* - * An OpenFont is pending for this font, this must - * be from a reopen attempt, so finish the open - * attempt and retry the LoadGlyphs - */ - if (blockrec->client == client) - { - err = blockrec->errcode; - if (err == StillWorking) - return Suspended; - - _fs_signal_clients_depending(&bfont->clients_depending); - _fs_remove_block_rec(conn, blockrec); - if (err != Successful) - return err; - break; - } - /* We've found an existing OpenFont blockrec for this - font but for another client. Rather than build a - blockrec for it now (which entails some complex - maintenance), we'll add it to a queue of clients to - be signalled when the existing OpenFont is - completed. */ - if (blockrec->errcode == StillWorking) - { - clients_depending = &bfont->clients_depending; - break; - } - } - } - } - - /* - * see if the desired glyphs already exist, and return Successful if they - * do, otherwise build up character range/character string - */ - res = fs_build_range(pfont, range_flag, nchars, item_size, data, - &nranges, &ranges); - - switch (res) - { - case AccessDone: - return Successful; - - case Successful: - break; - - default: - return res; - } - - /* - * If clients_depending is not null, this request must wait for - * some prior request(s) to complete. - */ - if (clients_depending) - { - /* Since we're not ready to send the load_glyphs request yet, - clean up the damage (if any) caused by the fs_build_range() - call. */ - if (nranges) - { - _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); - free(ranges); - } - return _fs_add_clients_depending(clients_depending, client); - } - - /* - * If fsd->generation != conn->generation, the font has been closed - * due to a lost connection. We will reopen it, which will result - * in one of three things happening: - * 1) The open will succeed and obtain the same font. Life - * is wonderful. - * 2) The open will fail. There is code above to recognize this - * and flunk the LoadGlyphs request. The client might not be - * thrilled. - * 3) Worst case: the open will succeed but the font we open will - * be different. The fs_read_query_info() procedure attempts - * to detect this by comparing the existing metrics and - * properties against those of the reopened font... if they - * don't match, we flunk the reopen, which eventually results - * in flunking the LoadGlyphs request. We could go a step - * further and compare the extents, but this should be - * sufficient. - */ - if (((FSFontDataPtr)pfont->fpePrivate)->generation != conn->generation) - { - /* Since we're not ready to send the load_glyphs request yet, - clean up the damage caused by the fs_build_range() call. */ - _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); - free(ranges); - - /* Now try to reopen the font. */ - return fs_send_open_font(client, pfont->fpe, - (Mask)FontReopen, (char *)0, 0, - (fsBitmapFormat)0, (fsBitmapFormatMask)0, - (XID)0, &pfont); - } - - return fs_send_load_glyphs(client, pfont, nranges, ranges); -} - -int -fs_load_all_glyphs(FontPtr pfont) -{ - int err; - FSFpePtr conn = (FSFpePtr) pfont->fpe->private; - - /* - * The purpose of this procedure is to load all glyphs in the event - * that we're dealing with someone who doesn't understand the finer - * points of glyph caching... it is called from _fs_get_glyphs() if - * the latter is called to get glyphs that have not yet been loaded. - * We assume that the caller will not know how to handle a return - * value of Suspended (usually the case for a GetGlyphs() caller), - * so this procedure hangs around, freezing the server, for the - * request to complete. This is an unpleasant kluge called to - * perform an unpleasant job that, we hope, will never be required. - */ - - while ((err = _fs_load_glyphs(serverClient, pfont, TRUE, 0, 0, NULL)) == - Suspended) - { - if (fs_await_reply (conn) != FSIO_READY) - { - /* Get rid of blockrec */ - fs_client_died(serverClient, pfont->fpe); - err = BadCharRange; - break; - } - fs_read_reply (pfont->fpe, serverClient); - } - return err; -} - -static int -fs_read_list(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockedListPtr blist = (FSBlockedListPtr) blockrec->data; - fsListFontsReply *rep; - char *data; - int length, - i, - ret; - int err; - - rep = (fsListFontsReply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error) - { - if (ret == FSIO_BLOCK) - return StillWorking; - if (rep) - _fs_done_read (conn, rep->length << 2); - return AllocError; - } - data = (char *) rep + SIZEOF (fsListFontsReply); - - err = Successful; - /* copy data into FontPathRecord */ - for (i = 0; i < rep->nFonts; i++) - { - length = *(unsigned char *)data++; - err = AddFontNamesName(blist->names, data, length); - if (err != Successful) - break; - data += length; - } - _fs_done_read (conn, rep->length << 2); - return err; -} - -static int -fs_send_list_fonts(pointer client, FontPathElementPtr fpe, char *pattern, - int patlen, int maxnames, FontNamesPtr newnames) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - FSBlockedListPtr blockedlist; - fsListFontsReq req; - - if (conn->blockState & FS_GIVE_UP) - return BadFontName; - - /* make a new block record, and add it to the end of the list */ - blockrec = fs_new_block_rec(fpe, client, FS_LIST_FONTS); - if (!blockrec) - return AllocError; - blockedlist = (FSBlockedListPtr) blockrec->data; - blockedlist->names = newnames; - - if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) - { - _fs_pending_reply (conn); - return Suspended; - } - - _fs_client_access (conn, client, FALSE); - _fs_client_resolution(conn); - - /* send the request */ - req.reqType = FS_ListFonts; - req.pad = 0; - req.maxNames = maxnames; - req.nbytes = patlen; - req.length = (SIZEOF(fsListFontsReq) + patlen + 3) >> 2; - _fs_add_req_log(conn, FS_ListFonts); - _fs_write(conn, (char *) &req, SIZEOF(fsListFontsReq)); - _fs_write_pad(conn, (char *) pattern, patlen); - - blockrec->sequenceNumber = conn->current_seq; - -#ifdef NCD - if (configData.ExtendedFontDiags) { - char buf[256]; - - memcpy(buf, pattern, MIN(256, patlen)); - buf[MIN(256, patlen)] = '\0'; - printf("Listing fonts on pattern \"%s\" from font server \"%s\"\n", - buf, fpe->name); - } -#endif - - _fs_prepare_for_reply (conn); - return Suspended; -} - -static int -fs_list_fonts(pointer client, FontPathElementPtr fpe, - char *pattern, int patlen, int maxnames, FontNamesPtr newnames) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - int err; - - /* see if the result is already there */ - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - { - if (blockrec->type == FS_LIST_FONTS && blockrec->client == client) - { - err = blockrec->errcode; - if (err == StillWorking) - return Suspended; - _fs_remove_block_rec(conn, blockrec); - return err; - } - } - - /* didn't find waiting record, so send a new one */ - return fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames); -} - -/* - * Read a single list info reply and restart for the next reply - */ -static int -fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data; - fsListFontsWithXInfoReply *rep; - char *buf; - FSFpePtr conn = (FSFpePtr) fpe->private; - fsPropInfo *pi; - fsPropOffset *po; - pointer pd; - int ret; - int err; - - /* clean up anything from the last trip */ - _fs_free_props (&binfo->info); - - rep = (fsListFontsWithXInfoReply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error) - { - if (ret == FSIO_BLOCK) - return StillWorking; - binfo->status = FS_LFWI_FINISHED; - err = AllocError; - goto done; - } - /* - * Normal termination -- the list ends with a name of length 0 - */ - if (rep->nameLength == 0) - { -#ifdef DEBUG - fprintf (stderr, "fs_read_list_info done\n"); -#endif - binfo->status = FS_LFWI_FINISHED; - err = BadFontName; - goto done; - } - - buf = (char *) rep + SIZEOF (fsListFontsWithXInfoReply); - - /* - * The original FS implementation didn't match - * the spec, version 1 was respecified to match the FS. - * Version 2 matches the original intent - */ - if (conn->fsMajorVersion <= 1) - { - memcpy (binfo->name, buf, rep->nameLength); - buf += _fs_pad_length (rep->nameLength); - } - pi = (fsPropInfo *) buf; - buf += SIZEOF (fsPropInfo); - po = (fsPropOffset *) buf; - buf += pi->num_offsets * SIZEOF (fsPropOffset); - pd = (pointer) buf; - buf += pi->data_len; - if (conn->fsMajorVersion > 1) - { - memcpy (binfo->name, buf, rep->nameLength); - buf += _fs_pad_length (rep->nameLength); - } - -#ifdef DEBUG - binfo->name[rep->nameLength] = '\0'; - fprintf (stderr, "fs_read_list_info %s\n", binfo->name); -#endif - err = _fs_convert_lfwi_reply(conn, &binfo->info, rep, pi, po, pd); - if (err != Successful) - { - binfo->status = FS_LFWI_FINISHED; - goto done; - } - binfo->namelen = rep->nameLength; - binfo->remaining = rep->nReplies; - - binfo->status = FS_LFWI_REPLY; - - /* disable this font server until we've processed this response */ - _fs_unmark_block (conn, FS_COMPLETE_REPLY); - FD_CLR(conn->fs_fd, &_fs_fd_mask); -done: - _fs_done_read (conn, rep->length << 2); - return err; -} - -/* ARGSUSED */ -static int -fs_start_list_with_info(pointer client, FontPathElementPtr fpe, - char *pattern, int len, int maxnames, pointer *pdata) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - FSBlockedListInfoPtr binfo; - fsListFontsWithXInfoReq req; - - if (conn->blockState & FS_GIVE_UP) - return BadFontName; - - /* make a new block record, and add it to the end of the list */ - blockrec = fs_new_block_rec(fpe, client, FS_LIST_WITH_INFO); - if (!blockrec) - return AllocError; - - binfo = (FSBlockedListInfoPtr) blockrec->data; - bzero((char *) binfo, sizeof(FSBlockedListInfoRec)); - binfo->status = FS_LFWI_WAITING; - - if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) - { - _fs_pending_reply (conn); - return Suspended; - } - - _fs_client_access (conn, client, FALSE); - _fs_client_resolution(conn); - - /* send the request */ - req.reqType = FS_ListFontsWithXInfo; - req.pad = 0; - req.maxNames = maxnames; - req.nbytes = len; - req.length = (SIZEOF(fsListFontsWithXInfoReq) + len + 3) >> 2; - _fs_add_req_log(conn, FS_ListFontsWithXInfo); - (void) _fs_write(conn, (char *) &req, SIZEOF(fsListFontsWithXInfoReq)); - (void) _fs_write_pad(conn, pattern, len); - - blockrec->sequenceNumber = conn->current_seq; - -#ifdef NCD - if (configData.ExtendedFontDiags) { - char buf[256]; - - memcpy(buf, pattern, MIN(256, len)); - buf[MIN(256, len)] = '\0'; - printf("Listing fonts with info on pattern \"%s\" from font server \"%s\"\n", - buf, fpe->name); - } -#endif - - _fs_prepare_for_reply (conn); - return Successful; -} - -/* ARGSUSED */ -static int -fs_next_list_with_info(pointer client, FontPathElementPtr fpe, - char **namep, int *namelenp, - FontInfoPtr *pFontInfo, int *numFonts, - pointer private) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - FSBlockedListInfoPtr binfo; - int err; - - /* see if the result is already there */ - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - if (blockrec->type == FS_LIST_WITH_INFO && blockrec->client == client) - break; - - if (!blockrec) - { - /* The only good reason for not finding a blockrec would be if - disconnect/reconnect to the font server wiped it out and the - code that called us didn't do the right thing to create - another one. Under those circumstances, we need to return an - error to prevent that code from attempting to interpret the - information we don't return. */ - return BadFontName; - } - - binfo = (FSBlockedListInfoPtr) blockrec->data; - - if (binfo->status == FS_LFWI_WAITING) - return Suspended; - - *namep = binfo->name; - *namelenp = binfo->namelen; - *pFontInfo = &binfo->info; - *numFonts = binfo->remaining; - - /* Restart reply processing from this font server */ - FD_SET(conn->fs_fd, &_fs_fd_mask); - if (fs_reply_ready (conn)) - _fs_mark_block (conn, FS_COMPLETE_REPLY); - - err = blockrec->errcode; - switch (binfo->status) { - case FS_LFWI_FINISHED: - _fs_remove_block_rec(conn, blockrec); - break; - case FS_LFWI_REPLY: - binfo->status = FS_LFWI_WAITING; - blockrec->errcode = StillWorking; - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - _fs_mark_block (conn, FS_PENDING_REPLY); - break; - } - - return err; -} - -/* - * Called when client exits - */ - -static void -fs_client_died(pointer client, FontPathElementPtr fpe) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec, - depending; - FSClientPtr *prev, cur; - fsFreeACReq freeac; - - for (prev = &conn->clients; (cur = *prev); prev = &cur->next) - { - if (cur->client == client) { - freeac.reqType = FS_FreeAC; - freeac.pad = 0; - freeac.id = cur->acid; - freeac.length = sizeof (fsFreeACReq) >> 2; - _fs_add_req_log(conn, FS_FreeAC); - _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq)); - *prev = cur->next; - free (cur); - break; - } - } - /* find a pending requests */ - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - if (blockrec->client == client) - break; - - if (!blockrec) - return; - - /* replace the client pointers in this block rec with the chained one */ - if ((depending = blockrec->depending)) - { - blockrec->client = depending->client; - blockrec->depending = depending->depending; - blockrec = depending; - } - fs_abort_blockrec(conn, blockrec); -} - -static void -_fs_client_access (FSFpePtr conn, pointer client, Bool sync) -{ - FSClientPtr *prev, cur; - fsCreateACReq crac; - fsSetAuthorizationReq setac; - char *authorizations; - int authlen; - Bool new_cur = FALSE; - char padding[4] = { 0, 0, 0, 0 }; - -#ifdef DEBUG - if (conn->blockState & (FS_RECONNECTING|FS_BROKEN_CONNECTION)) - { - fprintf (stderr, "Sending requests without a connection\n"); - } -#endif - for (prev = &conn->clients; (cur = *prev); prev = &cur->next) - { - if (cur->client == client) - { - if (prev != &conn->clients) - { - *prev = cur->next; - cur->next = conn->clients; - conn->clients = cur; - } - break; - } - } - if (!cur) - { - cur = malloc (sizeof (FSClientRec)); - if (!cur) - return; - cur->client = client; - cur->next = conn->clients; - conn->clients = cur; - cur->acid = GetNewFontClientID (); - new_cur = TRUE; - } - if (new_cur || cur->auth_generation != client_auth_generation(client)) - { - if (!new_cur) - { - fsFreeACReq freeac; - freeac.reqType = FS_FreeAC; - freeac.pad = 0; - freeac.id = cur->acid; - freeac.length = sizeof (fsFreeACReq) >> 2; - _fs_add_req_log(conn, FS_FreeAC); - _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq)); - } - crac.reqType = FS_CreateAC; - crac.num_auths = set_font_authorizations(&authorizations, &authlen, - client); - /* Work around bug in xfs versions up through modular release 1.0.8 - which rejects CreateAC packets with num_auths = 0 & authlen < 4 */ - if (crac.num_auths == 0) { - authorizations = padding; - authlen = 4; - } else { - authlen = (authlen + 3) & ~0x3; - } - crac.length = (sizeof (fsCreateACReq) + authlen) >> 2; - crac.acid = cur->acid; - _fs_add_req_log(conn, FS_CreateAC); - _fs_write(conn, (char *) &crac, sizeof (fsCreateACReq)); - _fs_write(conn, authorizations, authlen); - /* ignore reply; we don't even care about it */ - conn->curacid = 0; - cur->auth_generation = client_auth_generation(client); - } - if (conn->curacid != cur->acid) - { - setac.reqType = FS_SetAuthorization; - setac.pad = 0; - setac.length = sizeof (fsSetAuthorizationReq) >> 2; - setac.id = cur->acid; - _fs_add_req_log(conn, FS_SetAuthorization); - _fs_write(conn, (char *) &setac, sizeof (fsSetAuthorizationReq)); - conn->curacid = cur->acid; - } -} - -/* - * Poll a pending connect - */ - -static int -_fs_check_connect (FSFpePtr conn) -{ - int ret; - - ret = _fs_poll_connect (conn->trans_conn, 0); - switch (ret) { - case FSIO_READY: - conn->fs_fd = _FontTransGetConnectionNumber (conn->trans_conn); - FD_SET (conn->fs_fd, &_fs_fd_mask); - break; - case FSIO_BLOCK: - break; - } - return ret; -} - -/* - * Return an FSIO status while waiting for the completed connection - * reply to arrive - */ - -static fsConnSetup * -_fs_get_conn_setup (FSFpePtr conn, int *error, int *setup_len) -{ - int ret; - char *data; - int headlen; - int len; - fsConnSetup *setup; - fsConnSetupAccept *accept; - - ret = _fs_start_read (conn, SIZEOF (fsConnSetup), &data); - if (ret != FSIO_READY) - { - *error = ret; - return 0; - } - - setup = (fsConnSetup *) data; - if (setup->major_version > FS_PROTOCOL) - { - *error = FSIO_ERROR; - return 0; - } - - headlen = (SIZEOF (fsConnSetup) + - (setup->alternate_len << 2) + - (setup->auth_len << 2)); - /* On anything but Success, no extra data is sent */ - if (setup->status != AuthSuccess) - { - len = headlen; - } - else - { - ret = _fs_start_read (conn, headlen + SIZEOF (fsConnSetupAccept), &data); - if (ret != FSIO_READY) - { - *error = ret; - return 0; - } - setup = (fsConnSetup *) data; - accept = (fsConnSetupAccept *) (data + headlen); - len = headlen + (accept->length << 2); - } - ret = _fs_start_read (conn, len, &data); - if (ret != FSIO_READY) - { - *error = ret; - return 0; - } - *setup_len = len; - return (fsConnSetup *) data; -} - -static int -_fs_send_conn_client_prefix (FSFpePtr conn) -{ - fsConnClientPrefix req; - int endian; - int ret; - - /* send setup prefix */ - endian = 1; - if (*(char *) &endian) - req.byteOrder = 'l'; - else - req.byteOrder = 'B'; - - req.major_version = FS_PROTOCOL; - req.minor_version = FS_PROTOCOL_MINOR; - -/* XXX add some auth info here */ - req.num_auths = 0; - req.auth_len = 0; - ret = _fs_write (conn, (char *) &req, SIZEOF (fsConnClientPrefix)); - if (ret != FSIO_READY) - return FSIO_ERROR; - conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; - return ret; -} - -static int -_fs_recv_conn_setup (FSFpePtr conn) -{ - int ret = FSIO_ERROR; - fsConnSetup *setup; - FSFpeAltPtr alts; - int i, alt_len; - int setup_len; - char *alt_save, *alt_names; - - setup = _fs_get_conn_setup (conn, &ret, &setup_len); - if (!setup) - return ret; - conn->current_seq = 0; - conn->fsMajorVersion = setup->major_version; - /* - * Create an alternate list from the initial server, but - * don't chain looking for alternates. - */ - if (conn->alternate == 0) - { - /* - * free any existing alternates list, allowing the list to - * be updated - */ - if (conn->alts) - { - free (conn->alts); - conn->alts = 0; - conn->numAlts = 0; - } - if (setup->num_alternates) - { - alts = malloc (setup->num_alternates * sizeof (FSFpeAltRec) + - (setup->alternate_len << 2)); - if (alts) - { - alt_names = (char *) (setup + 1); - alt_save = (char *) (alts + setup->num_alternates); - for (i = 0; i < setup->num_alternates; i++) - { - alts[i].subset = alt_names[0]; - alt_len = alt_names[1]; - alts[i].name = alt_save; - memcpy (alt_save, alt_names + 2, alt_len); - alt_save[alt_len] = '\0'; - alt_save += alt_len + 1; - alt_names += _fs_pad_length (alt_len + 2); - } - conn->numAlts = setup->num_alternates; - conn->alts = alts; - } - } - } - _fs_done_read (conn, setup_len); - if (setup->status != AuthSuccess) - return FSIO_ERROR; - return FSIO_READY; -} - -static int -_fs_open_server (FSFpePtr conn) -{ - int ret; - char *servername; - - if (conn->alternate == 0) - servername = conn->servername; - else - servername = conn->alts[conn->alternate-1].name; - conn->trans_conn = _fs_connect (servername, &ret); - conn->blockedConnectTime = GetTimeInMillis () + FS_RECONNECT_WAIT; - return ret; -} - -static char * -_fs_catalog_name (char *servername) -{ - char *sp; - - sp = strchr (servername, '/'); - if (!sp) - return 0; - return strrchr (sp + 1, '/'); -} - -static int -_fs_send_init_packets (FSFpePtr conn) -{ - fsSetResolutionReq srreq; - fsSetCataloguesReq screq; - int num_cats, - clen; - char *catalogues; - char *cat; - char len; - char *end; - int num_res; - FontResolutionPtr res; - -#define CATALOGUE_SEP '+' - - res = GetClientResolutions(&num_res); - if (num_res) - { - srreq.reqType = FS_SetResolution; - srreq.num_resolutions = num_res; - srreq.length = (SIZEOF(fsSetResolutionReq) + - (num_res * SIZEOF(fsResolution)) + 3) >> 2; - - _fs_add_req_log(conn, FS_SetResolution); - if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != FSIO_READY) - return FSIO_ERROR; - if (_fs_write_pad(conn, (char *) res, (num_res * SIZEOF(fsResolution))) != FSIO_READY) - return FSIO_ERROR; - } - - catalogues = 0; - if (conn->alternate != 0) - catalogues = _fs_catalog_name (conn->alts[conn->alternate-1].name); - if (!catalogues) - catalogues = _fs_catalog_name (conn->servername); - - if (!catalogues) - { - conn->has_catalogues = FALSE; - return FSIO_READY; - } - conn->has_catalogues = TRUE; - - /* turn cats into counted list */ - catalogues++; - - cat = catalogues; - num_cats = 0; - clen = 0; - while (*cat) - { - num_cats++; - end = strchr(cat, CATALOGUE_SEP); - if (!end) - end = cat + strlen (cat); - clen += (end - cat) + 1; /* length byte + string */ - cat = end; - } - - screq.reqType = FS_SetCatalogues; - screq.num_catalogues = num_cats; - screq.length = (SIZEOF(fsSetCataloguesReq) + clen + 3) >> 2; - - _fs_add_req_log(conn, FS_SetCatalogues); - if (_fs_write(conn, (char *) &screq, SIZEOF(fsSetCataloguesReq)) != FSIO_READY) - return FSIO_ERROR; - - while (*cat) - { - num_cats++; - end = strchr(cat, CATALOGUE_SEP); - if (!end) - end = cat + strlen (cat); - len = end - cat; - if (_fs_write (conn, &len, 1) != FSIO_READY) - return FSIO_ERROR; - if (_fs_write (conn, cat, (int) len) != FSIO_READY) - return FSIO_ERROR; - cat = end; - } - - if (_fs_write (conn, "....", _fs_pad_length (clen) - clen) != FSIO_READY) - return FSIO_ERROR; - - return FSIO_READY; -} - -static int -_fs_send_cat_sync (FSFpePtr conn) -{ - fsListCataloguesReq lcreq; - - /* - * now sync up with the font server, to see if an error was generated - * by a bogus catalogue - */ - lcreq.reqType = FS_ListCatalogues; - lcreq.length = (SIZEOF(fsListCataloguesReq)) >> 2; - lcreq.maxNames = 0; - lcreq.nbytes = 0; - lcreq.pad2 = 0; - _fs_add_req_log(conn, FS_SetCatalogues); - if (_fs_write(conn, (char *) &lcreq, SIZEOF(fsListCataloguesReq)) != FSIO_READY) - return FSIO_ERROR; - conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; - return FSIO_READY; -} - -static int -_fs_recv_cat_sync (FSFpePtr conn) -{ - fsGenericReply *reply; - fsError *error; - int err; - int ret; - - reply = fs_get_reply (conn, &err); - if (!reply) - return err; - - ret = FSIO_READY; - if (reply->type == FS_Error) - { - error = (fsError *) reply; - if (error->major_opcode == FS_SetCatalogues) - ret = FSIO_ERROR; - } - _fs_done_read (conn, reply->length << 2); - return ret; -} - -static void -_fs_close_server (FSFpePtr conn) -{ - _fs_unmark_block (conn, FS_PENDING_WRITE|FS_BROKEN_WRITE|FS_COMPLETE_REPLY|FS_BROKEN_CONNECTION); - if (conn->trans_conn) - { - _FontTransClose (conn->trans_conn); - conn->trans_conn = 0; - _fs_io_reinit (conn); - } - if (conn->fs_fd >= 0) - { - FD_CLR (conn->fs_fd, &_fs_fd_mask); - conn->fs_fd = -1; - } - conn->fs_conn_state = FS_CONN_UNCONNECTED; -} - -static int -_fs_do_setup_connection (FSFpePtr conn) -{ - int ret; - - do - { -#ifdef DEBUG - fprintf (stderr, "fs_do_setup_connection state %d\n", conn->fs_conn_state); -#endif - switch (conn->fs_conn_state) { - case FS_CONN_UNCONNECTED: - ret = _fs_open_server (conn); - if (ret == FSIO_BLOCK) - conn->fs_conn_state = FS_CONN_CONNECTING; - break; - case FS_CONN_CONNECTING: - ret = _fs_check_connect (conn); - break; - case FS_CONN_CONNECTED: - ret = _fs_send_conn_client_prefix (conn); - break; - case FS_CONN_SENT_PREFIX: - ret = _fs_recv_conn_setup (conn); - break; - case FS_CONN_RECV_INIT: - ret = _fs_send_init_packets (conn); - if (conn->has_catalogues) - ret = _fs_send_cat_sync (conn); - break; - case FS_CONN_SENT_CAT: - if (conn->has_catalogues) - ret = _fs_recv_cat_sync (conn); - else - ret = FSIO_READY; - break; - default: - ret = FSIO_READY; - break; - } - switch (ret) { - case FSIO_READY: - if (conn->fs_conn_state < FS_CONN_RUNNING) - conn->fs_conn_state++; - break; - case FSIO_BLOCK: - if (TimeCmp (GetTimeInMillis (), <, conn->blockedConnectTime)) - break; - ret = FSIO_ERROR; - /* fall through... */ - case FSIO_ERROR: - _fs_close_server (conn); - /* - * Try the next alternate - */ - if (conn->alternate < conn->numAlts) - { - conn->alternate++; - ret = FSIO_READY; - } - else - conn->alternate = 0; - break; - } - } while (conn->fs_conn_state != FS_CONN_RUNNING && ret == FSIO_READY); - if (ret == FSIO_READY) - conn->generation = ++generationCount; - return ret; -} - -static int -_fs_wait_connect (FSFpePtr conn) -{ - int ret; - - for (;;) - { - ret = _fs_do_setup_connection (conn); - if (ret != FSIO_BLOCK) - break; - if (conn->fs_conn_state <= FS_CONN_CONNECTING) - ret = _fs_poll_connect (conn->trans_conn, 1000); - else - ret = _fs_wait_for_readable (conn, 1000); - if (ret == FSIO_ERROR) - break; - } - return ret; -} - -/* - * Poll a connection in the process of reconnecting - */ -static void -_fs_check_reconnect (FSFpePtr conn) -{ - int ret; - - ret = _fs_do_setup_connection (conn); - switch (ret) { - case FSIO_READY: - _fs_unmark_block (conn, FS_RECONNECTING|FS_GIVE_UP); - _fs_restart_connection (conn); - break; - case FSIO_BLOCK: - break; - case FSIO_ERROR: - conn->brokenConnectionTime = GetTimeInMillis () + FS_RECONNECT_POLL; - break; - } -} - -/* - * Start the reconnection process - */ -static void -_fs_start_reconnect (FSFpePtr conn) -{ - if (conn->blockState & FS_RECONNECTING) - return; - conn->alternate = 0; - _fs_mark_block (conn, FS_RECONNECTING); - _fs_unmark_block (conn, FS_BROKEN_CONNECTION); - _fs_check_reconnect (conn); -} - - -static FSFpePtr -_fs_init_conn (char *servername) -{ - FSFpePtr conn; - - conn = calloc (1, sizeof (FSFpeRec) + strlen (servername) + 1); - if (!conn) - return 0; - if (!_fs_io_init (conn)) - { - free (conn); - return 0; - } - conn->servername = (char *) (conn + 1); - conn->fs_conn_state = FS_CONN_UNCONNECTED; - conn->fs_fd = -1; - strcpy (conn->servername, servername); - return conn; -} - -static void -_fs_free_conn (FSFpePtr conn) -{ - _fs_close_server (conn); - _fs_io_fini (conn); - if (conn->alts) - free (conn->alts); - free (conn); -} - -/* - * called at server init time - */ - -void -fs_register_fpe_functions(void) -{ - RegisterFPEFunctions(fs_name_check, - fs_init_fpe, - fs_free_fpe, - fs_reset_fpe, - fs_open_font, - fs_close_font, - fs_list_fonts, - fs_start_list_with_info, - fs_next_list_with_info, - fs_wakeup, - fs_client_died, - _fs_load_glyphs, - NULL, - NULL, - NULL); -} +/*
+
+Copyright 1990, 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.
+
+*/
+
+/*
+ * Copyright 1990 Network Computing Devices
+ *
+ * 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, and that the names of Network Computing Devices, or Digital
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ *
+ * NETWORK COMPUTING DEVICES, AND DIGITAL AND DISCLAIM ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES,
+ * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ * THIS SOFTWARE.
+ *
+ * Author: Dave Lemke, Network Computing Devices, Inc
+ */
+/*
+ * font server specific font access
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef WIN32
+#define _WILLWINSOCK_
+#endif
+#define FONT_t
+#define TRANS_CLIENT
+#include "X11/Xtrans/Xtrans.h"
+#include "X11/Xpoll.h"
+#include <X11/fonts/FS.h>
+#include <X11/fonts/FSproto.h>
+#include <X11/X.h>
+#include <X11/Xos.h>
+#include <X11/fonts/fontmisc.h>
+#include <X11/fonts/fontstruct.h>
+#include "fservestr.h"
+#include <X11/fonts/fontutil.h>
+#include <errno.h>
+
+#include <time.h>
+#define Time_t time_t
+
+#ifdef NCD
+#include <ncd/nvram.h>
+#endif
+
+#include <stddef.h>
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+#define TimeCmp(a,c,b) ((int) ((a) - (b)) c 0)
+
+#define NONZEROMETRICS(pci) ((pci)->leftSideBearing || \
+ (pci)->rightSideBearing || \
+ (pci)->ascent || \
+ (pci)->descent || \
+ (pci)->characterWidth)
+
+extern void ErrorF(const char *f, ...);
+
+static int fs_read_glyphs ( FontPathElementPtr fpe, FSBlockDataPtr blockrec );
+static int fs_read_list ( FontPathElementPtr fpe, FSBlockDataPtr blockrec );
+static int fs_read_list_info ( FontPathElementPtr fpe,
+ FSBlockDataPtr blockrec );
+
+extern fd_set _fs_fd_mask;
+
+static void fs_block_handler ( pointer data, OSTimePtr wt,
+ pointer LastSelectMask );
+static int fs_wakeup ( FontPathElementPtr fpe, unsigned long *mask );
+
+/*
+ * List of all FPEs
+ */
+static FSFpePtr fs_fpes;
+/*
+ * Union of all FPE blockStates
+ */
+static CARD32 fs_blockState;
+
+static int _fs_restart_connection ( FSFpePtr conn );
+static void fs_send_query_bitmaps ( FontPathElementPtr fpe,
+ FSBlockDataPtr blockrec );
+static int fs_send_close_font ( FontPathElementPtr fpe, Font id );
+static void fs_client_died ( pointer client, FontPathElementPtr fpe );
+static void _fs_client_access ( FSFpePtr conn, pointer client, Bool sync );
+static void _fs_client_resolution ( FSFpePtr conn );
+static fsGenericReply *fs_get_reply (FSFpePtr conn, int *error);
+static int fs_await_reply (FSFpePtr conn);
+static void _fs_do_blocked (FSFpePtr conn);
+static void fs_cleanup_bfont (FSBlockedFontPtr bfont);
+
+char _fs_glyph_undefined;
+char _fs_glyph_requested;
+static char _fs_glyph_zero_length;
+
+static int generationCount;
+
+static int FontServerRequestTimeout = 30 * 1000;
+
+static void
+_fs_close_server (FSFpePtr conn);
+
+static FSFpePtr
+_fs_init_conn (char *servername);
+
+static int
+_fs_wait_connect (FSFpePtr conn);
+
+static int
+_fs_send_init_packets (FSFpePtr conn);
+
+static void
+_fs_check_reconnect (FSFpePtr conn);
+
+static void
+_fs_start_reconnect (FSFpePtr conn);
+
+static void
+_fs_free_conn (FSFpePtr conn);
+
+static int
+fs_free_fpe(FontPathElementPtr fpe);
+
+/*
+ * Font server access
+ *
+ * the basic idea for the non-blocking access is to have the function
+ * called multiple times until the actual data is returned, instead
+ * of ClientBlocked.
+ *
+ * the first call to the function will cause the request to be sent to
+ * the font server, and a block record to be stored in the fpe's list
+ * of outstanding requests. the FS block handler also sticks the
+ * proper set of fd's into the select mask. when data is ready to be
+ * read in, the FS wakup handler will be hit. this will read the
+ * data off the wire into the proper block record, and then signal the
+ * client that caused the block so that it can restart. it will then
+ * call the access function again, which will realize that the data has
+ * arrived and return it.
+ */
+
+
+#ifdef DEBUG
+static void
+_fs_add_req_log(FSFpePtr conn, int opcode)
+{
+ conn->current_seq++;
+ fprintf (stderr, "\t\tRequest: %5d Opcode: %2d\n",
+ conn->current_seq, opcode);
+ conn->reqbuffer[conn->reqindex].opcode = opcode;
+ conn->reqbuffer[conn->reqindex].sequence = conn->current_seq;
+ conn->reqindex++;
+ if (conn->reqindex == REQUEST_LOG_SIZE)
+ conn->reqindex = 0;
+}
+
+static void
+_fs_add_rep_log (FSFpePtr conn, fsGenericReply *rep)
+{
+ int i;
+
+ for (i = 0; i < REQUEST_LOG_SIZE; i++)
+ if (conn->reqbuffer[i].sequence == rep->sequenceNumber)
+ break;
+ if (i == REQUEST_LOG_SIZE)
+ fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: unknown\n",
+ rep->sequenceNumber);
+ else
+ fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: %d\n",
+ rep->sequenceNumber,
+ conn->reqbuffer[i].opcode);
+}
+#else
+#define _fs_add_req_log(conn,op) ((conn)->current_seq++)
+#define _fs_add_rep_log(conn,rep)
+#endif
+
+static Bool
+fs_name_check(char *name)
+{
+ /* Just make sure there is a protocol/ prefix */
+ return (name && *name != '/' && strchr(name, '/'));
+}
+
+static void
+_fs_client_resolution(FSFpePtr conn)
+{
+ fsSetResolutionReq srreq;
+ int num_res;
+ FontResolutionPtr res;
+
+ res = GetClientResolutions(&num_res);
+
+ if (num_res) {
+ srreq.reqType = FS_SetResolution;
+ srreq.num_resolutions = num_res;
+ srreq.length = (SIZEOF(fsSetResolutionReq) +
+ (num_res * SIZEOF(fsResolution)) + 3) >> 2;
+
+ _fs_add_req_log(conn, FS_SetResolution);
+ if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != -1)
+ (void)_fs_write_pad(conn, (char *) res,
+ (num_res * SIZEOF(fsResolution)));
+ }
+}
+
+/*
+ * close font server and remove any state associated with
+ * this connection - this includes any client records.
+ */
+
+static void
+fs_close_conn(FSFpePtr conn)
+{
+ FSClientPtr client, nclient;
+
+ _fs_close_server (conn);
+
+ for (client = conn->clients; client; client = nclient)
+ {
+ nclient = client->next;
+ free (client);
+ }
+ conn->clients = NULL;
+}
+
+/*
+ * the wakeup handlers have to be set when the FPE is open, and not
+ * removed until it is freed, in order to handle unexpected data, like
+ * events
+ */
+/* ARGSUSED */
+static int
+fs_init_fpe(FontPathElementPtr fpe)
+{
+ FSFpePtr conn;
+ char *name;
+ int err;
+ int ret;
+
+ /* open font server */
+ /* create FS specific fpe info */
+ name = fpe->name;
+
+ /* hack for old style names */
+ if (*name == ':')
+ name++; /* skip ':' */
+
+ conn = _fs_init_conn (name);
+ if (!conn)
+ err = AllocError;
+ else
+ {
+ err = init_fs_handlers (fpe, fs_block_handler);
+ if (err != Successful)
+ {
+ _fs_free_conn (conn);
+ err = AllocError;
+ }
+ else
+ {
+ fpe->private = conn;
+ conn->next = fs_fpes;
+ fs_fpes = conn;
+ ret = _fs_wait_connect (conn);
+ if (ret != FSIO_READY)
+ {
+ fs_free_fpe (fpe);
+ err = BadFontPath;
+ }
+ else
+ err = Successful;
+ }
+ }
+
+ if (err == Successful)
+ {
+#ifdef NCD
+ if (configData.ExtendedFontDiags)
+ printf("Connected to font server \"%s\"\n", name);
+#endif
+#ifdef DEBUG
+ fprintf (stderr, "connected to FS \"%s\"\n", name);
+#endif
+ }
+ else
+ {
+#ifdef DEBUG
+ fprintf(stderr, "failed to connect to FS \"%s\" %d\n", name, err);
+#endif
+#ifdef NCD
+ if (configData.ExtendedFontDiags)
+ printf("Failed to connect to font server \"%s\"\n", name);
+#endif
+ ;
+ }
+ return err;
+}
+
+static int
+fs_reset_fpe(FontPathElementPtr fpe)
+{
+ (void) _fs_send_init_packets((FSFpePtr) fpe->private);
+ return Successful;
+}
+
+/*
+ * this shouldn't be called till all refs to the FPE are gone
+ */
+
+static int
+fs_free_fpe(FontPathElementPtr fpe)
+{
+ FSFpePtr conn = (FSFpePtr) fpe->private, *prev;
+
+ /* unhook from chain of all font servers */
+ for (prev = &fs_fpes; *prev; prev = &(*prev)->next)
+ {
+ if (*prev == conn)
+ {
+ *prev = conn->next;
+ break;
+ }
+ }
+ _fs_unmark_block (conn, conn->blockState);
+ fs_close_conn(conn);
+ remove_fs_handlers(fpe, fs_block_handler, fs_fpes == 0);
+ _fs_free_conn (conn);
+ fpe->private = (pointer) 0;
+
+#ifdef NCD
+ if (configData.ExtendedFontDiags)
+ printf("Disconnected from font server \"%s\"\n", fpe->name);
+#endif
+#ifdef DEBUG
+ fprintf (stderr, "disconnect from FS \"%s\"\n", fpe->name);
+#endif
+
+ return Successful;
+}
+
+static FSBlockDataPtr
+fs_new_block_rec(FontPathElementPtr fpe, pointer client, int type)
+{
+ FSBlockDataPtr blockrec,
+ *prev;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ int size;
+
+ switch (type) {
+ case FS_OPEN_FONT:
+ size = sizeof(FSBlockedFontRec);
+ break;
+ case FS_LOAD_GLYPHS:
+ size = sizeof(FSBlockedGlyphRec);
+ break;
+ case FS_LIST_FONTS:
+ size = sizeof(FSBlockedListRec);
+ break;
+ case FS_LIST_WITH_INFO:
+ size = sizeof(FSBlockedListInfoRec);
+ break;
+ default:
+ size = 0;
+ break;
+ }
+ blockrec = malloc(sizeof(FSBlockDataRec) + size);
+ if (!blockrec)
+ return (FSBlockDataPtr) 0;
+ blockrec->data = (pointer) (blockrec + 1);
+ blockrec->client = client;
+ blockrec->sequenceNumber = -1;
+ blockrec->errcode = StillWorking;
+ blockrec->type = type;
+ blockrec->depending = 0;
+ blockrec->next = (FSBlockDataPtr) 0;
+
+ /* stick it on the end of the list (since its expected last) */
+ for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next)
+ ;
+ *prev = blockrec;
+
+ return blockrec;
+}
+
+static void
+_fs_set_pending_reply (FSFpePtr conn)
+{
+ FSBlockDataPtr blockrec;
+
+ for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
+ if (blockrec->errcode == StillWorking)
+ break;
+ if (blockrec)
+ {
+ conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout;
+ _fs_mark_block (conn, FS_PENDING_REPLY);
+ }
+ else
+ _fs_unmark_block (conn, FS_PENDING_REPLY);
+}
+
+static void
+_fs_remove_block_rec(FSFpePtr conn, FSBlockDataPtr blockrec)
+{
+ FSBlockDataPtr *prev;
+
+ for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next)
+ if (*prev == blockrec)
+ {
+ *prev = blockrec->next;
+ break;
+ }
+ if (blockrec->type == FS_LOAD_GLYPHS)
+ {
+ FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data;
+ if (bglyph->num_expected_ranges)
+ free(bglyph->expected_ranges);
+ }
+ free(blockrec);
+ _fs_set_pending_reply (conn);
+}
+
+static void
+_fs_signal_clients_depending(FSClientsDependingPtr *clients_depending)
+{
+ FSClientsDependingPtr p;
+
+ while ((p = *clients_depending))
+ {
+ *clients_depending = p->next;
+ ClientSignal(p->client);
+ free(p);
+ }
+}
+
+static int
+_fs_add_clients_depending(FSClientsDependingPtr *clients_depending, pointer client)
+{
+ FSClientsDependingPtr new, cd;
+
+ for (; (cd = *clients_depending);
+ clients_depending = &(*clients_depending)->next)
+ {
+ if (cd->client == client)
+ return Suspended;
+ }
+
+ new = malloc (sizeof (FSClientsDependingRec));
+ if (!new)
+ return BadAlloc;
+
+ new->client = client;
+ new->next = 0;
+ *clients_depending = new;
+ return Suspended;
+}
+
+/*
+ * When a request is aborted due to a font server failure,
+ * signal any depending clients to restart their dependant
+ * requests
+ */
+static void
+_fs_clean_aborted_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec)
+{
+ switch(blockrec->type) {
+ case FS_OPEN_FONT: {
+ FSBlockedFontPtr bfont = (FSBlockedFontPtr)blockrec->data;
+
+ fs_cleanup_bfont (bfont);
+ _fs_signal_clients_depending(&bfont->clients_depending);
+ break;
+ }
+ case FS_LOAD_GLYPHS: {
+ FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data;
+
+ _fs_clean_aborted_loadglyphs(bglyph->pfont,
+ bglyph->num_expected_ranges,
+ bglyph->expected_ranges);
+ _fs_signal_clients_depending(&bglyph->clients_depending);
+ break;
+ }
+ case FS_LIST_FONTS:
+ break;
+ case FS_LIST_WITH_INFO: {
+ FSBlockedListInfoPtr binfo;
+ binfo = (FSBlockedListInfoPtr) blockrec->data;
+ if (binfo->status == FS_LFWI_REPLY)
+ FD_SET(conn->fs_fd, &_fs_fd_mask);
+ _fs_free_props (&binfo->info);
+ }
+ default:
+ break;
+ }
+}
+
+static void
+fs_abort_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec)
+{
+ _fs_clean_aborted_blockrec (conn, blockrec);
+ _fs_remove_block_rec (conn, blockrec);
+}
+
+/*
+ * Tell the font server we've failed to complete an open and
+ * then unload the partially created font
+ */
+static void
+fs_cleanup_bfont (FSBlockedFontPtr bfont)
+{
+ FSFontDataRec *fsd;
+
+ if (bfont->pfont)
+ {
+ fsd = (FSFontDataRec *) bfont->pfont->fpePrivate;
+
+ /* make sure the FS knows we choked on it */
+ fs_send_close_font(bfont->pfont->fpe, bfont->fontid);
+
+ /*
+ * Either unload the font if it's being opened for
+ * the first time, or smash the generation field to
+ * mark this font as an orphan
+ */
+ if (!(bfont->flags & FontReopen))
+ {
+ if (bfont->freeFont)
+ (*bfont->pfont->unload_font) (bfont->pfont);
+#ifdef DEBUG
+ else
+ fprintf (stderr, "Not freeing other font in cleanup_bfont\n");
+#endif
+ bfont->pfont = 0;
+ }
+ else
+ fsd->generation = -1;
+ }
+}
+
+/*
+ * Check to see if a complete reply is waiting
+ */
+static fsGenericReply *
+fs_get_reply (FSFpePtr conn, int *error)
+{
+ char *buf;
+ fsGenericReply *rep;
+ int ret;
+
+ /* block if the connection is down or paused in lfwi */
+ if (conn->fs_fd == -1 || !FD_ISSET (conn->fs_fd, &_fs_fd_mask))
+ {
+ *error = FSIO_BLOCK;
+ return 0;
+ }
+
+ ret = _fs_start_read (conn, sizeof (fsGenericReply), &buf);
+ if (ret != FSIO_READY)
+ {
+ *error = FSIO_BLOCK;
+ return 0;
+ }
+
+ rep = (fsGenericReply *) buf;
+
+ ret = _fs_start_read (conn, rep->length << 2, &buf);
+ if (ret != FSIO_READY)
+ {
+ *error = FSIO_BLOCK;
+ return 0;
+ }
+
+ *error = FSIO_READY;
+
+ return (fsGenericReply *) buf;
+}
+
+static Bool
+fs_reply_ready (FSFpePtr conn)
+{
+ fsGenericReply *rep;
+
+ if (conn->fs_fd == -1 || !FD_ISSET (conn->fs_fd, &_fs_fd_mask))
+ return FALSE;
+ if (fs_data_read (conn) < sizeof (fsGenericReply))
+ return FALSE;
+ rep = (fsGenericReply *) (conn->inBuf.buf + conn->inBuf.remove);
+ if (fs_data_read (conn) < rep->length << 2)
+ return FALSE;
+ return TRUE;
+}
+
+static void
+_fs_pending_reply (FSFpePtr conn)
+{
+ if (!(conn->blockState & FS_PENDING_REPLY))
+ {
+ _fs_mark_block (conn, FS_PENDING_REPLY);
+ conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout;
+ }
+}
+
+static void
+_fs_prepare_for_reply (FSFpePtr conn)
+{
+ _fs_pending_reply (conn);
+ _fs_flush (conn);
+}
+
+/*
+ * Block (for a while) awaiting a complete reply
+ */
+static int
+fs_await_reply (FSFpePtr conn)
+{
+ int ret;
+
+ if (conn->blockState & FS_COMPLETE_REPLY)
+ return FSIO_READY;
+
+ while (!fs_get_reply (conn, &ret))
+ {
+ if (ret != FSIO_BLOCK)
+ return ret;
+ if (_fs_wait_for_readable (conn, FontServerRequestTimeout) != FSIO_READY)
+ {
+ _fs_connection_died (conn);
+ return FSIO_ERROR;
+ }
+ }
+ return FSIO_READY;
+}
+
+/*
+ * Process the reply to an OpenBitmapFont request
+ */
+static int
+fs_read_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
+{
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
+ fsOpenBitmapFontReply *rep;
+ FSBlockDataPtr blockOrig;
+ FSBlockedFontPtr origBfont;
+ int ret;
+
+ rep = (fsOpenBitmapFontReply *) fs_get_reply (conn, &ret);
+ if (!rep || rep->type == FS_Error)
+ {
+ if (ret == FSIO_BLOCK)
+ return StillWorking;
+ if (rep)
+ _fs_done_read (conn, rep->length << 2);
+ fs_cleanup_bfont (bfont);
+ return BadFontName;
+ }
+
+ /* If we're not reopening a font and FS detected a duplicate font
+ open request, replace our reference to the new font with a
+ reference to an existing font (possibly one not finished
+ opening). If this is a reopen, keep the new font reference...
+ it's got the metrics and extents we read when the font was opened
+ before. This also gives us the freedom to easily close the font
+ if we we decide (in fs_read_query_info()) that we don't like what
+ we got. */
+
+ if (rep->otherid && !(bfont->flags & FontReopen))
+ {
+ fs_cleanup_bfont (bfont);
+
+ /* Find old font if we're completely done getting it from server. */
+ bfont->pfont = find_old_font(rep->otherid);
+ bfont->freeFont = FALSE;
+ bfont->fontid = rep->otherid;
+ bfont->state = FS_DONE_REPLY;
+ /*
+ * look for a blocked request to open the same font
+ */
+ for (blockOrig = conn->blockedRequests;
+ blockOrig;
+ blockOrig = blockOrig->next)
+ {
+ if (blockOrig != blockrec && blockOrig->type == FS_OPEN_FONT)
+ {
+ origBfont = (FSBlockedFontPtr) blockOrig->data;
+ if (origBfont->fontid == rep->otherid)
+ {
+ blockrec->depending = blockOrig->depending;
+ blockOrig->depending = blockrec;
+ bfont->state = FS_DEPENDING;
+ bfont->pfont = origBfont->pfont;
+ break;
+ }
+ }
+ }
+ if (bfont->pfont == NULL)
+ {
+ /* XXX - something nasty happened */
+ ret = BadFontName;
+ }
+ else
+ ret = AccessDone;
+ }
+ else
+ {
+ bfont->pfont->info.cachable = rep->cachable != 0;
+ bfont->state = FS_INFO_REPLY;
+ /*
+ * Reset the blockrec for the next reply
+ */
+ blockrec->sequenceNumber = bfont->queryInfoSequence;
+ conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout;
+ ret = StillWorking;
+ }
+ _fs_done_read (conn, rep->length << 2);
+ return ret;
+}
+
+static Bool
+fs_fonts_match (FontInfoPtr pInfo1, FontInfoPtr pInfo2)
+{
+ int i;
+
+ if (pInfo1->firstCol != pInfo2->firstCol ||
+ pInfo1->lastCol != pInfo2->lastCol ||
+ pInfo1->firstRow != pInfo2->firstRow ||
+ pInfo1->lastRow != pInfo2->lastRow ||
+ pInfo1->defaultCh != pInfo2->defaultCh ||
+ pInfo1->noOverlap != pInfo2->noOverlap ||
+ pInfo1->terminalFont != pInfo2->terminalFont ||
+ pInfo1->constantMetrics != pInfo2->constantMetrics ||
+ pInfo1->constantWidth != pInfo2->constantWidth ||
+ pInfo1->inkInside != pInfo2->inkInside ||
+ pInfo1->inkMetrics != pInfo2->inkMetrics ||
+ pInfo1->allExist != pInfo2->allExist ||
+ pInfo1->drawDirection != pInfo2->drawDirection ||
+ pInfo1->cachable != pInfo2->cachable ||
+ pInfo1->anamorphic != pInfo2->anamorphic ||
+ pInfo1->maxOverlap != pInfo2->maxOverlap ||
+ pInfo1->fontAscent != pInfo2->fontAscent ||
+ pInfo1->fontDescent != pInfo2->fontDescent ||
+ pInfo1->nprops != pInfo2->nprops)
+ return FALSE;
+
+#define MATCH(xci1, xci2) \
+ (((xci1).leftSideBearing == (xci2).leftSideBearing) && \
+ ((xci1).rightSideBearing == (xci2).rightSideBearing) && \
+ ((xci1).characterWidth == (xci2).characterWidth) && \
+ ((xci1).ascent == (xci2).ascent) && \
+ ((xci1).descent == (xci2).descent) && \
+ ((xci1).attributes == (xci2).attributes))
+
+ if (!MATCH(pInfo1->maxbounds, pInfo2->maxbounds) ||
+ !MATCH(pInfo1->minbounds, pInfo2->minbounds) ||
+ !MATCH(pInfo1->ink_maxbounds, pInfo2->ink_maxbounds) ||
+ !MATCH(pInfo1->ink_minbounds, pInfo2->ink_minbounds))
+ return FALSE;
+
+#undef MATCH
+
+ for (i = 0; i < pInfo1->nprops; i++)
+ if (pInfo1->isStringProp[i] !=
+ pInfo2->isStringProp[i] ||
+ pInfo1->props[i].name !=
+ pInfo2->props[i].name ||
+ pInfo1->props[i].value !=
+ pInfo2->props[i].value)
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static int
+fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
+{
+ FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ fsQueryXInfoReply *rep;
+ char *buf;
+ fsPropInfo *pi;
+ fsPropOffset *po;
+ pointer pd;
+ FontInfoPtr pInfo;
+ FontInfoRec tempInfo;
+ int err;
+ int ret;
+
+ rep = (fsQueryXInfoReply *) fs_get_reply (conn, &ret);
+ if (!rep || rep->type == FS_Error)
+ {
+ if (ret == FSIO_BLOCK)
+ return StillWorking;
+ if (rep)
+ _fs_done_read (conn, rep->length << 2);
+ fs_cleanup_bfont (bfont);
+ return BadFontName;
+ }
+
+ /* If this is a reopen, accumulate the query info into a dummy
+ font and compare to our original data. */
+ if (bfont->flags & FontReopen)
+ pInfo = &tempInfo;
+ else
+ pInfo = &bfont->pfont->info;
+
+ buf = (char *) rep;
+ buf += SIZEOF(fsQueryXInfoReply);
+
+ /* move the data over */
+ fsUnpack_XFontInfoHeader(rep, pInfo);
+
+ /* compute accelerators */
+ _fs_init_fontinfo(conn, pInfo);
+
+ /* Compute offsets into the reply */
+ pi = (fsPropInfo *) buf;
+ buf += SIZEOF (fsPropInfo);
+
+ po = (fsPropOffset *) buf;
+ buf += pi->num_offsets * SIZEOF(fsPropOffset);
+
+ pd = (pointer) buf;
+ buf += pi->data_len;
+
+ /* convert the properties and step over the reply */
+ ret = _fs_convert_props(pi, po, pd, pInfo);
+ _fs_done_read (conn, rep->length << 2);
+
+ if (ret == -1)
+ {
+ fs_cleanup_bfont (bfont);
+ return AllocError;
+ }
+
+ if (bfont->flags & FontReopen)
+ {
+ /* We're reopening a font that we lost because of a downed
+ connection. In the interest of avoiding corruption from
+ opening a different font than the old one (we already have
+ its metrics, extents, and probably some of its glyphs),
+ verify that the metrics and properties all match. */
+
+ if (fs_fonts_match (pInfo, &bfont->pfont->info))
+ {
+ err = Successful;
+ bfont->state = FS_DONE_REPLY;
+ }
+ else
+ {
+ fs_cleanup_bfont (bfont);
+ err = BadFontName;
+ }
+ _fs_free_props (pInfo);
+
+ return err;
+ }
+
+ /*
+ * Ask for terminal format fonts if possible
+ */
+ if (bfont->pfont->info.terminalFont)
+ bfont->format = ((bfont->format & ~ (BitmapFormatImageRectMask)) |
+ BitmapFormatImageRectMax);
+
+ /*
+ * Figure out if the whole font should get loaded right now.
+ */
+ if (glyphCachingMode == CACHING_OFF ||
+ (glyphCachingMode == CACHE_16_BIT_GLYPHS
+ && !bfont->pfont->info.lastRow))
+ {
+ bfont->flags |= FontLoadAll;
+ }
+
+ /*
+ * Ready to send the query bitmaps; the terminal font bit has
+ * been computed and glyphCaching has been considered
+ */
+ if (bfont->flags & FontLoadBitmaps)
+ {
+ fs_send_query_bitmaps (fpe, blockrec);
+ _fs_flush (conn);
+ }
+
+ bfont->state = FS_EXTENT_REPLY;
+
+ /*
+ * Reset the blockrec for the next reply
+ */
+ blockrec->sequenceNumber = bfont->queryExtentsSequence;
+ conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout;
+
+ return StillWorking;
+}
+
+static int
+fs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
+{
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
+ FSFontDataPtr fsd = (FSFontDataPtr) bfont->pfont->fpePrivate;
+ FSFontPtr fsfont = (FSFontPtr) bfont->pfont->fontPrivate;
+ fsQueryXExtents16Reply *rep;
+ char *buf;
+ int i;
+ int numExtents;
+ int numInfos;
+ int ret;
+ Bool haveInk = FALSE; /* need separate ink metrics? */
+ CharInfoPtr ci, pCI;
+ char *fsci;
+ fsXCharInfo fscilocal;
+ FontInfoRec *fi = &bfont->pfont->info;
+
+ rep = (fsQueryXExtents16Reply *) fs_get_reply (conn, &ret);
+ if (!rep || rep->type == FS_Error)
+ {
+ if (ret == FSIO_BLOCK)
+ return StillWorking;
+ if (rep)
+ _fs_done_read (conn, rep->length << 2);
+ fs_cleanup_bfont (bfont);
+ return BadFontName;
+ }
+
+ /* move the data over */
+ /* need separate inkMetrics for fixed font server protocol version */
+ numExtents = rep->num_extents;
+ numInfos = numExtents;
+ if (bfont->pfont->info.terminalFont && conn->fsMajorVersion > 1)
+ {
+ numInfos *= 2;
+ haveInk = TRUE;
+ }
+ ci = pCI = malloc(sizeof(CharInfoRec) * numInfos);
+
+ if (!pCI)
+ {
+ _fs_done_read (conn, rep->length << 2);
+ fs_cleanup_bfont(bfont);
+ return AllocError;
+ }
+ fsfont->encoding = pCI;
+ if (haveInk)
+ fsfont->inkMetrics = pCI + numExtents;
+ else
+ fsfont->inkMetrics = pCI;
+
+ buf = (char *) rep;
+ buf += SIZEOF (fsQueryXExtents16Reply);
+ fsci = buf;
+
+ fsd->glyphs_to_get = 0;
+ ci = fsfont->inkMetrics;
+ for (i = 0; i < numExtents; i++)
+ {
+ memcpy(&fscilocal, fsci, SIZEOF(fsXCharInfo)); /* align it */
+ _fs_convert_char_info(&fscilocal, &ci->metrics);
+ /* Bounds check. */
+ if (ci->metrics.ascent > fi->maxbounds.ascent)
+ {
+ ErrorF("fserve: warning: %s %s ascent (%d) > maxascent (%d)\n",
+ fpe->name, fsd->name,
+ ci->metrics.ascent, fi->maxbounds.ascent);
+ ci->metrics.ascent = fi->maxbounds.ascent;
+ }
+ if (ci->metrics.descent > fi->maxbounds.descent)
+ {
+ ErrorF("fserve: warning: %s %s descent (%d) > maxdescent (%d)\n",
+ fpe->name, fsd->name,
+ ci->metrics.descent, fi->maxbounds.descent);
+ ci->metrics.descent = fi->maxbounds.descent;
+ }
+ fsci = fsci + SIZEOF(fsXCharInfo);
+ /* Initialize the bits field for later glyph-caching use */
+ if (NONZEROMETRICS(&ci->metrics))
+ {
+ if (!haveInk &&
+ (ci->metrics.leftSideBearing == ci->metrics.rightSideBearing ||
+ ci->metrics.ascent == -ci->metrics.descent))
+ pCI[i].bits = &_fs_glyph_zero_length;
+ else
+ {
+ pCI[i].bits = &_fs_glyph_undefined;
+ fsd->glyphs_to_get++;
+ }
+ }
+ else
+ pCI[i].bits = (char *)0;
+ ci++;
+ }
+
+ /* Done with reply */
+ _fs_done_read (conn, rep->length << 2);
+
+ /* build bitmap metrics, ImageRectMax style */
+ if (haveInk)
+ {
+ CharInfoPtr ii;
+
+ ci = fsfont->encoding;
+ ii = fsfont->inkMetrics;
+ for (i = 0; i < numExtents; i++, ci++, ii++)
+ {
+ if (NONZEROMETRICS(&ii->metrics))
+ {
+ ci->metrics.leftSideBearing = FONT_MIN_LEFT(fi);
+ ci->metrics.rightSideBearing = FONT_MAX_RIGHT(fi);
+ ci->metrics.ascent = FONT_MAX_ASCENT(fi);
+ ci->metrics.descent = FONT_MAX_DESCENT(fi);
+ ci->metrics.characterWidth = FONT_MAX_WIDTH(fi);
+ ci->metrics.attributes = ii->metrics.attributes;
+ }
+ else
+ {
+ ci->metrics = ii->metrics;
+ }
+ /* Bounds check. */
+ if (ci->metrics.ascent > fi->maxbounds.ascent)
+ {
+ ErrorF("fserve: warning: %s %s ascent (%d) "
+ "> maxascent (%d)\n",
+ fpe->name, fsd->name,
+ ci->metrics.ascent, fi->maxbounds.ascent);
+ ci->metrics.ascent = fi->maxbounds.ascent;
+ }
+ if (ci->metrics.descent > fi->maxbounds.descent)
+ {
+ ErrorF("fserve: warning: %s %s descent (%d) "
+ "> maxdescent (%d)\n",
+ fpe->name, fsd->name,
+ ci->metrics.descent, fi->maxbounds.descent);
+ ci->metrics.descent = fi->maxbounds.descent;
+ }
+ }
+ }
+ {
+ unsigned int r, c, numCols, firstCol;
+
+ firstCol = bfont->pfont->info.firstCol;
+ numCols = bfont->pfont->info.lastCol - firstCol + 1;
+ c = bfont->pfont->info.defaultCh;
+ fsfont->pDefault = 0;
+ if (bfont->pfont->info.lastRow)
+ {
+ r = c >> 8;
+ r -= bfont->pfont->info.firstRow;
+ c &= 0xff;
+ c -= firstCol;
+ if (r < bfont->pfont->info.lastRow-bfont->pfont->info.firstRow+1 &&
+ c < numCols)
+ fsfont->pDefault = &pCI[r * numCols + c];
+ }
+ else
+ {
+ c -= firstCol;
+ if (c < numCols)
+ fsfont->pDefault = &pCI[c];
+ }
+ }
+ bfont->state = FS_GLYPHS_REPLY;
+
+ if (bfont->flags & FontLoadBitmaps)
+ {
+ /*
+ * Reset the blockrec for the next reply
+ */
+ blockrec->sequenceNumber = bfont->queryBitmapsSequence;
+ conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout;
+ return StillWorking;
+ }
+ return Successful;
+}
+
+#ifdef DEBUG
+static char *fs_open_states[] = {
+ "OPEN_REPLY ",
+ "INFO_REPLY ",
+ "EXTENT_REPLY",
+ "GLYPHS_REPLY",
+ "DONE_REPLY ",
+ "DEPENDING ",
+};
+#endif
+
+static int
+fs_do_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
+{
+ FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
+ int err;
+
+#ifdef DEBUG
+ fprintf (stderr, "fs_do_open_font state %s %s\n",
+ fs_open_states[bfont->state],
+ ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name);
+#endif
+ err = BadFontName;
+ switch (bfont->state) {
+ case FS_OPEN_REPLY:
+ err = fs_read_open_font(fpe, blockrec);
+ if (err != StillWorking) { /* already loaded, or error */
+ /* if font's already loaded, massage error code */
+ switch (bfont->state) {
+ case FS_DONE_REPLY:
+ err = Successful;
+ break;
+ case FS_DEPENDING:
+ err = StillWorking;
+ break;
+ }
+ }
+ break;
+ case FS_INFO_REPLY:
+ err = fs_read_query_info(fpe, blockrec);
+ break;
+ case FS_EXTENT_REPLY:
+ err = fs_read_extent_info(fpe, blockrec);
+ break;
+ case FS_GLYPHS_REPLY:
+ if (bfont->flags & FontLoadBitmaps)
+ err = fs_read_glyphs(fpe, blockrec);
+ break;
+ case FS_DEPENDING: /* can't happen */
+ default:
+ break;
+ }
+#ifdef DEBUG
+ fprintf (stderr, "fs_do_open_font err %d\n", err);
+#endif
+ if (err != StillWorking)
+ {
+ bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */
+ while ((blockrec = blockrec->depending))
+ {
+ bfont = (FSBlockedFontPtr) blockrec->data;
+ bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */
+ }
+ }
+ return err;
+}
+
+void
+_fs_mark_block (FSFpePtr conn, CARD32 mask)
+{
+ conn->blockState |= mask;
+ fs_blockState |= mask;
+}
+
+void
+_fs_unmark_block (FSFpePtr conn, CARD32 mask)
+{
+ FSFpePtr c;
+
+ if (conn->blockState & mask)
+ {
+ conn->blockState &= ~mask;
+ fs_blockState = 0;
+ for (c = fs_fpes; c; c = c->next)
+ fs_blockState |= c->blockState;
+ }
+}
+
+/* ARGSUSED */
+static void
+fs_block_handler(pointer data, OSTimePtr wt, pointer LastSelectMask)
+{
+ static struct timeval block_timeout;
+ CARD32 now, earliest, wakeup;
+ int soonest;
+ FSFpePtr conn;
+
+ XFD_ORSET((fd_set *)LastSelectMask, (fd_set *)LastSelectMask,
+ &_fs_fd_mask);
+ /*
+ * Flush all pending output
+ */
+ if (fs_blockState & FS_PENDING_WRITE)
+ for (conn = fs_fpes; conn; conn = conn->next)
+ if (conn->blockState & FS_PENDING_WRITE)
+ _fs_flush (conn);
+ /*
+ * Check for any fpe with a complete reply, set sleep time to zero
+ */
+ if (fs_blockState & FS_COMPLETE_REPLY)
+ {
+ block_timeout.tv_sec = 0;
+ block_timeout.tv_usec = 0;
+ if (*wt == NULL)
+ *wt = &block_timeout;
+ else
+ **wt = block_timeout;
+ }
+ /*
+ * Walk through fpe list computing sleep time
+ */
+ else if (fs_blockState & (FS_BROKEN_WRITE|
+ FS_BROKEN_CONNECTION|
+ FS_PENDING_REPLY|
+ FS_RECONNECTING))
+ {
+ now = GetTimeInMillis ();
+ earliest = now + 10000000;
+ for (conn = fs_fpes; conn; conn = conn->next)
+ {
+ if (conn->blockState & FS_RECONNECTING)
+ {
+ wakeup = conn->blockedConnectTime;
+ if (TimeCmp (wakeup, <, earliest))
+ earliest = wakeup;
+ }
+ if (conn->blockState & FS_BROKEN_CONNECTION)
+ {
+ wakeup = conn->brokenConnectionTime;
+ if (TimeCmp (wakeup, <, earliest))
+ earliest = wakeup;
+ }
+ if (conn->blockState & FS_BROKEN_WRITE)
+ {
+ wakeup = conn->brokenWriteTime;
+ if (TimeCmp (wakeup, <, earliest))
+ earliest = wakeup;
+ }
+ if (conn->blockState & FS_PENDING_REPLY)
+ {
+ wakeup = conn->blockedReplyTime;
+ if (TimeCmp (wakeup, <, earliest))
+ earliest = wakeup;
+ }
+ }
+ soonest = earliest - now;
+ if (soonest < 0)
+ soonest = 0;
+ block_timeout.tv_sec = soonest / 1000;
+ block_timeout.tv_usec = (soonest % 1000) * 1000;
+ if (*wt == NULL)
+ *wt = &block_timeout;
+ else if (soonest < (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000)
+ **wt = block_timeout;
+ }
+}
+
+static void
+fs_handle_unexpected(FSFpePtr conn, fsGenericReply *rep)
+{
+ if (rep->type == FS_Event && rep->data1 == KeepAlive)
+ {
+ fsNoopReq req;
+
+ /* ping it back */
+ req.reqType = FS_Noop;
+ req.length = SIZEOF(fsNoopReq) >> 2;
+ _fs_add_req_log(conn, FS_Noop);
+ _fs_write(conn, (char *) &req, SIZEOF(fsNoopReq));
+ }
+ /* this should suck up unexpected replies and events */
+ _fs_done_read (conn, rep->length << 2);
+}
+
+static void
+fs_read_reply (FontPathElementPtr fpe, pointer client)
+{
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ FSBlockDataPtr blockrec;
+ int ret;
+ int err;
+ fsGenericReply *rep;
+
+ if ((rep = fs_get_reply (conn, &ret)))
+ {
+ _fs_add_rep_log (conn, rep);
+ for (blockrec = conn->blockedRequests;
+ blockrec;
+ blockrec = blockrec->next)
+ {
+ if (blockrec->sequenceNumber == rep->sequenceNumber)
+ break;
+ }
+ err = Successful;
+ if (!blockrec)
+ {
+ fs_handle_unexpected(conn, rep);
+ }
+ else
+ {
+ /*
+ * go read it, and if we're done,
+ * wake up the appropriate client
+ */
+ switch (blockrec->type) {
+ case FS_OPEN_FONT:
+ blockrec->errcode = fs_do_open_font(fpe, blockrec);
+ break;
+ case FS_LOAD_GLYPHS:
+ blockrec->errcode = fs_read_glyphs(fpe, blockrec);
+ break;
+ case FS_LIST_FONTS:
+ blockrec->errcode = fs_read_list(fpe, blockrec);
+ break;
+ case FS_LIST_WITH_INFO:
+ blockrec->errcode = fs_read_list_info(fpe, blockrec);
+ break;
+ default:
+ break;
+ }
+ err = blockrec->errcode;
+ if (err != StillWorking)
+ {
+ while (blockrec)
+ {
+ blockrec->errcode = err;
+ if (client != blockrec->client)
+ ClientSignal(blockrec->client);
+ blockrec = blockrec->depending;
+ }
+ _fs_unmark_block (conn, FS_PENDING_REPLY);
+ }
+ }
+ if (fs_reply_ready (conn))
+ _fs_mark_block (conn, FS_COMPLETE_REPLY);
+ else
+ _fs_unmark_block (conn, FS_COMPLETE_REPLY);
+ }
+}
+
+static int
+fs_wakeup(FontPathElementPtr fpe, unsigned long *mask)
+{
+ fd_set *LastSelectMask = (fd_set *) mask;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+
+ /*
+ * Don't continue if the fd is -1 (which will be true when the
+ * font server terminates
+ */
+ if ((conn->blockState & FS_RECONNECTING))
+ _fs_check_reconnect (conn);
+ else if ((conn->blockState & FS_COMPLETE_REPLY) ||
+ (conn->fs_fd != -1 && FD_ISSET(conn->fs_fd, LastSelectMask)))
+ fs_read_reply (fpe, 0);
+ if (conn->blockState & (FS_PENDING_REPLY|FS_BROKEN_CONNECTION|FS_BROKEN_WRITE))
+ _fs_do_blocked (conn);
+#ifdef DEBUG
+ {
+ FSBlockDataPtr blockrec;
+ FSBlockedFontPtr bfont;
+ FSBlockedListPtr blist;
+ static CARD32 lastState;
+ static FSBlockDataPtr lastBlock;
+
+ if (conn->blockState || conn->blockedRequests || lastState || lastBlock)
+ {
+ fprintf (stderr, " Block State 0x%x\n", (int) conn->blockState);
+ lastState = conn->blockState;
+ lastBlock = conn->blockedRequests;
+ }
+ for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
+ {
+ switch (blockrec->type) {
+ case FS_OPEN_FONT:
+ bfont = (FSBlockedFontPtr) blockrec->data;
+ fprintf (stderr, " Blocked font errcode %d sequence %d state %s %s\n",
+ blockrec->errcode,
+ blockrec->sequenceNumber,
+ fs_open_states[bfont->state],
+ bfont->pfont ?
+ ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name :
+ "<freed>");
+ break;
+ case FS_LIST_FONTS:
+ blist = (FSBlockedListPtr) blockrec->data;
+ fprintf (stderr, " Blocked list errcode %d sequence %d\n",
+ blockrec->errcode, blockrec->sequenceNumber);
+ break;
+ default:
+ fprintf (stderr, " Blocked type %d errcode %d sequence %d\n",
+ blockrec->type,
+ blockrec->errcode,
+ blockrec->sequenceNumber);
+ break;
+ }
+ }
+ }
+#endif
+ return FALSE;
+}
+
+/*
+ * Notice a dead connection and prepare for reconnect
+ */
+
+void
+_fs_connection_died(FSFpePtr conn)
+{
+ if (conn->blockState & FS_BROKEN_CONNECTION)
+ return;
+ fs_close_conn(conn);
+ conn->brokenConnectionTime = GetTimeInMillis ();
+ _fs_mark_block (conn, FS_BROKEN_CONNECTION);
+ _fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE|FS_RECONNECTING);
+}
+
+/*
+ * Signal clients that the connection has come back up
+ */
+static int
+_fs_restart_connection(FSFpePtr conn)
+{
+ FSBlockDataPtr block;
+
+ _fs_unmark_block (conn, FS_GIVE_UP);
+ while ((block = (FSBlockDataPtr) conn->blockedRequests))
+ {
+ if (block->errcode == StillWorking)
+ {
+ ClientSignal(block->client);
+ fs_abort_blockrec(conn, block);
+ }
+ }
+ return TRUE;
+}
+
+/*
+ * Declare this font server connection useless
+ */
+static void
+_fs_giveup (FSFpePtr conn)
+{
+ FSBlockDataPtr block;
+
+ if (conn->blockState & FS_GIVE_UP)
+ return;
+#ifdef DEBUG
+ fprintf (stderr, "give up on FS \"%s\"\n", conn->servername);
+#endif
+ _fs_mark_block (conn, FS_GIVE_UP);
+ while ((block = (FSBlockDataPtr) conn->blockedRequests))
+ {
+ if (block->errcode == StillWorking)
+ {
+ ClientSignal (block->client);
+ fs_abort_blockrec (conn, block);
+ }
+ }
+ if (conn->fs_fd >= 0)
+ _fs_connection_died (conn);
+}
+
+static void
+_fs_do_blocked (FSFpePtr conn)
+{
+ CARD32 now;
+
+ now = GetTimeInMillis ();
+ if ((conn->blockState & FS_PENDING_REPLY) &&
+ TimeCmp (conn->blockedReplyTime, <=, now))
+ {
+ _fs_giveup (conn);
+ }
+ else
+ {
+ if (conn->blockState & FS_BROKEN_CONNECTION)
+ {
+ /* Try to reconnect broken connections */
+ if (TimeCmp (conn->brokenConnectionTime, <=, now))
+ _fs_start_reconnect (conn);
+ }
+ else if (conn->blockState & FS_BROKEN_WRITE)
+ {
+ /* Try to flush blocked connections */
+ if (TimeCmp (conn->brokenWriteTime, <=, now))
+ _fs_flush (conn);
+ }
+ }
+}
+
+/*
+ * sends the actual request out
+ */
+/* ARGSUSED */
+static int
+fs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
+ char *name, int namelen,
+ fsBitmapFormat format, fsBitmapFormatMask fmask,
+ XID id, FontPtr *ppfont)
+{
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ FontPtr font;
+ FSBlockDataPtr blockrec = NULL;
+ FSBlockedFontPtr bfont;
+ FSFontDataPtr fsd;
+ fsOpenBitmapFontReq openreq;
+ fsQueryXInfoReq inforeq;
+ fsQueryXExtents16Req extreq;
+ int err;
+ unsigned char buf[1024];
+
+ if (conn->blockState & FS_GIVE_UP)
+ return BadFontName;
+
+ if (namelen <= 0 || namelen > sizeof (buf) - 1)
+ return BadFontName;
+
+ /*
+ * Get the font structure put together, either by reusing
+ * the existing one or creating a new one
+ */
+ if (flags & FontReopen)
+ {
+ Atom nameatom, fn = None;
+ int i;
+
+ font = *ppfont;
+ fsd = (FSFontDataPtr)font->fpePrivate;
+ /* This is an attempt to reopen a font. Did the font have a
+ NAME property? */
+ if ((nameatom = MakeAtom("FONT", 4, 0)) != None)
+ {
+ for (i = 0; i < font->info.nprops; i++)
+ if (font->info.props[i].name == nameatom &&
+ font->info.isStringProp[i])
+ {
+ fn = font->info.props[i].value;
+ break;
+ }
+ }
+ if (fn == None || !(name = NameForAtom(fn)))
+ {
+ name = fsd->name;
+ namelen = fsd->namelen;
+ }
+ else
+ namelen = strlen(name);
+ }
+ else
+ {
+ font = fs_create_font (fpe, name, namelen, format, fmask);
+ if (!font)
+ return AllocError;
+
+ fsd = (FSFontDataPtr)font->fpePrivate;
+ }
+
+ /* make a new block record, and add it to the end of the list */
+ blockrec = fs_new_block_rec(font->fpe, client, FS_OPEN_FONT);
+ if (!blockrec)
+ {
+ if (!(flags & FontReopen))
+ (*font->unload_font) (font);
+ return AllocError;
+ }
+
+ /*
+ * Must check this before generating any protocol, otherwise we'll
+ * mess up a reconnect in progress
+ */
+ if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING))
+ {
+ _fs_pending_reply (conn);
+ return Suspended;
+ }
+
+ fsd->generation = conn->generation;
+
+ bfont = (FSBlockedFontPtr) blockrec->data;
+ bfont->fontid = fsd->fontid;
+ bfont->pfont = font;
+ bfont->state = FS_OPEN_REPLY;
+ bfont->flags = flags;
+ bfont->format = fsd->format;
+ bfont->clients_depending = (FSClientsDependingPtr)0;
+ bfont->freeFont = (flags & FontReopen) == 0;
+
+ _fs_client_access (conn, client, (flags & FontOpenSync) != 0);
+ _fs_client_resolution(conn);
+
+ /* do an FS_OpenFont, FS_QueryXInfo and FS_QueryXExtents */
+ buf[0] = (unsigned char) namelen;
+ memcpy(&buf[1], name, namelen);
+ openreq.reqType = FS_OpenBitmapFont;
+ openreq.pad = 0;
+ openreq.fid = fsd->fontid;
+ openreq.format_hint = fsd->format;
+ openreq.format_mask = fsd->fmask;
+ openreq.length = (SIZEOF(fsOpenBitmapFontReq) + namelen + 4) >> 2;
+
+ _fs_add_req_log(conn, FS_OpenBitmapFont);
+ _fs_write(conn, (char *) &openreq, SIZEOF(fsOpenBitmapFontReq));
+ _fs_write_pad(conn, (char *) buf, namelen + 1);
+
+ blockrec->sequenceNumber = conn->current_seq;
+
+ inforeq.reqType = FS_QueryXInfo;
+ inforeq.pad = 0;
+ inforeq.id = fsd->fontid;
+ inforeq.length = SIZEOF(fsQueryXInfoReq) >> 2;
+
+ bfont->queryInfoSequence = conn->current_seq + 1;
+
+ _fs_add_req_log(conn, FS_QueryXInfo);
+ _fs_write(conn, (char *) &inforeq, SIZEOF(fsQueryXInfoReq));
+
+ if (!(bfont->flags & FontReopen))
+ {
+ extreq.reqType = FS_QueryXExtents16;
+ extreq.range = fsTrue;
+ extreq.fid = fsd->fontid;
+ extreq.num_ranges = 0;
+ extreq.length = SIZEOF(fsQueryXExtents16Req) >> 2;
+
+ bfont->queryExtentsSequence = conn->current_seq + 1;
+
+ _fs_add_req_log(conn, FS_QueryXExtents16);
+ _fs_write(conn, (char *) &extreq, SIZEOF(fsQueryXExtents16Req));
+ }
+
+#ifdef NCD
+ if (configData.ExtendedFontDiags)
+ {
+ memcpy(buf, name, MIN(256, namelen));
+ buf[MIN(256, namelen)] = '\0';
+ printf("Requesting font \"%s\" from font server \"%s\"\n",
+ buf, font->fpe->name);
+ }
+#endif
+ _fs_prepare_for_reply (conn);
+
+ err = blockrec->errcode;
+ if (bfont->flags & FontOpenSync)
+ {
+ while (blockrec->errcode == StillWorking)
+ {
+ if (fs_await_reply (conn) != FSIO_READY)
+ {
+ blockrec->errcode = BadFontName;
+ break;
+ }
+ fs_read_reply (font->fpe, client);
+ }
+ err = blockrec->errcode;
+ if (err == Successful)
+ *ppfont = bfont->pfont;
+ else
+ fs_cleanup_bfont (bfont);
+ bfont->freeFont = FALSE;
+ _fs_remove_block_rec (conn, blockrec);
+ }
+ return err == StillWorking ? Suspended : err;
+}
+
+static void
+fs_send_query_bitmaps(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
+{
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
+ fsQueryXBitmaps16Req bitreq;
+
+ /* send the request */
+ bitreq.reqType = FS_QueryXBitmaps16;
+ bitreq.fid = bfont->fontid;
+ bitreq.format = bfont->format;
+ bitreq.range = TRUE;
+ bitreq.length = SIZEOF(fsQueryXBitmaps16Req) >> 2;
+ bitreq.num_ranges = 0;
+
+ bfont->queryBitmapsSequence = conn->current_seq + 1;
+
+ _fs_add_req_log(conn, FS_QueryXBitmaps16);
+ _fs_write(conn, (char *) &bitreq, SIZEOF(fsQueryXBitmaps16Req));
+}
+
+/* ARGSUSED */
+static int
+fs_open_font(pointer client, FontPathElementPtr fpe, Mask flags,
+ char *name, int namelen,
+ fsBitmapFormat format, fsBitmapFormatMask fmask,
+ XID id, FontPtr *ppfont,
+ char **alias, FontPtr non_cachable_font)
+{
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ FSBlockDataPtr blockrec;
+ FSBlockedFontPtr bfont;
+ int err;
+
+ /* libfont interface expects ImageRectMin glyphs */
+ format = (format & ~BitmapFormatImageRectMask) | BitmapFormatImageRectMin;
+
+ *alias = (char *) 0;
+ for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
+ {
+ if (blockrec->type == FS_OPEN_FONT && blockrec->client == client)
+ {
+ err = blockrec->errcode;
+ if (err == StillWorking)
+ return Suspended;
+
+ bfont = (FSBlockedFontPtr) blockrec->data;
+ if (err == Successful)
+ *ppfont = bfont->pfont;
+ else
+ fs_cleanup_bfont (bfont);
+ _fs_remove_block_rec (conn, blockrec);
+ return err;
+ }
+ }
+ return fs_send_open_font(client, fpe, flags, name, namelen, format, fmask,
+ id, ppfont);
+}
+
+/* ARGSUSED */
+static int
+fs_send_close_font(FontPathElementPtr fpe, Font id)
+{
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ fsCloseReq req;
+
+ if (conn->blockState & FS_GIVE_UP)
+ return Successful;
+ /* tell the font server to close the font */
+ req.reqType = FS_CloseFont;
+ req.pad = 0;
+ req.length = SIZEOF(fsCloseReq) >> 2;
+ req.id = id;
+ _fs_add_req_log(conn, FS_CloseFont);
+ _fs_write(conn, (char *) &req, SIZEOF(fsCloseReq));
+
+ return Successful;
+}
+
+/* ARGSUSED */
+static void
+fs_close_font(FontPathElementPtr fpe, FontPtr pfont)
+{
+ FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+
+ if (conn->generation == fsd->generation)
+ fs_send_close_font(fpe, fsd->fontid);
+
+#ifdef DEBUG
+ {
+ FSBlockDataPtr blockrec;
+ FSBlockedFontPtr bfont;
+
+ for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
+ {
+ if (blockrec->type == FS_OPEN_FONT)
+ {
+ bfont = (FSBlockedFontPtr) blockrec->data;
+ if (bfont->pfont == pfont)
+ fprintf (stderr, "closing font which hasn't been opened\n");
+ }
+ }
+ }
+#endif
+ (*pfont->unload_font) (pfont);
+}
+
+static int
+fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
+{
+ FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr) blockrec->data;
+ FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ FontPtr pfont = bglyph->pfont;
+ /* works for either blocked font
+ or glyph rec... pfont is at
+ the very beginning of both
+ blockrec->data structures */
+ FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate);
+ FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate;
+ FontInfoPtr pfi = &pfont->info;
+ fsQueryXBitmaps16Reply *rep;
+ char *buf;
+ fsOffset32 *ppbits;
+ fsOffset32 local_off;
+ char *off_adr;
+ pointer pbitmaps;
+ char *bits, *allbits;
+#ifdef DEBUG
+ char *origallbits;
+#endif
+ int i,
+ err;
+ int nranges = 0;
+ int ret;
+ fsRange *nextrange = 0;
+ unsigned long minchar, maxchar;
+
+ rep = (fsQueryXBitmaps16Reply *) fs_get_reply (conn, &ret);
+ if (!rep || rep->type == FS_Error)
+ {
+ if (ret == FSIO_BLOCK)
+ return StillWorking;
+ if (rep)
+ _fs_done_read (conn, rep->length << 2);
+ err = AllocError;
+ goto bail;
+ }
+
+ buf = (char *) rep;
+ buf += SIZEOF (fsQueryXBitmaps16Reply);
+
+ ppbits = (fsOffset32 *) buf;
+ buf += SIZEOF (fsOffset32) * (rep->num_chars);
+
+ pbitmaps = (pointer ) buf;
+
+ if (blockrec->type == FS_LOAD_GLYPHS)
+ {
+ nranges = bglyph->num_expected_ranges;
+ nextrange = bglyph->expected_ranges;
+ }
+
+ /* place the incoming glyphs */
+ if (nranges)
+ {
+ /* We're operating under the assumption that the ranges
+ requested in the LoadGlyphs call were all legal for this
+ font, and that individual ranges do not cover multiple
+ rows... fs_build_range() is designed to ensure this. */
+ minchar = (nextrange->min_char_high - pfi->firstRow) *
+ (pfi->lastCol - pfi->firstCol + 1) +
+ nextrange->min_char_low - pfi->firstCol;
+ maxchar = (nextrange->max_char_high - pfi->firstRow) *
+ (pfi->lastCol - pfi->firstCol + 1) +
+ nextrange->max_char_low - pfi->firstCol;
+ nextrange++;
+ }
+ else
+ {
+ minchar = 0;
+ maxchar = rep->num_chars;
+ }
+
+ off_adr = (char *)ppbits;
+
+ allbits = fs_alloc_glyphs (pfont, rep->nbytes);
+
+ if (!allbits)
+ {
+ err = AllocError;
+ goto bail;
+ }
+
+#ifdef DEBUG
+ origallbits = allbits;
+ fprintf (stderr, "Reading %d glyphs in %d bytes for %s\n",
+ (int) rep->num_chars, (int) rep->nbytes, fsd->name);
+#endif
+
+ for (i = 0; i < rep->num_chars; i++)
+ {
+ memcpy(&local_off, off_adr, SIZEOF(fsOffset32)); /* align it */
+ if (blockrec->type == FS_OPEN_FONT ||
+ fsdata->encoding[minchar].bits == &_fs_glyph_requested)
+ {
+ /*
+ * Broken X font server returns bits for missing characters
+ * when font is padded
+ */
+ if (NONZEROMETRICS(&fsdata->encoding[minchar].metrics))
+ {
+ if (local_off.length)
+ {
+ bits = allbits;
+ allbits += local_off.length;
+ memcpy(bits, (char *)pbitmaps + local_off.position,
+ local_off.length);
+ }
+ else
+ bits = &_fs_glyph_zero_length;
+ }
+ else
+ bits = 0;
+ if (fsdata->encoding[minchar].bits == &_fs_glyph_requested)
+ fsd->glyphs_to_get--;
+ fsdata->encoding[minchar].bits = bits;
+ }
+ if (minchar++ == maxchar)
+ {
+ if (!--nranges) break;
+ minchar = (nextrange->min_char_high - pfi->firstRow) *
+ (pfi->lastCol - pfi->firstCol + 1) +
+ nextrange->min_char_low - pfi->firstCol;
+ maxchar = (nextrange->max_char_high - pfi->firstRow) *
+ (pfi->lastCol - pfi->firstCol + 1) +
+ nextrange->max_char_low - pfi->firstCol;
+ nextrange++;
+ }
+ off_adr += SIZEOF(fsOffset32);
+ }
+#ifdef DEBUG
+ fprintf (stderr, "Used %d bytes instead of %d\n",
+ (int) (allbits - origallbits), (int) rep->nbytes);
+#endif
+
+ if (blockrec->type == FS_OPEN_FONT)
+ {
+ fsd->glyphs_to_get = 0;
+ bfont->state = FS_DONE_REPLY;
+ }
+ err = Successful;
+
+bail:
+ _fs_done_read (conn, rep->length << 2);
+ return err;
+}
+
+static int
+fs_send_load_glyphs(pointer client, FontPtr pfont,
+ int nranges, fsRange *ranges)
+{
+ FontPathElementPtr fpe = pfont->fpe;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ FSBlockedGlyphPtr blockedglyph;
+ fsQueryXBitmaps16Req req;
+ FSBlockDataPtr blockrec;
+
+ if (conn->blockState & FS_GIVE_UP)
+ return BadCharRange;
+
+ /* make a new block record, and add it to the end of the list */
+ blockrec = fs_new_block_rec(fpe, client, FS_LOAD_GLYPHS);
+ if (!blockrec)
+ return AllocError;
+ blockedglyph = (FSBlockedGlyphPtr) blockrec->data;
+ blockedglyph->pfont = pfont;
+ blockedglyph->num_expected_ranges = nranges;
+ /* Assumption: it's our job to free ranges */
+ blockedglyph->expected_ranges = ranges;
+ blockedglyph->clients_depending = (FSClientsDependingPtr)0;
+
+ if (conn->blockState & (FS_BROKEN_CONNECTION|FS_RECONNECTING))
+ {
+ _fs_pending_reply (conn);
+ return Suspended;
+ }
+
+ /* send the request */
+ req.reqType = FS_QueryXBitmaps16;
+ req.fid = ((FSFontDataPtr) pfont->fpePrivate)->fontid;
+ req.format = pfont->format;
+ if (pfont->info.terminalFont)
+ req.format = (req.format & ~(BitmapFormatImageRectMask)) |
+ BitmapFormatImageRectMax;
+ req.range = TRUE;
+ /* each range takes up 4 bytes */
+ req.length = (SIZEOF(fsQueryXBitmaps16Req) >> 2) + nranges;
+ req.num_ranges = nranges * 2; /* protocol wants count of fsChar2bs */
+ _fs_add_req_log(conn, FS_QueryXBitmaps16);
+ _fs_write(conn, (char *) &req, SIZEOF(fsQueryXBitmaps16Req));
+
+ blockrec->sequenceNumber = conn->current_seq;
+
+ /* Send ranges to the server... pack into a char array by hand
+ to avoid structure-packing portability problems and to
+ handle swapping for version1 protocol */
+ if (nranges)
+ {
+#define RANGE_BUFFER_SIZE 64
+#define RANGE_BUFFER_SIZE_MASK 63
+ int i;
+ char range_buffer[RANGE_BUFFER_SIZE * 4];
+ char *range_buffer_p;
+
+ range_buffer_p = range_buffer;
+ for (i = 0; i < nranges;)
+ {
+ if (conn->fsMajorVersion > 1)
+ {
+ *range_buffer_p++ = ranges[i].min_char_high;
+ *range_buffer_p++ = ranges[i].min_char_low;
+ *range_buffer_p++ = ranges[i].max_char_high;
+ *range_buffer_p++ = ranges[i].max_char_low;
+ }
+ else
+ {
+ *range_buffer_p++ = ranges[i].min_char_low;
+ *range_buffer_p++ = ranges[i].min_char_high;
+ *range_buffer_p++ = ranges[i].max_char_low;
+ *range_buffer_p++ = ranges[i].max_char_high;
+ }
+
+ if (!(++i & RANGE_BUFFER_SIZE_MASK))
+ {
+ _fs_write(conn, range_buffer, RANGE_BUFFER_SIZE * 4);
+ range_buffer_p = range_buffer;
+ }
+ }
+ if (i &= RANGE_BUFFER_SIZE_MASK)
+ _fs_write(conn, range_buffer, i * 4);
+ }
+
+ _fs_prepare_for_reply (conn);
+ return Suspended;
+}
+
+
+extern pointer serverClient; /* This could be any number that
+ doesn't conflict with existing
+ client values. */
+
+static int
+_fs_load_glyphs(pointer client, FontPtr pfont, Bool range_flag,
+ unsigned int nchars, int item_size, unsigned char *data)
+{
+ FSFpePtr conn = (FSFpePtr) pfont->fpe->private;
+ int nranges = 0;
+ fsRange *ranges = NULL;
+ int res;
+ FSBlockDataPtr blockrec;
+ FSBlockedGlyphPtr blockedglyph;
+ FSClientsDependingPtr *clients_depending = NULL;
+ int err;
+
+ /* see if the result is already there */
+ for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
+ {
+ if (blockrec->type == FS_LOAD_GLYPHS)
+ {
+ blockedglyph = (FSBlockedGlyphPtr) blockrec->data;
+ if (blockedglyph->pfont == pfont)
+ {
+ /* Look for this request */
+ if (blockrec->client == client)
+ {
+ err = blockrec->errcode;
+ if (err == StillWorking)
+ return Suspended;
+ _fs_signal_clients_depending(&blockedglyph->clients_depending);
+ _fs_remove_block_rec(conn, blockrec);
+ return err;
+ }
+ /* We've found an existing LoadGlyphs blockrec for this
+ font but for another client. Rather than build a
+ blockrec for it now (which entails some complex
+ maintenance), we'll add it to a queue of clients to
+ be signalled when the existing LoadGlyphs is
+ completed. */
+ clients_depending = &blockedglyph->clients_depending;
+ break;
+ }
+ }
+ else if (blockrec->type == FS_OPEN_FONT)
+ {
+ FSBlockedFontPtr bfont;
+ bfont = (FSBlockedFontPtr) blockrec->data;
+ if (bfont->pfont == pfont)
+ {
+ /*
+ * An OpenFont is pending for this font, this must
+ * be from a reopen attempt, so finish the open
+ * attempt and retry the LoadGlyphs
+ */
+ if (blockrec->client == client)
+ {
+ err = blockrec->errcode;
+ if (err == StillWorking)
+ return Suspended;
+
+ _fs_signal_clients_depending(&bfont->clients_depending);
+ _fs_remove_block_rec(conn, blockrec);
+ if (err != Successful)
+ return err;
+ break;
+ }
+ /* We've found an existing OpenFont blockrec for this
+ font but for another client. Rather than build a
+ blockrec for it now (which entails some complex
+ maintenance), we'll add it to a queue of clients to
+ be signalled when the existing OpenFont is
+ completed. */
+ if (blockrec->errcode == StillWorking)
+ {
+ clients_depending = &bfont->clients_depending;
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * see if the desired glyphs already exist, and return Successful if they
+ * do, otherwise build up character range/character string
+ */
+ res = fs_build_range(pfont, range_flag, nchars, item_size, data,
+ &nranges, &ranges);
+
+ switch (res)
+ {
+ case AccessDone:
+ return Successful;
+
+ case Successful:
+ break;
+
+ default:
+ return res;
+ }
+
+ /*
+ * If clients_depending is not null, this request must wait for
+ * some prior request(s) to complete.
+ */
+ if (clients_depending)
+ {
+ /* Since we're not ready to send the load_glyphs request yet,
+ clean up the damage (if any) caused by the fs_build_range()
+ call. */
+ if (nranges)
+ {
+ _fs_clean_aborted_loadglyphs(pfont, nranges, ranges);
+ free(ranges);
+ }
+ return _fs_add_clients_depending(clients_depending, client);
+ }
+
+ /*
+ * If fsd->generation != conn->generation, the font has been closed
+ * due to a lost connection. We will reopen it, which will result
+ * in one of three things happening:
+ * 1) The open will succeed and obtain the same font. Life
+ * is wonderful.
+ * 2) The open will fail. There is code above to recognize this
+ * and flunk the LoadGlyphs request. The client might not be
+ * thrilled.
+ * 3) Worst case: the open will succeed but the font we open will
+ * be different. The fs_read_query_info() procedure attempts
+ * to detect this by comparing the existing metrics and
+ * properties against those of the reopened font... if they
+ * don't match, we flunk the reopen, which eventually results
+ * in flunking the LoadGlyphs request. We could go a step
+ * further and compare the extents, but this should be
+ * sufficient.
+ */
+ if (((FSFontDataPtr)pfont->fpePrivate)->generation != conn->generation)
+ {
+ /* Since we're not ready to send the load_glyphs request yet,
+ clean up the damage caused by the fs_build_range() call. */
+ _fs_clean_aborted_loadglyphs(pfont, nranges, ranges);
+ free(ranges);
+
+ /* Now try to reopen the font. */
+ return fs_send_open_font(client, pfont->fpe,
+ (Mask)FontReopen, (char *)0, 0,
+ (fsBitmapFormat)0, (fsBitmapFormatMask)0,
+ (XID)0, &pfont);
+ }
+
+ return fs_send_load_glyphs(client, pfont, nranges, ranges);
+}
+
+int
+fs_load_all_glyphs(FontPtr pfont)
+{
+ int err;
+ FSFpePtr conn = (FSFpePtr) pfont->fpe->private;
+
+ /*
+ * The purpose of this procedure is to load all glyphs in the event
+ * that we're dealing with someone who doesn't understand the finer
+ * points of glyph caching... it is called from _fs_get_glyphs() if
+ * the latter is called to get glyphs that have not yet been loaded.
+ * We assume that the caller will not know how to handle a return
+ * value of Suspended (usually the case for a GetGlyphs() caller),
+ * so this procedure hangs around, freezing the server, for the
+ * request to complete. This is an unpleasant kluge called to
+ * perform an unpleasant job that, we hope, will never be required.
+ */
+
+ while ((err = _fs_load_glyphs(serverClient, pfont, TRUE, 0, 0, NULL)) ==
+ Suspended)
+ {
+ if (fs_await_reply (conn) != FSIO_READY)
+ {
+ /* Get rid of blockrec */
+ fs_client_died(serverClient, pfont->fpe);
+ err = BadCharRange;
+ break;
+ }
+ fs_read_reply (pfont->fpe, serverClient);
+ }
+ return err;
+}
+
+static int
+fs_read_list(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
+{
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ FSBlockedListPtr blist = (FSBlockedListPtr) blockrec->data;
+ fsListFontsReply *rep;
+ char *data;
+ int length,
+ i,
+ ret;
+ int err;
+
+ rep = (fsListFontsReply *) fs_get_reply (conn, &ret);
+ if (!rep || rep->type == FS_Error)
+ {
+ if (ret == FSIO_BLOCK)
+ return StillWorking;
+ if (rep)
+ _fs_done_read (conn, rep->length << 2);
+ return AllocError;
+ }
+ data = (char *) rep + SIZEOF (fsListFontsReply);
+
+ err = Successful;
+ /* copy data into FontPathRecord */
+ for (i = 0; i < rep->nFonts; i++)
+ {
+ length = *(unsigned char *)data++;
+ err = AddFontNamesName(blist->names, data, length);
+ if (err != Successful)
+ break;
+ data += length;
+ }
+ _fs_done_read (conn, rep->length << 2);
+ return err;
+}
+
+static int
+fs_send_list_fonts(pointer client, FontPathElementPtr fpe, char *pattern,
+ int patlen, int maxnames, FontNamesPtr newnames)
+{
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ FSBlockDataPtr blockrec;
+ FSBlockedListPtr blockedlist;
+ fsListFontsReq req;
+
+ if (conn->blockState & FS_GIVE_UP)
+ return BadFontName;
+
+ /* make a new block record, and add it to the end of the list */
+ blockrec = fs_new_block_rec(fpe, client, FS_LIST_FONTS);
+ if (!blockrec)
+ return AllocError;
+ blockedlist = (FSBlockedListPtr) blockrec->data;
+ blockedlist->names = newnames;
+
+ if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING))
+ {
+ _fs_pending_reply (conn);
+ return Suspended;
+ }
+
+ _fs_client_access (conn, client, FALSE);
+ _fs_client_resolution(conn);
+
+ /* send the request */
+ req.reqType = FS_ListFonts;
+ req.pad = 0;
+ req.maxNames = maxnames;
+ req.nbytes = patlen;
+ req.length = (SIZEOF(fsListFontsReq) + patlen + 3) >> 2;
+ _fs_add_req_log(conn, FS_ListFonts);
+ _fs_write(conn, (char *) &req, SIZEOF(fsListFontsReq));
+ _fs_write_pad(conn, (char *) pattern, patlen);
+
+ blockrec->sequenceNumber = conn->current_seq;
+
+#ifdef NCD
+ if (configData.ExtendedFontDiags) {
+ char buf[256];
+
+ memcpy(buf, pattern, MIN(256, patlen));
+ buf[MIN(256, patlen)] = '\0';
+ printf("Listing fonts on pattern \"%s\" from font server \"%s\"\n",
+ buf, fpe->name);
+ }
+#endif
+
+ _fs_prepare_for_reply (conn);
+ return Suspended;
+}
+
+static int
+fs_list_fonts(pointer client, FontPathElementPtr fpe,
+ char *pattern, int patlen, int maxnames, FontNamesPtr newnames)
+{
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ FSBlockDataPtr blockrec;
+ int err;
+
+ /* see if the result is already there */
+ for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
+ {
+ if (blockrec->type == FS_LIST_FONTS && blockrec->client == client)
+ {
+ err = blockrec->errcode;
+ if (err == StillWorking)
+ return Suspended;
+ _fs_remove_block_rec(conn, blockrec);
+ return err;
+ }
+ }
+
+ /* didn't find waiting record, so send a new one */
+ return fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames);
+}
+
+/*
+ * Read a single list info reply and restart for the next reply
+ */
+static int
+fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
+{
+ FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data;
+ fsListFontsWithXInfoReply *rep;
+ char *buf;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ fsPropInfo *pi;
+ fsPropOffset *po;
+ pointer pd;
+ int ret;
+ int err;
+
+ /* clean up anything from the last trip */
+ _fs_free_props (&binfo->info);
+
+ rep = (fsListFontsWithXInfoReply *) fs_get_reply (conn, &ret);
+ if (!rep || rep->type == FS_Error)
+ {
+ if (ret == FSIO_BLOCK)
+ return StillWorking;
+ binfo->status = FS_LFWI_FINISHED;
+ err = AllocError;
+ goto done;
+ }
+ /*
+ * Normal termination -- the list ends with a name of length 0
+ */
+ if (rep->nameLength == 0)
+ {
+#ifdef DEBUG
+ fprintf (stderr, "fs_read_list_info done\n");
+#endif
+ binfo->status = FS_LFWI_FINISHED;
+ err = BadFontName;
+ goto done;
+ }
+
+ buf = (char *) rep + SIZEOF (fsListFontsWithXInfoReply);
+
+ /*
+ * The original FS implementation didn't match
+ * the spec, version 1 was respecified to match the FS.
+ * Version 2 matches the original intent
+ */
+ if (conn->fsMajorVersion <= 1)
+ {
+ memcpy (binfo->name, buf, rep->nameLength);
+ buf += _fs_pad_length (rep->nameLength);
+ }
+ pi = (fsPropInfo *) buf;
+ buf += SIZEOF (fsPropInfo);
+ po = (fsPropOffset *) buf;
+ buf += pi->num_offsets * SIZEOF (fsPropOffset);
+ pd = (pointer) buf;
+ buf += pi->data_len;
+ if (conn->fsMajorVersion > 1)
+ {
+ memcpy (binfo->name, buf, rep->nameLength);
+ buf += _fs_pad_length (rep->nameLength);
+ }
+
+#ifdef DEBUG
+ binfo->name[rep->nameLength] = '\0';
+ fprintf (stderr, "fs_read_list_info %s\n", binfo->name);
+#endif
+ err = _fs_convert_lfwi_reply(conn, &binfo->info, rep, pi, po, pd);
+ if (err != Successful)
+ {
+ binfo->status = FS_LFWI_FINISHED;
+ goto done;
+ }
+ binfo->namelen = rep->nameLength;
+ binfo->remaining = rep->nReplies;
+
+ binfo->status = FS_LFWI_REPLY;
+
+ /* disable this font server until we've processed this response */
+ _fs_unmark_block (conn, FS_COMPLETE_REPLY);
+ FD_CLR(conn->fs_fd, &_fs_fd_mask);
+done:
+ _fs_done_read (conn, rep->length << 2);
+ return err;
+}
+
+/* ARGSUSED */
+static int
+fs_start_list_with_info(pointer client, FontPathElementPtr fpe,
+ char *pattern, int len, int maxnames, pointer *pdata)
+{
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ FSBlockDataPtr blockrec;
+ FSBlockedListInfoPtr binfo;
+ fsListFontsWithXInfoReq req;
+
+ if (conn->blockState & FS_GIVE_UP)
+ return BadFontName;
+
+ /* make a new block record, and add it to the end of the list */
+ blockrec = fs_new_block_rec(fpe, client, FS_LIST_WITH_INFO);
+ if (!blockrec)
+ return AllocError;
+
+ binfo = (FSBlockedListInfoPtr) blockrec->data;
+ bzero((char *) binfo, sizeof(FSBlockedListInfoRec));
+ binfo->status = FS_LFWI_WAITING;
+
+ if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING))
+ {
+ _fs_pending_reply (conn);
+ return Suspended;
+ }
+
+ _fs_client_access (conn, client, FALSE);
+ _fs_client_resolution(conn);
+
+ /* send the request */
+ req.reqType = FS_ListFontsWithXInfo;
+ req.pad = 0;
+ req.maxNames = maxnames;
+ req.nbytes = len;
+ req.length = (SIZEOF(fsListFontsWithXInfoReq) + len + 3) >> 2;
+ _fs_add_req_log(conn, FS_ListFontsWithXInfo);
+ (void) _fs_write(conn, (char *) &req, SIZEOF(fsListFontsWithXInfoReq));
+ (void) _fs_write_pad(conn, pattern, len);
+
+ blockrec->sequenceNumber = conn->current_seq;
+
+#ifdef NCD
+ if (configData.ExtendedFontDiags) {
+ char buf[256];
+
+ memcpy(buf, pattern, MIN(256, len));
+ buf[MIN(256, len)] = '\0';
+ printf("Listing fonts with info on pattern \"%s\" from font server \"%s\"\n",
+ buf, fpe->name);
+ }
+#endif
+
+ _fs_prepare_for_reply (conn);
+ return Successful;
+}
+
+/* ARGSUSED */
+static int
+fs_next_list_with_info(pointer client, FontPathElementPtr fpe,
+ char **namep, int *namelenp,
+ FontInfoPtr *pFontInfo, int *numFonts,
+ pointer private)
+{
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ FSBlockDataPtr blockrec;
+ FSBlockedListInfoPtr binfo;
+ int err;
+
+ /* see if the result is already there */
+ for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
+ if (blockrec->type == FS_LIST_WITH_INFO && blockrec->client == client)
+ break;
+
+ if (!blockrec)
+ {
+ /* The only good reason for not finding a blockrec would be if
+ disconnect/reconnect to the font server wiped it out and the
+ code that called us didn't do the right thing to create
+ another one. Under those circumstances, we need to return an
+ error to prevent that code from attempting to interpret the
+ information we don't return. */
+ return BadFontName;
+ }
+
+ binfo = (FSBlockedListInfoPtr) blockrec->data;
+
+ if (binfo->status == FS_LFWI_WAITING)
+ return Suspended;
+
+ *namep = binfo->name;
+ *namelenp = binfo->namelen;
+ *pFontInfo = &binfo->info;
+ *numFonts = binfo->remaining;
+
+ /* Restart reply processing from this font server */
+ FD_SET(conn->fs_fd, &_fs_fd_mask);
+ if (fs_reply_ready (conn))
+ _fs_mark_block (conn, FS_COMPLETE_REPLY);
+
+ err = blockrec->errcode;
+ switch (binfo->status) {
+ case FS_LFWI_FINISHED:
+ _fs_remove_block_rec(conn, blockrec);
+ break;
+ case FS_LFWI_REPLY:
+ binfo->status = FS_LFWI_WAITING;
+ blockrec->errcode = StillWorking;
+ conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout;
+ _fs_mark_block (conn, FS_PENDING_REPLY);
+ break;
+ }
+
+ return err;
+}
+
+/*
+ * Called when client exits
+ */
+
+static void
+fs_client_died(pointer client, FontPathElementPtr fpe)
+{
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ FSBlockDataPtr blockrec,
+ depending;
+ FSClientPtr *prev, cur;
+ fsFreeACReq freeac;
+
+ for (prev = &conn->clients; (cur = *prev); prev = &cur->next)
+ {
+ if (cur->client == client) {
+ freeac.reqType = FS_FreeAC;
+ freeac.pad = 0;
+ freeac.id = cur->acid;
+ freeac.length = sizeof (fsFreeACReq) >> 2;
+ _fs_add_req_log(conn, FS_FreeAC);
+ _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq));
+ *prev = cur->next;
+ free (cur);
+ break;
+ }
+ }
+ /* find a pending requests */
+ for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next)
+ if (blockrec->client == client)
+ break;
+
+ if (!blockrec)
+ return;
+
+ /* replace the client pointers in this block rec with the chained one */
+ if ((depending = blockrec->depending))
+ {
+ blockrec->client = depending->client;
+ blockrec->depending = depending->depending;
+ blockrec = depending;
+ }
+ fs_abort_blockrec(conn, blockrec);
+}
+
+static void
+_fs_client_access (FSFpePtr conn, pointer client, Bool sync)
+{
+ FSClientPtr *prev, cur;
+ fsCreateACReq crac;
+ fsSetAuthorizationReq setac;
+ char *authorizations;
+ int authlen;
+ Bool new_cur = FALSE;
+ char padding[4] = { 0, 0, 0, 0 };
+
+#ifdef DEBUG
+ if (conn->blockState & (FS_RECONNECTING|FS_BROKEN_CONNECTION))
+ {
+ fprintf (stderr, "Sending requests without a connection\n");
+ }
+#endif
+ for (prev = &conn->clients; (cur = *prev); prev = &cur->next)
+ {
+ if (cur->client == client)
+ {
+ if (prev != &conn->clients)
+ {
+ *prev = cur->next;
+ cur->next = conn->clients;
+ conn->clients = cur;
+ }
+ break;
+ }
+ }
+ if (!cur)
+ {
+ cur = malloc (sizeof (FSClientRec));
+ if (!cur)
+ return;
+ cur->client = client;
+ cur->next = conn->clients;
+ conn->clients = cur;
+ cur->acid = GetNewFontClientID ();
+ new_cur = TRUE;
+ }
+ if (new_cur || cur->auth_generation != client_auth_generation(client))
+ {
+ if (!new_cur)
+ {
+ fsFreeACReq freeac;
+ freeac.reqType = FS_FreeAC;
+ freeac.pad = 0;
+ freeac.id = cur->acid;
+ freeac.length = sizeof (fsFreeACReq) >> 2;
+ _fs_add_req_log(conn, FS_FreeAC);
+ _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq));
+ }
+ crac.reqType = FS_CreateAC;
+ crac.num_auths = set_font_authorizations(&authorizations, &authlen,
+ client);
+ /* Work around bug in xfs versions up through modular release 1.0.8
+ which rejects CreateAC packets with num_auths = 0 & authlen < 4 */
+ if (crac.num_auths == 0) {
+ authorizations = padding;
+ authlen = 4;
+ } else {
+ authlen = (authlen + 3) & ~0x3;
+ }
+ crac.length = (sizeof (fsCreateACReq) + authlen) >> 2;
+ crac.acid = cur->acid;
+ _fs_add_req_log(conn, FS_CreateAC);
+ _fs_write(conn, (char *) &crac, sizeof (fsCreateACReq));
+ _fs_write(conn, authorizations, authlen);
+ /* ignore reply; we don't even care about it */
+ conn->curacid = 0;
+ cur->auth_generation = client_auth_generation(client);
+ }
+ if (conn->curacid != cur->acid)
+ {
+ setac.reqType = FS_SetAuthorization;
+ setac.pad = 0;
+ setac.length = sizeof (fsSetAuthorizationReq) >> 2;
+ setac.id = cur->acid;
+ _fs_add_req_log(conn, FS_SetAuthorization);
+ _fs_write(conn, (char *) &setac, sizeof (fsSetAuthorizationReq));
+ conn->curacid = cur->acid;
+ }
+}
+
+/*
+ * Poll a pending connect
+ */
+
+static int
+_fs_check_connect (FSFpePtr conn)
+{
+ int ret;
+
+ ret = _fs_poll_connect (conn->trans_conn, 0);
+ switch (ret) {
+ case FSIO_READY:
+ conn->fs_fd = _FontTransGetConnectionNumber (conn->trans_conn);
+ FD_SET (conn->fs_fd, &_fs_fd_mask);
+ break;
+ case FSIO_BLOCK:
+ break;
+ }
+ return ret;
+}
+
+/*
+ * Return an FSIO status while waiting for the completed connection
+ * reply to arrive
+ */
+
+static fsConnSetup *
+_fs_get_conn_setup (FSFpePtr conn, int *error, int *setup_len)
+{
+ int ret;
+ char *data;
+ int headlen;
+ int len;
+ fsConnSetup *setup;
+ fsConnSetupAccept *accept;
+
+ ret = _fs_start_read (conn, SIZEOF (fsConnSetup), &data);
+ if (ret != FSIO_READY)
+ {
+ *error = ret;
+ return 0;
+ }
+
+ setup = (fsConnSetup *) data;
+ if (setup->major_version > FS_PROTOCOL)
+ {
+ *error = FSIO_ERROR;
+ return 0;
+ }
+
+ headlen = (SIZEOF (fsConnSetup) +
+ (setup->alternate_len << 2) +
+ (setup->auth_len << 2));
+ /* On anything but Success, no extra data is sent */
+ if (setup->status != AuthSuccess)
+ {
+ len = headlen;
+ }
+ else
+ {
+ ret = _fs_start_read (conn, headlen + SIZEOF (fsConnSetupAccept), &data);
+ if (ret != FSIO_READY)
+ {
+ *error = ret;
+ return 0;
+ }
+ setup = (fsConnSetup *) data;
+ accept = (fsConnSetupAccept *) (data + headlen);
+ len = headlen + (accept->length << 2);
+ }
+ ret = _fs_start_read (conn, len, &data);
+ if (ret != FSIO_READY)
+ {
+ *error = ret;
+ return 0;
+ }
+ *setup_len = len;
+ return (fsConnSetup *) data;
+}
+
+static int
+_fs_send_conn_client_prefix (FSFpePtr conn)
+{
+ fsConnClientPrefix req;
+ int endian;
+ int ret;
+
+ /* send setup prefix */
+ endian = 1;
+ if (*(char *) &endian)
+ req.byteOrder = 'l';
+ else
+ req.byteOrder = 'B';
+
+ req.major_version = FS_PROTOCOL;
+ req.minor_version = FS_PROTOCOL_MINOR;
+
+/* XXX add some auth info here */
+ req.num_auths = 0;
+ req.auth_len = 0;
+ ret = _fs_write (conn, (char *) &req, SIZEOF (fsConnClientPrefix));
+ if (ret != FSIO_READY)
+ return FSIO_ERROR;
+ conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout;
+ return ret;
+}
+
+static int
+_fs_recv_conn_setup (FSFpePtr conn)
+{
+ int ret = FSIO_ERROR;
+ fsConnSetup *setup;
+ FSFpeAltPtr alts;
+ int i, alt_len;
+ int setup_len;
+ char *alt_save, *alt_names;
+
+ setup = _fs_get_conn_setup (conn, &ret, &setup_len);
+ if (!setup)
+ return ret;
+ conn->current_seq = 0;
+ conn->fsMajorVersion = setup->major_version;
+ /*
+ * Create an alternate list from the initial server, but
+ * don't chain looking for alternates.
+ */
+ if (conn->alternate == 0)
+ {
+ /*
+ * free any existing alternates list, allowing the list to
+ * be updated
+ */
+ if (conn->alts)
+ {
+ free (conn->alts);
+ conn->alts = 0;
+ conn->numAlts = 0;
+ }
+ if (setup->num_alternates)
+ {
+ alts = malloc (setup->num_alternates * sizeof (FSFpeAltRec) +
+ (setup->alternate_len << 2));
+ if (alts)
+ {
+ alt_names = (char *) (setup + 1);
+ alt_save = (char *) (alts + setup->num_alternates);
+ for (i = 0; i < setup->num_alternates; i++)
+ {
+ alts[i].subset = alt_names[0];
+ alt_len = alt_names[1];
+ alts[i].name = alt_save;
+ memcpy (alt_save, alt_names + 2, alt_len);
+ alt_save[alt_len] = '\0';
+ alt_save += alt_len + 1;
+ alt_names += _fs_pad_length (alt_len + 2);
+ }
+ conn->numAlts = setup->num_alternates;
+ conn->alts = alts;
+ }
+ }
+ }
+ _fs_done_read (conn, setup_len);
+ if (setup->status != AuthSuccess)
+ return FSIO_ERROR;
+ return FSIO_READY;
+}
+
+static int
+_fs_open_server (FSFpePtr conn)
+{
+ int ret;
+ char *servername;
+
+ if (conn->alternate == 0)
+ servername = conn->servername;
+ else
+ servername = conn->alts[conn->alternate-1].name;
+ conn->trans_conn = _fs_connect (servername, &ret);
+ conn->blockedConnectTime = GetTimeInMillis () + FS_RECONNECT_WAIT;
+ return ret;
+}
+
+static char *
+_fs_catalog_name (char *servername)
+{
+ char *sp;
+
+ sp = strchr (servername, '/');
+ if (!sp)
+ return 0;
+ return strrchr (sp + 1, '/');
+}
+
+static int
+_fs_send_init_packets (FSFpePtr conn)
+{
+ fsSetResolutionReq srreq;
+ fsSetCataloguesReq screq;
+ int num_cats,
+ clen;
+ char *catalogues;
+ char *cat;
+ char len;
+ char *end;
+ int num_res;
+ FontResolutionPtr res;
+
+#define CATALOGUE_SEP '+'
+
+ res = GetClientResolutions(&num_res);
+ if (num_res)
+ {
+ srreq.reqType = FS_SetResolution;
+ srreq.num_resolutions = num_res;
+ srreq.length = (SIZEOF(fsSetResolutionReq) +
+ (num_res * SIZEOF(fsResolution)) + 3) >> 2;
+
+ _fs_add_req_log(conn, FS_SetResolution);
+ if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != FSIO_READY)
+ return FSIO_ERROR;
+ if (_fs_write_pad(conn, (char *) res, (num_res * SIZEOF(fsResolution))) != FSIO_READY)
+ return FSIO_ERROR;
+ }
+
+ catalogues = 0;
+ if (conn->alternate != 0)
+ catalogues = _fs_catalog_name (conn->alts[conn->alternate-1].name);
+ if (!catalogues)
+ catalogues = _fs_catalog_name (conn->servername);
+
+ if (!catalogues)
+ {
+ conn->has_catalogues = FALSE;
+ return FSIO_READY;
+ }
+ conn->has_catalogues = TRUE;
+
+ /* turn cats into counted list */
+ catalogues++;
+
+ cat = catalogues;
+ num_cats = 0;
+ clen = 0;
+ while (*cat)
+ {
+ num_cats++;
+ end = strchr(cat, CATALOGUE_SEP);
+ if (!end)
+ end = cat + strlen (cat);
+ clen += (end - cat) + 1; /* length byte + string */
+ cat = end;
+ }
+
+ screq.reqType = FS_SetCatalogues;
+ screq.num_catalogues = num_cats;
+ screq.length = (SIZEOF(fsSetCataloguesReq) + clen + 3) >> 2;
+
+ _fs_add_req_log(conn, FS_SetCatalogues);
+ if (_fs_write(conn, (char *) &screq, SIZEOF(fsSetCataloguesReq)) != FSIO_READY)
+ return FSIO_ERROR;
+
+ while (*cat)
+ {
+ num_cats++;
+ end = strchr(cat, CATALOGUE_SEP);
+ if (!end)
+ end = cat + strlen (cat);
+ len = end - cat;
+ if (_fs_write (conn, &len, 1) != FSIO_READY)
+ return FSIO_ERROR;
+ if (_fs_write (conn, cat, (int) len) != FSIO_READY)
+ return FSIO_ERROR;
+ cat = end;
+ }
+
+ if (_fs_write (conn, "....", _fs_pad_length (clen) - clen) != FSIO_READY)
+ return FSIO_ERROR;
+
+ return FSIO_READY;
+}
+
+static int
+_fs_send_cat_sync (FSFpePtr conn)
+{
+ fsListCataloguesReq lcreq;
+
+ /*
+ * now sync up with the font server, to see if an error was generated
+ * by a bogus catalogue
+ */
+ lcreq.reqType = FS_ListCatalogues;
+ lcreq.length = (SIZEOF(fsListCataloguesReq)) >> 2;
+ lcreq.maxNames = 0;
+ lcreq.nbytes = 0;
+ lcreq.pad2 = 0;
+ _fs_add_req_log(conn, FS_SetCatalogues);
+ if (_fs_write(conn, (char *) &lcreq, SIZEOF(fsListCataloguesReq)) != FSIO_READY)
+ return FSIO_ERROR;
+ conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout;
+ return FSIO_READY;
+}
+
+static int
+_fs_recv_cat_sync (FSFpePtr conn)
+{
+ fsGenericReply *reply;
+ fsError *error;
+ int err;
+ int ret;
+
+ reply = fs_get_reply (conn, &err);
+ if (!reply)
+ return err;
+
+ ret = FSIO_READY;
+ if (reply->type == FS_Error)
+ {
+ error = (fsError *) reply;
+ if (error->major_opcode == FS_SetCatalogues)
+ ret = FSIO_ERROR;
+ }
+ _fs_done_read (conn, reply->length << 2);
+ return ret;
+}
+
+static void
+_fs_close_server (FSFpePtr conn)
+{
+ _fs_unmark_block (conn, FS_PENDING_WRITE|FS_BROKEN_WRITE|FS_COMPLETE_REPLY|FS_BROKEN_CONNECTION);
+ if (conn->trans_conn)
+ {
+ _FontTransClose (conn->trans_conn);
+ conn->trans_conn = 0;
+ _fs_io_reinit (conn);
+ }
+ if (conn->fs_fd >= 0)
+ {
+ FD_CLR (conn->fs_fd, &_fs_fd_mask);
+ conn->fs_fd = -1;
+ }
+ conn->fs_conn_state = FS_CONN_UNCONNECTED;
+}
+
+static int
+_fs_do_setup_connection (FSFpePtr conn)
+{
+ int ret;
+
+ do
+ {
+#ifdef DEBUG
+ fprintf (stderr, "fs_do_setup_connection state %d\n", conn->fs_conn_state);
+#endif
+ switch (conn->fs_conn_state) {
+ case FS_CONN_UNCONNECTED:
+ ret = _fs_open_server (conn);
+ if (ret == FSIO_BLOCK)
+ conn->fs_conn_state = FS_CONN_CONNECTING;
+ break;
+ case FS_CONN_CONNECTING:
+ ret = _fs_check_connect (conn);
+ break;
+ case FS_CONN_CONNECTED:
+ ret = _fs_send_conn_client_prefix (conn);
+ break;
+ case FS_CONN_SENT_PREFIX:
+ ret = _fs_recv_conn_setup (conn);
+ break;
+ case FS_CONN_RECV_INIT:
+ ret = _fs_send_init_packets (conn);
+ if (conn->has_catalogues)
+ ret = _fs_send_cat_sync (conn);
+ break;
+ case FS_CONN_SENT_CAT:
+ if (conn->has_catalogues)
+ ret = _fs_recv_cat_sync (conn);
+ else
+ ret = FSIO_READY;
+ break;
+ default:
+ ret = FSIO_READY;
+ break;
+ }
+ switch (ret) {
+ case FSIO_READY:
+ if (conn->fs_conn_state < FS_CONN_RUNNING)
+ conn->fs_conn_state++;
+ break;
+ case FSIO_BLOCK:
+ if (TimeCmp (GetTimeInMillis (), <, conn->blockedConnectTime))
+ break;
+ ret = FSIO_ERROR;
+ /* fall through... */
+ case FSIO_ERROR:
+ _fs_close_server (conn);
+ /*
+ * Try the next alternate
+ */
+ if (conn->alternate < conn->numAlts)
+ {
+ conn->alternate++;
+ ret = FSIO_READY;
+ }
+ else
+ conn->alternate = 0;
+ break;
+ }
+ } while (conn->fs_conn_state != FS_CONN_RUNNING && ret == FSIO_READY);
+ if (ret == FSIO_READY)
+ conn->generation = ++generationCount;
+ return ret;
+}
+
+static int
+_fs_wait_connect (FSFpePtr conn)
+{
+ int ret;
+
+ for (;;)
+ {
+ ret = _fs_do_setup_connection (conn);
+ if (ret != FSIO_BLOCK)
+ break;
+ if (conn->fs_conn_state <= FS_CONN_CONNECTING)
+ ret = _fs_poll_connect (conn->trans_conn, 1000);
+ else
+ ret = _fs_wait_for_readable (conn, 1000);
+ if (ret == FSIO_ERROR)
+ break;
+ }
+ return ret;
+}
+
+/*
+ * Poll a connection in the process of reconnecting
+ */
+static void
+_fs_check_reconnect (FSFpePtr conn)
+{
+ int ret;
+
+ ret = _fs_do_setup_connection (conn);
+ switch (ret) {
+ case FSIO_READY:
+ _fs_unmark_block (conn, FS_RECONNECTING|FS_GIVE_UP);
+ _fs_restart_connection (conn);
+ break;
+ case FSIO_BLOCK:
+ break;
+ case FSIO_ERROR:
+ conn->brokenConnectionTime = GetTimeInMillis () + FS_RECONNECT_POLL;
+ break;
+ }
+}
+
+/*
+ * Start the reconnection process
+ */
+static void
+_fs_start_reconnect (FSFpePtr conn)
+{
+ if (conn->blockState & FS_RECONNECTING)
+ return;
+ conn->alternate = 0;
+ _fs_mark_block (conn, FS_RECONNECTING);
+ _fs_unmark_block (conn, FS_BROKEN_CONNECTION);
+ _fs_check_reconnect (conn);
+}
+
+
+static FSFpePtr
+_fs_init_conn (char *servername)
+{
+ FSFpePtr conn;
+
+ conn = calloc (1, sizeof (FSFpeRec) + strlen (servername) + 1);
+ if (!conn)
+ return 0;
+ if (!_fs_io_init (conn))
+ {
+ free (conn);
+ return 0;
+ }
+ conn->servername = (char *) (conn + 1);
+ conn->fs_conn_state = FS_CONN_UNCONNECTED;
+ conn->fs_fd = -1;
+ strcpy (conn->servername, servername);
+ return conn;
+}
+
+static void
+_fs_free_conn (FSFpePtr conn)
+{
+ _fs_close_server (conn);
+ _fs_io_fini (conn);
+ if (conn->alts)
+ free (conn->alts);
+ free (conn);
+}
+
+/*
+ * called at server init time
+ */
+
+void
+fs_register_fpe_functions(void)
+{
+ RegisterFPEFunctions(fs_name_check,
+ fs_init_fpe,
+ fs_free_fpe,
+ fs_reset_fpe,
+ fs_open_font,
+ fs_close_font,
+ fs_list_fonts,
+ fs_start_list_with_info,
+ fs_next_list_with_info,
+ fs_wakeup,
+ fs_client_died,
+ _fs_load_glyphs,
+ NULL,
+ NULL,
+ NULL);
+}
diff --git a/libXfont/src/fc/fserve.h b/libXfont/src/fc/fserve.h index 5999861b6..71f165ae1 100644 --- a/libXfont/src/fc/fserve.h +++ b/libXfont/src/fc/fserve.h @@ -1,91 +1,91 @@ -/* - * Copyright 1990 Network Computing Devices - * - * 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, and that the name of Network Computing Devices not be - * used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. Network Computing - * Devices makes no representations about the suitability of this software - * for any purpose. It is provided "as is" without express or implied - * warranty. - * - * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, - * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE - * OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Dave Lemke, Network Computing Devices, Inc - * - */ - -#ifndef _FSERVE_H_ -#define _FSERVE_H_ -/* - * font server data structures - */ - -/* types of block records */ -#define FS_OPEN_FONT 1 -#define FS_LOAD_GLYPHS 2 -#define FS_LIST_FONTS 3 -#define FS_LIST_WITH_INFO 4 - -/* states of OpenFont */ -#define FS_OPEN_REPLY 0 -#define FS_INFO_REPLY 1 -#define FS_EXTENT_REPLY 2 -#define FS_GLYPHS_REPLY 3 -#define FS_DONE_REPLY 4 -#define FS_DEPENDING 5 - -/* status of ListFontsWithInfo */ -#define FS_LFWI_WAITING 0 -#define FS_LFWI_REPLY 1 -#define FS_LFWI_FINISHED 2 - -/* states of connection */ -#define FS_CONN_CLOSED 0 -#define FS_CONN_CONNECTING 1 -#define FS_CONN_READ_HEADER 2 -#define FS_CONN_READ_DATA 3 - -#define AccessDone 0x400 - -typedef struct _fs_font_data *FSFontDataPtr; -typedef struct _fs_blocked_font *FSBlockedFontPtr; -typedef struct _fs_blocked_glyphs *FSBlockedGlyphPtr; -typedef struct _fs_blocked_list *FSBlockedListPtr; -typedef struct _fs_blocked_list_info *FSBlockedListInfoPtr; -typedef struct _fs_block_data *FSBlockDataPtr; -typedef struct _fs_font_table *FSFontTablePtr; -typedef struct _fs_fpe_data *FSFpePtr; - -typedef struct _fs_blocked_bitmaps *FSBlockedBitmapPtr; -typedef struct _fs_blocked_extents *FSBlockedExtentPtr; - -extern void _fs_convert_char_info ( fsXCharInfo *src, xCharInfo *dst ); -extern void _fs_free_props (FontInfoPtr pfi); -extern FontPtr fs_create_font (FontPathElementPtr fpe, - char *name, - int namelen, - fsBitmapFormat format, - fsBitmapFormatMask fmask); - -extern int fs_load_all_glyphs ( FontPtr pfont ); - -/* - * These should be declared elsewhere, but I'm concerned that moving them - * would cause problems building other pieces - */ -extern FontPtr find_old_font (Font id); -extern int set_font_authorizations (char **a, int *len, pointer client); -extern long GetTimeInMillis (void); - - -#endif /* _FSERVE_H_ */ +/*
+ * Copyright 1990 Network Computing Devices
+ *
+ * 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, and that the name of Network Computing Devices not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. Network Computing
+ * Devices makes no representations about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+ * OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Dave Lemke, Network Computing Devices, Inc
+ *
+ */
+
+#ifndef _FSERVE_H_
+#define _FSERVE_H_
+/*
+ * font server data structures
+ */
+
+/* types of block records */
+#define FS_OPEN_FONT 1
+#define FS_LOAD_GLYPHS 2
+#define FS_LIST_FONTS 3
+#define FS_LIST_WITH_INFO 4
+
+/* states of OpenFont */
+#define FS_OPEN_REPLY 0
+#define FS_INFO_REPLY 1
+#define FS_EXTENT_REPLY 2
+#define FS_GLYPHS_REPLY 3
+#define FS_DONE_REPLY 4
+#define FS_DEPENDING 5
+
+/* status of ListFontsWithInfo */
+#define FS_LFWI_WAITING 0
+#define FS_LFWI_REPLY 1
+#define FS_LFWI_FINISHED 2
+
+/* states of connection */
+#define FS_CONN_CLOSED 0
+#define FS_CONN_CONNECTING 1
+#define FS_CONN_READ_HEADER 2
+#define FS_CONN_READ_DATA 3
+
+#define AccessDone 0x400
+
+typedef struct _fs_font_data *FSFontDataPtr;
+typedef struct _fs_blocked_font *FSBlockedFontPtr;
+typedef struct _fs_blocked_glyphs *FSBlockedGlyphPtr;
+typedef struct _fs_blocked_list *FSBlockedListPtr;
+typedef struct _fs_blocked_list_info *FSBlockedListInfoPtr;
+typedef struct _fs_block_data *FSBlockDataPtr;
+typedef struct _fs_font_table *FSFontTablePtr;
+typedef struct _fs_fpe_data *FSFpePtr;
+
+typedef struct _fs_blocked_bitmaps *FSBlockedBitmapPtr;
+typedef struct _fs_blocked_extents *FSBlockedExtentPtr;
+
+extern void _fs_convert_char_info ( fsXCharInfo *src, xCharInfo *dst );
+extern void _fs_free_props (FontInfoPtr pfi);
+extern FontPtr fs_create_font (FontPathElementPtr fpe,
+ char *name,
+ int namelen,
+ fsBitmapFormat format,
+ fsBitmapFormatMask fmask);
+
+extern int fs_load_all_glyphs ( FontPtr pfont );
+
+/*
+ * These should be declared elsewhere, but I'm concerned that moving them
+ * would cause problems building other pieces
+ */
+extern FontPtr find_old_font (Font id);
+extern int set_font_authorizations (char **a, int *len, pointer client);
+extern long GetTimeInMillis (void);
+
+
+#endif /* _FSERVE_H_ */
diff --git a/libXfont/src/fc/fservestr.h b/libXfont/src/fc/fservestr.h index a6d0d1d53..90f17c29e 100644 --- a/libXfont/src/fc/fservestr.h +++ b/libXfont/src/fc/fservestr.h @@ -1,200 +1,200 @@ -/* - * Copyright 1990 Network Computing Devices - * - * 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, and that the name of Network Computing Devices not be - * used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. Network Computing - * Devices makes no representations about the suitability of this software - * for any purpose. It is provided "as is" without express or implied - * warranty. - * - * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, - * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE - * OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Dave Lemke, Network Computing Devices, Inc - */ - -#ifndef _FSERVESTR_H_ -#define _FSERVESTR_H_ - -#include "fserve.h" -#include "fsio.h" - -/* - * font server data structures - */ -/* - * font server private storage - */ - -typedef struct _fs_glyph { - struct _fs_glyph *next; -} FSGlyphRec, *FSGlyphPtr; - -typedef struct _fs_font { - CharInfoPtr pDefault; - CharInfoPtr encoding; - CharInfoPtr inkMetrics; - FSGlyphPtr glyphs; -} FSFontRec, *FSFontPtr; - -/* FS special data for the font */ -typedef struct _fs_font_data { - long fontid; - int generation; /* FS generation when opened */ - unsigned long glyphs_to_get; /* # glyphs remaining to be gotten */ - - /* Following data needed in case font needs to be reopened. */ - int namelen; - char *name; - fsBitmapFormat format; - fsBitmapFormatMask fmask; -} FSFontDataRec; - -typedef struct fs_clients_depending { - pointer client; - struct fs_clients_depending *next; -} FSClientsDependingRec, *FSClientsDependingPtr; - -/* OpenFont specific data for blocked request */ -typedef struct _fs_blocked_font { - FontPtr pfont; /* must be first for fs_read_glyphs */ - long fontid; - int state; /* how many of the replies have landed */ - int flags; - Bool freeFont; /* free this font on failure */ - CARD16 queryInfoSequence; - CARD16 queryExtentsSequence; - CARD16 queryBitmapsSequence; - fsBitmapFormat format; - FSClientsDependingPtr clients_depending; -} FSBlockedFontRec; - -/* LoadGlyphs data for blocked request */ -typedef struct _fs_blocked_glyphs { - FontPtr pfont; /* must be first for fs_read_glyphs */ - int num_expected_ranges; - fsRange *expected_ranges; - FSClientsDependingPtr clients_depending; -} FSBlockedGlyphRec; - -/* LoadExtents data for blocked request */ -typedef struct _fs_blocked_extents { - FontPtr pfont; - fsRange *expected_ranges; - int nranges; - unsigned long nextents; - fsXCharInfo *extents; -} FSBlockedExtentRec; - -/* LoadBitmaps data for blocked request */ -typedef struct _fs_blocked_bitmaps { - FontPtr pfont; - fsRange *expected_ranges; - int nranges; - unsigned long size; - unsigned long nglyphs; - fsOffset32 *offsets; - pointer gdata; -} FSBlockedBitmapRec; - -/* state for blocked ListFonts */ -typedef struct _fs_blocked_list { - FontNamesPtr names; -} FSBlockedListRec; - -/* state for blocked ListFontsWithInfo */ -typedef struct _fs_blocked_list_info { - int status; - int namelen; - FontInfoRec info; - char name[256]; - int remaining; -} FSBlockedListInfoRec; - -/* state for blocked request */ -typedef struct _fs_block_data { - int type; /* Open Font, LoadGlyphs, ListFonts, - * ListWithInfo */ - pointer client; /* who wants it */ - CARD16 sequenceNumber; /* expected */ - pointer data; /* type specific data */ - int errcode; /* Suspended, et al. */ - struct _fs_block_data *depending; /* clients depending on this one */ - struct _fs_block_data *next; -} FSBlockDataRec; - -/* state for reconnected to dead font server */ -typedef struct _fs_reconnect { - int i; -} FSReconnectRec, *FSReconnectPtr; - - -#if !defined(UNIXCPP) || defined(ANSICPP) -#define fsCat(x,y) x##_##y -#else -#define fsCat(x,y) x/**/_/**/y -#endif - - -/* copy XCharInfo parts of a protocol reply into a xCharInfo */ - -#define fsUnpack_XCharInfo(packet, structure) \ - (structure)->leftSideBearing = fsCat(packet,left); \ - (structure)->rightSideBearing = fsCat(packet,right); \ - (structure)->characterWidth = fsCat(packet,width); \ - (structure)->ascent = fsCat(packet,ascent); \ - (structure)->descent = fsCat(packet,descent); \ - (structure)->attributes = fsCat(packet,attributes) - - -/* copy XFontInfoHeader parts of a protocol reply into a FontInfoRec */ - -#define fsUnpack_XFontInfoHeader(packet, structure) \ - (structure)->allExist = ((packet)->font_header_flags & FontInfoAllCharsExist) != 0; \ - (structure)->drawDirection = \ - ((packet)->font_header_draw_direction == LeftToRightDrawDirection) ? \ - LeftToRight : RightToLeft; \ - (structure)->inkInside = ((packet)->font_header_flags & FontInfoInkInside) != 0; \ - \ - (structure)->firstRow = (packet)->font_hdr_char_range_min_char_high; \ - (structure)->firstCol = (packet)->font_hdr_char_range_min_char_low; \ - (structure)->lastRow = (packet)->font_hdr_char_range_max_char_high; \ - (structure)->lastCol = (packet)->font_hdr_char_range_max_char_low; \ - (structure)->defaultCh = (packet)->font_header_default_char_low \ - + ((packet)->font_header_default_char_high << 8); \ - \ - (structure)->fontDescent = (packet)->font_header_font_descent; \ - (structure)->fontAscent = (packet)->font_header_font_ascent; \ - \ - fsUnpack_XCharInfo((packet)->font_header_min_bounds, &(structure)->minbounds); \ - fsUnpack_XCharInfo((packet)->font_header_min_bounds, &(structure)->ink_minbounds); \ - fsUnpack_XCharInfo((packet)->font_header_max_bounds, &(structure)->maxbounds); \ - fsUnpack_XCharInfo((packet)->font_header_max_bounds, &(structure)->ink_maxbounds) - -extern void _fs_init_fontinfo ( FSFpePtr conn, FontInfoPtr pfi ); -extern int _fs_convert_props ( fsPropInfo *pi, fsPropOffset *po, pointer pd, - FontInfoPtr pfi ); -extern int _fs_convert_lfwi_reply ( FSFpePtr conn, FontInfoPtr pfi, - fsListFontsWithXInfoReply *fsrep, - fsPropInfo *pi, fsPropOffset *po, - pointer pd ); -extern int fs_build_range ( FontPtr pfont, Bool range_flag, - unsigned int count, int item_size, - unsigned char *data, int *nranges, - fsRange **ranges ); -extern void _fs_clean_aborted_loadglyphs ( FontPtr pfont, - int num_expected_ranges, - fsRange *expected_ranges ); -extern void _fs_init_font ( FontPtr pfont ); -extern pointer fs_alloc_glyphs (FontPtr pFont, int size); -#endif /* _FSERVESTR_H_ */ +/*
+ * Copyright 1990 Network Computing Devices
+ *
+ * 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, and that the name of Network Computing Devices not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. Network Computing
+ * Devices makes no representations about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+ * OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Dave Lemke, Network Computing Devices, Inc
+ */
+
+#ifndef _FSERVESTR_H_
+#define _FSERVESTR_H_
+
+#include "fserve.h"
+#include "fsio.h"
+
+/*
+ * font server data structures
+ */
+/*
+ * font server private storage
+ */
+
+typedef struct _fs_glyph {
+ struct _fs_glyph *next;
+} FSGlyphRec, *FSGlyphPtr;
+
+typedef struct _fs_font {
+ CharInfoPtr pDefault;
+ CharInfoPtr encoding;
+ CharInfoPtr inkMetrics;
+ FSGlyphPtr glyphs;
+} FSFontRec, *FSFontPtr;
+
+/* FS special data for the font */
+typedef struct _fs_font_data {
+ long fontid;
+ int generation; /* FS generation when opened */
+ unsigned long glyphs_to_get; /* # glyphs remaining to be gotten */
+
+ /* Following data needed in case font needs to be reopened. */
+ int namelen;
+ char *name;
+ fsBitmapFormat format;
+ fsBitmapFormatMask fmask;
+} FSFontDataRec;
+
+typedef struct fs_clients_depending {
+ pointer client;
+ struct fs_clients_depending *next;
+} FSClientsDependingRec, *FSClientsDependingPtr;
+
+/* OpenFont specific data for blocked request */
+typedef struct _fs_blocked_font {
+ FontPtr pfont; /* must be first for fs_read_glyphs */
+ long fontid;
+ int state; /* how many of the replies have landed */
+ int flags;
+ Bool freeFont; /* free this font on failure */
+ CARD16 queryInfoSequence;
+ CARD16 queryExtentsSequence;
+ CARD16 queryBitmapsSequence;
+ fsBitmapFormat format;
+ FSClientsDependingPtr clients_depending;
+} FSBlockedFontRec;
+
+/* LoadGlyphs data for blocked request */
+typedef struct _fs_blocked_glyphs {
+ FontPtr pfont; /* must be first for fs_read_glyphs */
+ int num_expected_ranges;
+ fsRange *expected_ranges;
+ FSClientsDependingPtr clients_depending;
+} FSBlockedGlyphRec;
+
+/* LoadExtents data for blocked request */
+typedef struct _fs_blocked_extents {
+ FontPtr pfont;
+ fsRange *expected_ranges;
+ int nranges;
+ unsigned long nextents;
+ fsXCharInfo *extents;
+} FSBlockedExtentRec;
+
+/* LoadBitmaps data for blocked request */
+typedef struct _fs_blocked_bitmaps {
+ FontPtr pfont;
+ fsRange *expected_ranges;
+ int nranges;
+ unsigned long size;
+ unsigned long nglyphs;
+ fsOffset32 *offsets;
+ pointer gdata;
+} FSBlockedBitmapRec;
+
+/* state for blocked ListFonts */
+typedef struct _fs_blocked_list {
+ FontNamesPtr names;
+} FSBlockedListRec;
+
+/* state for blocked ListFontsWithInfo */
+typedef struct _fs_blocked_list_info {
+ int status;
+ int namelen;
+ FontInfoRec info;
+ char name[256];
+ int remaining;
+} FSBlockedListInfoRec;
+
+/* state for blocked request */
+typedef struct _fs_block_data {
+ int type; /* Open Font, LoadGlyphs, ListFonts,
+ * ListWithInfo */
+ pointer client; /* who wants it */
+ CARD16 sequenceNumber; /* expected */
+ pointer data; /* type specific data */
+ int errcode; /* Suspended, et al. */
+ struct _fs_block_data *depending; /* clients depending on this one */
+ struct _fs_block_data *next;
+} FSBlockDataRec;
+
+/* state for reconnected to dead font server */
+typedef struct _fs_reconnect {
+ int i;
+} FSReconnectRec, *FSReconnectPtr;
+
+
+#if !defined(UNIXCPP) || defined(ANSICPP)
+#define fsCat(x,y) x##_##y
+#else
+#define fsCat(x,y) x/**/_/**/y
+#endif
+
+
+/* copy XCharInfo parts of a protocol reply into a xCharInfo */
+
+#define fsUnpack_XCharInfo(packet, structure) \
+ (structure)->leftSideBearing = fsCat(packet,left); \
+ (structure)->rightSideBearing = fsCat(packet,right); \
+ (structure)->characterWidth = fsCat(packet,width); \
+ (structure)->ascent = fsCat(packet,ascent); \
+ (structure)->descent = fsCat(packet,descent); \
+ (structure)->attributes = fsCat(packet,attributes)
+
+
+/* copy XFontInfoHeader parts of a protocol reply into a FontInfoRec */
+
+#define fsUnpack_XFontInfoHeader(packet, structure) \
+ (structure)->allExist = ((packet)->font_header_flags & FontInfoAllCharsExist) != 0; \
+ (structure)->drawDirection = \
+ ((packet)->font_header_draw_direction == LeftToRightDrawDirection) ? \
+ LeftToRight : RightToLeft; \
+ (structure)->inkInside = ((packet)->font_header_flags & FontInfoInkInside) != 0; \
+ \
+ (structure)->firstRow = (packet)->font_hdr_char_range_min_char_high; \
+ (structure)->firstCol = (packet)->font_hdr_char_range_min_char_low; \
+ (structure)->lastRow = (packet)->font_hdr_char_range_max_char_high; \
+ (structure)->lastCol = (packet)->font_hdr_char_range_max_char_low; \
+ (structure)->defaultCh = (packet)->font_header_default_char_low \
+ + ((packet)->font_header_default_char_high << 8); \
+ \
+ (structure)->fontDescent = (packet)->font_header_font_descent; \
+ (structure)->fontAscent = (packet)->font_header_font_ascent; \
+ \
+ fsUnpack_XCharInfo((packet)->font_header_min_bounds, &(structure)->minbounds); \
+ fsUnpack_XCharInfo((packet)->font_header_min_bounds, &(structure)->ink_minbounds); \
+ fsUnpack_XCharInfo((packet)->font_header_max_bounds, &(structure)->maxbounds); \
+ fsUnpack_XCharInfo((packet)->font_header_max_bounds, &(structure)->ink_maxbounds)
+
+extern void _fs_init_fontinfo ( FSFpePtr conn, FontInfoPtr pfi );
+extern int _fs_convert_props ( fsPropInfo *pi, fsPropOffset *po, pointer pd,
+ FontInfoPtr pfi );
+extern int _fs_convert_lfwi_reply ( FSFpePtr conn, FontInfoPtr pfi,
+ fsListFontsWithXInfoReply *fsrep,
+ fsPropInfo *pi, fsPropOffset *po,
+ pointer pd );
+extern int fs_build_range ( FontPtr pfont, Bool range_flag,
+ unsigned int count, int item_size,
+ unsigned char *data, int *nranges,
+ fsRange **ranges );
+extern void _fs_clean_aborted_loadglyphs ( FontPtr pfont,
+ int num_expected_ranges,
+ fsRange *expected_ranges );
+extern void _fs_init_font ( FontPtr pfont );
+extern pointer fs_alloc_glyphs (FontPtr pFont, int size);
+#endif /* _FSERVESTR_H_ */
diff --git a/libXfont/src/fc/fsio.c b/libXfont/src/fc/fsio.c index 63d3b4f3c..29c0d7d26 100644 --- a/libXfont/src/fc/fsio.c +++ b/libXfont/src/fc/fsio.c @@ -1,451 +1,452 @@ -/* - * Copyright 1990 Network Computing Devices - * - * 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, and that the name of Network Computing Devices not be - * used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. Network Computing - * Devices makes no representations about the suitability of this software - * for any purpose. It is provided "as is" without express or implied - * warranty. - * - * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, - * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE - * OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Dave Lemke, Network Computing Devices, Inc - */ -/* - * font server i/o routines - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef WIN32 -#define _WILLWINSOCK_ -#include "X11/Xwindows.h" -#endif - -#define FONT_t -#define TRANS_CLIENT -#include "X11/Xtrans/Xtrans.h" -#include "X11/Xpoll.h" -#include <X11/fonts/FS.h> -#include <X11/fonts/FSproto.h> -#include <X11/fonts/fontmisc.h> -#include <X11/fonts/fontstruct.h> -#include "fservestr.h" - -#include <stdio.h> -#include <signal.h> -#include <sys/types.h> -#if !defined(WIN32) -#ifndef Lynx -#include <sys/socket.h> -#else -#include <socket.h> -#endif -#endif -#include <errno.h> -#ifdef WIN32 -#define EWOULDBLOCK WSAEWOULDBLOCK -#undef EINTR -#define EINTR WSAEINTR -#endif - - - -static int padlength[4] = {0, 3, 2, 1}; -fd_set _fs_fd_mask; - -static int -_fs_resize (FSBufPtr buf, long size); - -static void -_fs_downsize (FSBufPtr buf, long size); - -int -_fs_poll_connect (XtransConnInfo trans_conn, int timeout) -{ - fd_set w_mask; - struct timeval tv; - int fs_fd = _FontTransGetConnectionNumber (trans_conn); - int ret; - - do - { - tv.tv_usec = 0; - tv.tv_sec = timeout; - FD_ZERO (&w_mask); - FD_SET (fs_fd, &w_mask); - ret = Select (fs_fd + 1, NULL, &w_mask, NULL, &tv); - } while (ret < 0 && ECHECK(EINTR)); - if (ret == 0) - return FSIO_BLOCK; - if (ret < 0) - return FSIO_ERROR; - return FSIO_READY; -} - -XtransConnInfo -_fs_connect(char *servername, int *err) -{ - XtransConnInfo trans_conn; /* transport connection object */ - int ret; - int i = 0; - int retries = 5; - - /* - * Open the network connection. - */ - if( (trans_conn=_FontTransOpenCOTSClient(servername)) == NULL ) - { - *err = FSIO_ERROR; - return 0; - } - - /* - * Set the connection non-blocking since we use select() to block. - */ - - _FontTransSetOption(trans_conn, TRANS_NONBLOCKING, 1); - - do { - i = _FontTransConnect(trans_conn,servername); - } while ((i == TRANS_TRY_CONNECT_AGAIN) && (retries-- > 0)); - - if (i < 0) - { - if (i == TRANS_IN_PROGRESS) - ret = FSIO_BLOCK; - else - ret = FSIO_ERROR; - } - else - ret = FSIO_READY; - - if (ret == FSIO_ERROR) - { - _FontTransClose(trans_conn); - trans_conn = 0; - } - - *err = ret; - return trans_conn; -} - -static int -_fs_fill (FSFpePtr conn) -{ - long avail; - long bytes_read; - Bool waited = FALSE; - - if (_fs_flush (conn) < 0) - return FSIO_ERROR; - /* - * Don't go overboard here; stop reading when we've - * got enough to satisfy the pending request - */ - while ((conn->inNeed - (conn->inBuf.insert - conn->inBuf.remove)) > 0) - { - avail = conn->inBuf.size - conn->inBuf.insert; - /* - * For SVR4 with a unix-domain connection, ETEST() after selecting - * readable means the server has died. To do this here, we look for - * two consecutive reads returning ETEST(). - */ - ESET (0); - bytes_read =_FontTransRead(conn->trans_conn, - conn->inBuf.buf + conn->inBuf.insert, - avail); - if (bytes_read > 0) { - conn->inBuf.insert += bytes_read; - waited = FALSE; - } - else - { - if (bytes_read == 0 || ETEST ()) - { - if (!waited) - { - waited = TRUE; - if (_fs_wait_for_readable (conn, 0) == FSIO_BLOCK) - return FSIO_BLOCK; - continue; - } - } - _fs_connection_died (conn); - return FSIO_ERROR; - } - } - return FSIO_READY; -} - -/* - * Make space and return whether data have already arrived - */ - -int -_fs_start_read (FSFpePtr conn, long size, char **buf) -{ - int ret; - - conn->inNeed = size; - if (fs_inqueued(conn) < size) - { - if (_fs_resize (&conn->inBuf, size) != FSIO_READY) - { - _fs_connection_died (conn); - return FSIO_ERROR; - } - ret = _fs_fill (conn); - if (ret == FSIO_ERROR) - return ret; - if (ret == FSIO_BLOCK || fs_inqueued(conn) < size) - return FSIO_BLOCK; - } - if (buf) - *buf = conn->inBuf.buf + conn->inBuf.remove; - return FSIO_READY; -} - -void -_fs_done_read (FSFpePtr conn, long size) -{ - if (conn->inBuf.insert - conn->inBuf.remove < size) - { -#ifdef DEBUG - fprintf (stderr, "_fs_done_read skipping to many bytes\n"); -#endif - return; - } - conn->inBuf.remove += size; - conn->inNeed -= size; - _fs_downsize (&conn->inBuf, FS_BUF_MAX); -} - -long -_fs_pad_length (long len) -{ - return len + padlength[len&3]; -} - -int -_fs_flush (FSFpePtr conn) -{ - long bytes_written; - long remain; - - /* XXX - hack. The right fix is to remember that the font server - has gone away when we first discovered it. */ - if (conn->fs_fd < 0) - return FSIO_ERROR; - - while ((remain = conn->outBuf.insert - conn->outBuf.remove) > 0) - { - bytes_written = _FontTransWrite(conn->trans_conn, - conn->outBuf.buf + conn->outBuf.remove, - (int) remain); - if (bytes_written > 0) - { - conn->outBuf.remove += bytes_written; - } - else - { - if (bytes_written == 0 || ETEST ()) - { - conn->brokenWriteTime = GetTimeInMillis () + FS_FLUSH_POLL; - _fs_mark_block (conn, FS_BROKEN_WRITE); - break; - } - if (!ECHECK (EINTR)) - { - _fs_connection_died (conn); - return FSIO_ERROR; - } - } - } - if (conn->outBuf.remove == conn->outBuf.insert) - { - _fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE); - if (conn->outBuf.size > FS_BUF_INC) - conn->outBuf.buf = realloc (conn->outBuf.buf, FS_BUF_INC); - conn->outBuf.remove = conn->outBuf.insert = 0; - } - return FSIO_READY; -} - -static int -_fs_resize (FSBufPtr buf, long size) -{ - char *new; - long new_size; - - if (buf->remove) - { - if (buf->remove != buf->insert) - { - memmove (buf->buf, - buf->buf + buf->remove, - buf->insert - buf->remove); - } - buf->insert -= buf->remove; - buf->remove = 0; - } - if (buf->size - buf->remove < size) - { - new_size = ((buf->remove + size + FS_BUF_INC) / FS_BUF_INC) * FS_BUF_INC; - new = realloc (buf->buf, new_size); - if (!new) - return FSIO_ERROR; - buf->buf = new; - buf->size = new_size; - } - return FSIO_READY; -} - -static void -_fs_downsize (FSBufPtr buf, long size) -{ - if (buf->insert == buf->remove) - { - buf->insert = buf->remove = 0; - if (buf->size > size) - { - buf->buf = realloc (buf->buf, size); - buf->size = size; - } - } -} - -void -_fs_io_reinit (FSFpePtr conn) -{ - conn->outBuf.insert = conn->outBuf.remove = 0; - _fs_downsize (&conn->outBuf, FS_BUF_INC); - conn->inBuf.insert = conn->inBuf.remove = 0; - _fs_downsize (&conn->inBuf, FS_BUF_MAX); -} - -Bool -_fs_io_init (FSFpePtr conn) -{ - conn->outBuf.insert = conn->outBuf.remove = 0; - conn->outBuf.buf = malloc (FS_BUF_INC); - if (!conn->outBuf.buf) - return FALSE; - conn->outBuf.size = FS_BUF_INC; - - conn->inBuf.insert = conn->inBuf.remove = 0; - conn->inBuf.buf = malloc (FS_BUF_INC); - if (!conn->inBuf.buf) - { - free (conn->outBuf.buf); - conn->outBuf.buf = 0; - return FALSE; - } - conn->inBuf.size = FS_BUF_INC; - - return TRUE; -} - -void -_fs_io_fini (FSFpePtr conn) -{ - if (conn->outBuf.buf) - free (conn->outBuf.buf); - if (conn->inBuf.buf) - free (conn->inBuf.buf); -} - -static int -_fs_do_write(FSFpePtr conn, char *data, long len, long size) -{ - if (size == 0) { -#ifdef DEBUG - fprintf(stderr, "tried to write 0 bytes \n"); -#endif - return FSIO_READY; - } - - if (conn->fs_fd == -1) - return FSIO_ERROR; - - while (conn->outBuf.insert + size > conn->outBuf.size) - { - if (_fs_flush (conn) < 0) - return FSIO_ERROR; - if (_fs_resize (&conn->outBuf, size) < 0) - { - _fs_connection_died (conn); - return FSIO_ERROR; - } - } - memcpy (conn->outBuf.buf + conn->outBuf.insert, data, len); - /* Clear pad data */ - memset (conn->outBuf.buf + conn->outBuf.insert + len, 0, size - len); - conn->outBuf.insert += size; - _fs_mark_block (conn, FS_PENDING_WRITE); - return FSIO_READY; -} - -/* - * Write the indicated bytes - */ -int -_fs_write (FSFpePtr conn, char *data, long len) -{ - return _fs_do_write (conn, data, len, len); -} - -/* - * Write the indicated bytes adding any appropriate pad - */ -int -_fs_write_pad(FSFpePtr conn, char *data, long len) -{ - return _fs_do_write (conn, data, len, len + padlength[len & 3]); -} - -int -_fs_wait_for_readable(FSFpePtr conn, int ms) -{ - fd_set r_mask; - fd_set e_mask; - int result; - struct timeval tv; - - for (;;) { - if (conn->fs_fd < 0) - return FSIO_ERROR; - FD_ZERO(&r_mask); - FD_ZERO(&e_mask); - tv.tv_sec = ms / 1000; - tv.tv_usec = (ms % 1000) * 1000; - FD_SET(conn->fs_fd, &r_mask); - FD_SET(conn->fs_fd, &e_mask); - result = Select(conn->fs_fd + 1, &r_mask, NULL, &e_mask, &tv); - if (result < 0) - { - if (ECHECK(EINTR) || ECHECK(EAGAIN)) - continue; - else - return FSIO_ERROR; - } - if (result == 0) - return FSIO_BLOCK; - if (FD_ISSET(conn->fs_fd, &r_mask)) - return FSIO_READY; - return FSIO_ERROR; - } -} +/*
+ * Copyright 1990 Network Computing Devices
+ *
+ * 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, and that the name of Network Computing Devices not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. Network Computing
+ * Devices makes no representations about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+ * OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Dave Lemke, Network Computing Devices, Inc
+ */
+/*
+ * font server i/o routines
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef WIN32
+#define _WILLWINSOCK_
+#include "X11/Xwinsock.h"
+#include "X11/Xwindows.h"
+#endif
+
+#define FONT_t
+#define TRANS_CLIENT
+#include "X11/Xtrans/Xtrans.h"
+#include "X11/Xpoll.h"
+#include <X11/fonts/FS.h>
+#include <X11/fonts/FSproto.h>
+#include <X11/fonts/fontmisc.h>
+#include <X11/fonts/fontstruct.h>
+#include "fservestr.h"
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#if !defined(WIN32)
+#ifndef Lynx
+#include <sys/socket.h>
+#else
+#include <socket.h>
+#endif
+#endif
+#include <errno.h>
+#ifdef WIN32
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#undef EINTR
+#define EINTR WSAEINTR
+#endif
+
+
+
+static int padlength[4] = {0, 3, 2, 1};
+fd_set _fs_fd_mask;
+
+static int
+_fs_resize (FSBufPtr buf, long size);
+
+static void
+_fs_downsize (FSBufPtr buf, long size);
+
+int
+_fs_poll_connect (XtransConnInfo trans_conn, int timeout)
+{
+ fd_set w_mask;
+ struct timeval tv;
+ int fs_fd = _FontTransGetConnectionNumber (trans_conn);
+ int ret;
+
+ do
+ {
+ tv.tv_usec = 0;
+ tv.tv_sec = timeout;
+ FD_ZERO (&w_mask);
+ FD_SET (fs_fd, &w_mask);
+ ret = Select (fs_fd + 1, NULL, &w_mask, NULL, &tv);
+ } while (ret < 0 && ECHECK(EINTR));
+ if (ret == 0)
+ return FSIO_BLOCK;
+ if (ret < 0)
+ return FSIO_ERROR;
+ return FSIO_READY;
+}
+
+XtransConnInfo
+_fs_connect(char *servername, int *err)
+{
+ XtransConnInfo trans_conn; /* transport connection object */
+ int ret;
+ int i = 0;
+ int retries = 5;
+
+ /*
+ * Open the network connection.
+ */
+ if( (trans_conn=_FontTransOpenCOTSClient(servername)) == NULL )
+ {
+ *err = FSIO_ERROR;
+ return 0;
+ }
+
+ /*
+ * Set the connection non-blocking since we use select() to block.
+ */
+
+ _FontTransSetOption(trans_conn, TRANS_NONBLOCKING, 1);
+
+ do {
+ i = _FontTransConnect(trans_conn,servername);
+ } while ((i == TRANS_TRY_CONNECT_AGAIN) && (retries-- > 0));
+
+ if (i < 0)
+ {
+ if (i == TRANS_IN_PROGRESS)
+ ret = FSIO_BLOCK;
+ else
+ ret = FSIO_ERROR;
+ }
+ else
+ ret = FSIO_READY;
+
+ if (ret == FSIO_ERROR)
+ {
+ _FontTransClose(trans_conn);
+ trans_conn = 0;
+ }
+
+ *err = ret;
+ return trans_conn;
+}
+
+static int
+_fs_fill (FSFpePtr conn)
+{
+ long avail;
+ long bytes_read;
+ Bool waited = FALSE;
+
+ if (_fs_flush (conn) < 0)
+ return FSIO_ERROR;
+ /*
+ * Don't go overboard here; stop reading when we've
+ * got enough to satisfy the pending request
+ */
+ while ((conn->inNeed - (conn->inBuf.insert - conn->inBuf.remove)) > 0)
+ {
+ avail = conn->inBuf.size - conn->inBuf.insert;
+ /*
+ * For SVR4 with a unix-domain connection, ETEST() after selecting
+ * readable means the server has died. To do this here, we look for
+ * two consecutive reads returning ETEST().
+ */
+ ESET (0);
+ bytes_read =_FontTransRead(conn->trans_conn,
+ conn->inBuf.buf + conn->inBuf.insert,
+ avail);
+ if (bytes_read > 0) {
+ conn->inBuf.insert += bytes_read;
+ waited = FALSE;
+ }
+ else
+ {
+ if (bytes_read == 0 || ETEST ())
+ {
+ if (!waited)
+ {
+ waited = TRUE;
+ if (_fs_wait_for_readable (conn, 0) == FSIO_BLOCK)
+ return FSIO_BLOCK;
+ continue;
+ }
+ }
+ _fs_connection_died (conn);
+ return FSIO_ERROR;
+ }
+ }
+ return FSIO_READY;
+}
+
+/*
+ * Make space and return whether data have already arrived
+ */
+
+int
+_fs_start_read (FSFpePtr conn, long size, char **buf)
+{
+ int ret;
+
+ conn->inNeed = size;
+ if (fs_inqueued(conn) < size)
+ {
+ if (_fs_resize (&conn->inBuf, size) != FSIO_READY)
+ {
+ _fs_connection_died (conn);
+ return FSIO_ERROR;
+ }
+ ret = _fs_fill (conn);
+ if (ret == FSIO_ERROR)
+ return ret;
+ if (ret == FSIO_BLOCK || fs_inqueued(conn) < size)
+ return FSIO_BLOCK;
+ }
+ if (buf)
+ *buf = conn->inBuf.buf + conn->inBuf.remove;
+ return FSIO_READY;
+}
+
+void
+_fs_done_read (FSFpePtr conn, long size)
+{
+ if (conn->inBuf.insert - conn->inBuf.remove < size)
+ {
+#ifdef DEBUG
+ fprintf (stderr, "_fs_done_read skipping to many bytes\n");
+#endif
+ return;
+ }
+ conn->inBuf.remove += size;
+ conn->inNeed -= size;
+ _fs_downsize (&conn->inBuf, FS_BUF_MAX);
+}
+
+long
+_fs_pad_length (long len)
+{
+ return len + padlength[len&3];
+}
+
+int
+_fs_flush (FSFpePtr conn)
+{
+ long bytes_written;
+ long remain;
+
+ /* XXX - hack. The right fix is to remember that the font server
+ has gone away when we first discovered it. */
+ if (conn->fs_fd < 0)
+ return FSIO_ERROR;
+
+ while ((remain = conn->outBuf.insert - conn->outBuf.remove) > 0)
+ {
+ bytes_written = _FontTransWrite(conn->trans_conn,
+ conn->outBuf.buf + conn->outBuf.remove,
+ (int) remain);
+ if (bytes_written > 0)
+ {
+ conn->outBuf.remove += bytes_written;
+ }
+ else
+ {
+ if (bytes_written == 0 || ETEST ())
+ {
+ conn->brokenWriteTime = GetTimeInMillis () + FS_FLUSH_POLL;
+ _fs_mark_block (conn, FS_BROKEN_WRITE);
+ break;
+ }
+ if (!ECHECK (EINTR))
+ {
+ _fs_connection_died (conn);
+ return FSIO_ERROR;
+ }
+ }
+ }
+ if (conn->outBuf.remove == conn->outBuf.insert)
+ {
+ _fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE);
+ if (conn->outBuf.size > FS_BUF_INC)
+ conn->outBuf.buf = realloc (conn->outBuf.buf, FS_BUF_INC);
+ conn->outBuf.remove = conn->outBuf.insert = 0;
+ }
+ return FSIO_READY;
+}
+
+static int
+_fs_resize (FSBufPtr buf, long size)
+{
+ char *new;
+ long new_size;
+
+ if (buf->remove)
+ {
+ if (buf->remove != buf->insert)
+ {
+ memmove (buf->buf,
+ buf->buf + buf->remove,
+ buf->insert - buf->remove);
+ }
+ buf->insert -= buf->remove;
+ buf->remove = 0;
+ }
+ if (buf->size - buf->remove < size)
+ {
+ new_size = ((buf->remove + size + FS_BUF_INC) / FS_BUF_INC) * FS_BUF_INC;
+ new = realloc (buf->buf, new_size);
+ if (!new)
+ return FSIO_ERROR;
+ buf->buf = new;
+ buf->size = new_size;
+ }
+ return FSIO_READY;
+}
+
+static void
+_fs_downsize (FSBufPtr buf, long size)
+{
+ if (buf->insert == buf->remove)
+ {
+ buf->insert = buf->remove = 0;
+ if (buf->size > size)
+ {
+ buf->buf = realloc (buf->buf, size);
+ buf->size = size;
+ }
+ }
+}
+
+void
+_fs_io_reinit (FSFpePtr conn)
+{
+ conn->outBuf.insert = conn->outBuf.remove = 0;
+ _fs_downsize (&conn->outBuf, FS_BUF_INC);
+ conn->inBuf.insert = conn->inBuf.remove = 0;
+ _fs_downsize (&conn->inBuf, FS_BUF_MAX);
+}
+
+Bool
+_fs_io_init (FSFpePtr conn)
+{
+ conn->outBuf.insert = conn->outBuf.remove = 0;
+ conn->outBuf.buf = malloc (FS_BUF_INC);
+ if (!conn->outBuf.buf)
+ return FALSE;
+ conn->outBuf.size = FS_BUF_INC;
+
+ conn->inBuf.insert = conn->inBuf.remove = 0;
+ conn->inBuf.buf = malloc (FS_BUF_INC);
+ if (!conn->inBuf.buf)
+ {
+ free (conn->outBuf.buf);
+ conn->outBuf.buf = 0;
+ return FALSE;
+ }
+ conn->inBuf.size = FS_BUF_INC;
+
+ return TRUE;
+}
+
+void
+_fs_io_fini (FSFpePtr conn)
+{
+ if (conn->outBuf.buf)
+ free (conn->outBuf.buf);
+ if (conn->inBuf.buf)
+ free (conn->inBuf.buf);
+}
+
+static int
+_fs_do_write(FSFpePtr conn, char *data, long len, long size)
+{
+ if (size == 0) {
+#ifdef DEBUG
+ fprintf(stderr, "tried to write 0 bytes \n");
+#endif
+ return FSIO_READY;
+ }
+
+ if (conn->fs_fd == -1)
+ return FSIO_ERROR;
+
+ while (conn->outBuf.insert + size > conn->outBuf.size)
+ {
+ if (_fs_flush (conn) < 0)
+ return FSIO_ERROR;
+ if (_fs_resize (&conn->outBuf, size) < 0)
+ {
+ _fs_connection_died (conn);
+ return FSIO_ERROR;
+ }
+ }
+ memcpy (conn->outBuf.buf + conn->outBuf.insert, data, len);
+ /* Clear pad data */
+ memset (conn->outBuf.buf + conn->outBuf.insert + len, 0, size - len);
+ conn->outBuf.insert += size;
+ _fs_mark_block (conn, FS_PENDING_WRITE);
+ return FSIO_READY;
+}
+
+/*
+ * Write the indicated bytes
+ */
+int
+_fs_write (FSFpePtr conn, char *data, long len)
+{
+ return _fs_do_write (conn, data, len, len);
+}
+
+/*
+ * Write the indicated bytes adding any appropriate pad
+ */
+int
+_fs_write_pad(FSFpePtr conn, char *data, long len)
+{
+ return _fs_do_write (conn, data, len, len + padlength[len & 3]);
+}
+
+int
+_fs_wait_for_readable(FSFpePtr conn, int ms)
+{
+ fd_set r_mask;
+ fd_set e_mask;
+ int result;
+ struct timeval tv;
+
+ for (;;) {
+ if (conn->fs_fd < 0)
+ return FSIO_ERROR;
+ FD_ZERO(&r_mask);
+ FD_ZERO(&e_mask);
+ tv.tv_sec = ms / 1000;
+ tv.tv_usec = (ms % 1000) * 1000;
+ FD_SET(conn->fs_fd, &r_mask);
+ FD_SET(conn->fs_fd, &e_mask);
+ result = Select(conn->fs_fd + 1, &r_mask, NULL, &e_mask, &tv);
+ if (result < 0)
+ {
+ if (ECHECK(EINTR) || ECHECK(EAGAIN))
+ continue;
+ else
+ return FSIO_ERROR;
+ }
+ if (result == 0)
+ return FSIO_BLOCK;
+ if (FD_ISSET(conn->fs_fd, &r_mask))
+ return FSIO_READY;
+ return FSIO_ERROR;
+ }
+}
diff --git a/libXfont/src/fc/fsio.h b/libXfont/src/fc/fsio.h index bd0c621e8..0105e4909 100644 --- a/libXfont/src/fc/fsio.h +++ b/libXfont/src/fc/fsio.h @@ -1,178 +1,178 @@ -/* - * Copyright 1990 Network Computing Devices - * - * 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, and that the name of Network Computing Devices not be - * used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. Network Computing - * Devices makes no representations about the suitability of this software - * for any purpose. It is provided "as is" without express or implied - * warranty. - * - * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, - * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE - * OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Dave Lemke, Network Computing Devices, Inc - */ - -#ifndef _FSIO_H_ -#define _FSIO_H_ - -#undef DEBUG -#define REQUEST_LOG_SIZE 100 - -typedef struct _fs_fpe_alternate { - char *name; - Bool subset; -} FSFpeAltRec, *FSFpeAltPtr; - - -/* Per client access contexts */ -typedef struct _fs_client_data { - pointer client; - struct _fs_client_data *next; - XID acid; - int auth_generation; -} FSClientRec, *FSClientPtr; - -#define FS_RECONNECT_POLL 1000 -#define FS_RECONNECT_WAIT 5000 -#define FS_GIVEUP_WAIT 20000 -#define FS_REQUEST_TIMEOUT 20000 -#define FS_OPEN_TIMEOUT 30000 -#define FS_REOPEN_TIMEOUT 10000 -#define FS_FLUSH_POLL 1000 - -typedef struct _fs_buf { - char *buf; /* data */ - long size; /* sizeof data */ - long insert; /* where to insert new data */ - long remove; /* where to remove old data */ -} FSBufRec, *FSBufPtr; - -#define FS_BUF_INC 1024 -#define FS_BUF_MAX 32768 - -#define FS_PENDING_WRITE 0x01 /* some write data is queued */ -#define FS_BROKEN_WRITE 0x02 /* writes are broken */ -#define FS_BROKEN_CONNECTION 0x04 /* connection is broken */ -#define FS_PENDING_REPLY 0x08 /* waiting for a reply */ -#define FS_GIVE_UP 0x10 /* font server declared useless */ -#define FS_COMPLETE_REPLY 0x20 /* complete reply ready */ -#define FS_RECONNECTING 0x40 - -#define FS_CONN_UNCONNECTED 0 -#define FS_CONN_CONNECTING 1 -#define FS_CONN_CONNECTED 2 -#define FS_CONN_SENT_PREFIX 3 -#define FS_CONN_RECV_INIT 4 -#define FS_CONN_SENT_CAT 5 -#define FS_CONN_RUNNING 6 - -/* FS specific font FontPathElement data */ -typedef struct _fs_fpe_data { - FSFpePtr next; /* list of all active fs fpes */ - int fs_fd; /* < 0 when not running */ - int fs_conn_state; /* connection state */ - int current_seq; - char *servername; - Bool has_catalogues; - - int generation; - int numAlts; - int alternate; /* which alternate is in use +1 */ - int fsMajorVersion; /* font server major version number */ - FSFpeAltPtr alts; - - FSClientPtr clients; - XID curacid; -#ifdef DEBUG - int reqindex; - struct { - int opcode; - int sequence; - } reqbuffer[REQUEST_LOG_SIZE]; -#endif - FSBufRec outBuf; /* request queue */ - FSBufRec inBuf; /* reply queue */ - long inNeed; /* amount needed for reply */ - - CARD32 blockState; - CARD32 blockedReplyTime; /* time to abort blocked read */ - CARD32 brokenWriteTime; /* time to retry broken write */ - CARD32 blockedConnectTime; /* time to abort blocked connect */ - CARD32 brokenConnectionTime; /* time to retry broken connection */ - - FSBlockDataPtr blockedRequests; - - struct _XtransConnInfo *trans_conn; /* transport connection object */ -} FSFpeRec; - -#define fs_outspace(conn) ((conn)->outBuf.size - (conn)->outBuf.insert) -#define fs_outqueued(conn) ((conn)->outBuf.insert - (conn)->outBuf.remove) -#define fs_inqueued(conn) ((conn)->inBuf.insert - (conn)->inBuf.remove) -#define fs_needsflush(conn) (fs_outqueued(conn) != 0) -#define fs_needsfill(conn) (fs_inqueued(conn) < (conn)->inNeed) -#define fs_needsconnect(conn) ((conn)->fs_fd < 0) -#define fs_data_read(conn) ((conn)->inBuf.insert - (conn)->inBuf.remove) - -#define FSIO_READY 1 -#define FSIO_BLOCK 0 -#define FSIO_ERROR -1 - -extern Bool _fs_reopen_server ( FSFpePtr conn ); -extern int _fs_write ( FSFpePtr conn, char *data, long size ); -extern int _fs_write_pad ( FSFpePtr conn, char *data, long len ); -extern int _fs_wait_for_readable ( FSFpePtr conn, int ms ); -extern long _fs_pad_length (long len); - -extern void _fs_connection_died ( FSFpePtr conn ); - -extern int _fs_flush (FSFpePtr conn); -extern void _fs_mark_block (FSFpePtr conn, CARD32 mask); -extern void _fs_unmark_block (FSFpePtr conn, CARD32 mask); -extern void _fs_done_read (FSFpePtr conn, long size); -extern void _fs_io_reinit (FSFpePtr conn); -extern int _fs_start_read (FSFpePtr conn, long size, char **buf); -extern Bool _fs_io_init (FSFpePtr conn); -extern void _fs_io_fini (FSFpePtr conn); -extern int _fs_poll_connect (XtransConnInfo trans_conn, int timeout); -extern XtransConnInfo _fs_connect(char *servername, int *ret); - -/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX - * systems are broken and return EWOULDBLOCK when they should return EAGAIN - */ -#ifdef WIN32 -#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK) -#else -#if defined(EAGAIN) && defined(EWOULDBLOCK) -#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK) -#else -#ifdef EAGAIN -#define ETEST() (errno == EAGAIN) -#else -#define ETEST() (errno == EWOULDBLOCK) -#endif -#endif -#endif -#ifdef WIN32 -#define ECHECK(err) (WSAGetLastError() == err) -#define ESET(val) WSASetLastError(val) -#else -#ifdef ISC -#define ECHECK(err) ((errno == err) || ETEST()) -#else -#define ECHECK(err) (errno == err) -#endif -#define ESET(val) errno = val -#endif - -#endif /* _FSIO_H_ */ +/*
+ * Copyright 1990 Network Computing Devices
+ *
+ * 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, and that the name of Network Computing Devices not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. Network Computing
+ * Devices makes no representations about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+ * OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Dave Lemke, Network Computing Devices, Inc
+ */
+
+#ifndef _FSIO_H_
+#define _FSIO_H_
+
+#undef DEBUG
+#define REQUEST_LOG_SIZE 100
+
+typedef struct _fs_fpe_alternate {
+ char *name;
+ Bool subset;
+} FSFpeAltRec, *FSFpeAltPtr;
+
+
+/* Per client access contexts */
+typedef struct _fs_client_data {
+ pointer client;
+ struct _fs_client_data *next;
+ XID acid;
+ int auth_generation;
+} FSClientRec, *FSClientPtr;
+
+#define FS_RECONNECT_POLL 1000
+#define FS_RECONNECT_WAIT 5000
+#define FS_GIVEUP_WAIT 20000
+#define FS_REQUEST_TIMEOUT 20000
+#define FS_OPEN_TIMEOUT 30000
+#define FS_REOPEN_TIMEOUT 10000
+#define FS_FLUSH_POLL 1000
+
+typedef struct _fs_buf {
+ char *buf; /* data */
+ long size; /* sizeof data */
+ long insert; /* where to insert new data */
+ long remove; /* where to remove old data */
+} FSBufRec, *FSBufPtr;
+
+#define FS_BUF_INC 1024
+#define FS_BUF_MAX 32768
+
+#define FS_PENDING_WRITE 0x01 /* some write data is queued */
+#define FS_BROKEN_WRITE 0x02 /* writes are broken */
+#define FS_BROKEN_CONNECTION 0x04 /* connection is broken */
+#define FS_PENDING_REPLY 0x08 /* waiting for a reply */
+#define FS_GIVE_UP 0x10 /* font server declared useless */
+#define FS_COMPLETE_REPLY 0x20 /* complete reply ready */
+#define FS_RECONNECTING 0x40
+
+#define FS_CONN_UNCONNECTED 0
+#define FS_CONN_CONNECTING 1
+#define FS_CONN_CONNECTED 2
+#define FS_CONN_SENT_PREFIX 3
+#define FS_CONN_RECV_INIT 4
+#define FS_CONN_SENT_CAT 5
+#define FS_CONN_RUNNING 6
+
+/* FS specific font FontPathElement data */
+typedef struct _fs_fpe_data {
+ FSFpePtr next; /* list of all active fs fpes */
+ int fs_fd; /* < 0 when not running */
+ int fs_conn_state; /* connection state */
+ int current_seq;
+ char *servername;
+ Bool has_catalogues;
+
+ int generation;
+ int numAlts;
+ int alternate; /* which alternate is in use +1 */
+ int fsMajorVersion; /* font server major version number */
+ FSFpeAltPtr alts;
+
+ FSClientPtr clients;
+ XID curacid;
+#ifdef DEBUG
+ int reqindex;
+ struct {
+ int opcode;
+ int sequence;
+ } reqbuffer[REQUEST_LOG_SIZE];
+#endif
+ FSBufRec outBuf; /* request queue */
+ FSBufRec inBuf; /* reply queue */
+ long inNeed; /* amount needed for reply */
+
+ CARD32 blockState;
+ CARD32 blockedReplyTime; /* time to abort blocked read */
+ CARD32 brokenWriteTime; /* time to retry broken write */
+ CARD32 blockedConnectTime; /* time to abort blocked connect */
+ CARD32 brokenConnectionTime; /* time to retry broken connection */
+
+ FSBlockDataPtr blockedRequests;
+
+ struct _XtransConnInfo *trans_conn; /* transport connection object */
+} FSFpeRec;
+
+#define fs_outspace(conn) ((conn)->outBuf.size - (conn)->outBuf.insert)
+#define fs_outqueued(conn) ((conn)->outBuf.insert - (conn)->outBuf.remove)
+#define fs_inqueued(conn) ((conn)->inBuf.insert - (conn)->inBuf.remove)
+#define fs_needsflush(conn) (fs_outqueued(conn) != 0)
+#define fs_needsfill(conn) (fs_inqueued(conn) < (conn)->inNeed)
+#define fs_needsconnect(conn) ((conn)->fs_fd < 0)
+#define fs_data_read(conn) ((conn)->inBuf.insert - (conn)->inBuf.remove)
+
+#define FSIO_READY 1
+#define FSIO_BLOCK 0
+#define FSIO_ERROR -1
+
+extern Bool _fs_reopen_server ( FSFpePtr conn );
+extern int _fs_write ( FSFpePtr conn, char *data, long size );
+extern int _fs_write_pad ( FSFpePtr conn, char *data, long len );
+extern int _fs_wait_for_readable ( FSFpePtr conn, int ms );
+extern long _fs_pad_length (long len);
+
+extern void _fs_connection_died ( FSFpePtr conn );
+
+extern int _fs_flush (FSFpePtr conn);
+extern void _fs_mark_block (FSFpePtr conn, CARD32 mask);
+extern void _fs_unmark_block (FSFpePtr conn, CARD32 mask);
+extern void _fs_done_read (FSFpePtr conn, long size);
+extern void _fs_io_reinit (FSFpePtr conn);
+extern int _fs_start_read (FSFpePtr conn, long size, char **buf);
+extern Bool _fs_io_init (FSFpePtr conn);
+extern void _fs_io_fini (FSFpePtr conn);
+extern int _fs_poll_connect (XtransConnInfo trans_conn, int timeout);
+extern XtransConnInfo _fs_connect(char *servername, int *ret);
+
+/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
+ * systems are broken and return EWOULDBLOCK when they should return EAGAIN
+ */
+#ifdef WIN32
+#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK)
+#else
+#if defined(EAGAIN) && defined(EWOULDBLOCK)
+#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK)
+#else
+#ifdef EAGAIN
+#define ETEST() (errno == EAGAIN)
+#else
+#define ETEST() (errno == EWOULDBLOCK)
+#endif
+#endif
+#endif
+#ifdef WIN32
+#define ECHECK(err) (WSAGetLastError() == err)
+#define ESET(val) WSASetLastError(val)
+#else
+#ifdef ISC
+#define ECHECK(err) ((errno == err) || ETEST())
+#else
+#define ECHECK(err) (errno == err)
+#endif
+#define ESET(val) errno = val
+#endif
+
+#endif /* _FSIO_H_ */
diff --git a/libXfont/src/fc/fslibos.h b/libXfont/src/fc/fslibos.h index c49f52e5b..c7c745616 100644 --- a/libXfont/src/fc/fslibos.h +++ b/libXfont/src/fc/fslibos.h @@ -1,218 +1,218 @@ -/* - * Copyright 1990 Network Computing Devices; - * Portions Copyright 1987 by Digital Equipment Corporation - */ - -/* - -Copyright 1987, 1994, 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. - -*/ - -/* - * FSlib networking & os include file - */ - -#include <X11/Xtrans/Xtrans.h> - -#ifndef WIN32 - -/* - * makedepend screws up on #undef OPEN_MAX, so we define a new symbol - */ - -#ifndef FONT_OPEN_MAX - -#ifndef X_NOT_POSIX -# ifdef _POSIX_SOURCE -# include <limits.h> -# else -# define _POSIX_SOURCE -# include <limits.h> -# undef _POSIX_SOURCE -# endif -#endif -#ifndef SIZE_MAX -# ifdef ULONG_MAX -# define SIZE_MAX ULONG_MAX -# else -# define SIZE_MAX UINT_MAX -# endif -#endif -#ifndef OPEN_MAX -#if defined(SVR4) -#define OPEN_MAX 256 -#else -#include <sys/param.h> -#ifndef OPEN_MAX -#ifdef __OSF1__ -#define OPEN_MAX 256 -#else -#ifdef NOFILE -#define OPEN_MAX NOFILE -#else -#define OPEN_MAX NOFILES_MAX -#endif -#endif -#endif -#endif -#endif - -#if OPEN_MAX > 256 -#define FONT_OPEN_MAX 256 -#else -#define FONT_OPEN_MAX OPEN_MAX -#endif - -#endif /* FONT_OPEN_MAX */ - -#ifdef WORD64 -#define NMSKBITS 64 -#else -#define NMSKBITS 32 -#endif - -#define MSKCNT ((FONT_OPEN_MAX + NMSKBITS - 1) / NMSKBITS) - -typedef unsigned long FdSet[MSKCNT]; -typedef FdSet FdSetPtr; - -#if (MSKCNT==1) -#define BITMASK(i) (1 << (i)) -#define MASKIDX(i) 0 -#endif - -#if (MSKCNT>1) -#define BITMASK(i) (1 << ((i) & (NMSKBITS - 1))) -#define MASKIDX(i) ((i) / NMSKBITS) -#endif - -#define MASKWORD(buf, i) buf[MASKIDX(i)] -#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) -#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) -#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) - -#if (MSKCNT==1) -#define COPYBITS(src, dst) dst[0] = src[0] -#define CLEARBITS(buf) buf[0] = 0 -#define MASKANDSETBITS(dst, b1, b2) dst[0] = (b1[0] & b2[0]) -#define ORBITS(dst, b1, b2) dst[0] = (b1[0] | b2[0]) -#define UNSETBITS(dst, b1) (dst[0] &= ~b1[0]) -#define ANYSET(src) (src[0]) -#endif - -#if (MSKCNT==2) -#define COPYBITS(src, dst) { dst[0] = src[0]; dst[1] = src[1]; } -#define CLEARBITS(buf) { buf[0] = 0; buf[1] = 0; } -#define MASKANDSETBITS(dst, b1, b2) {\ - dst[0] = (b1[0] & b2[0]);\ - dst[1] = (b1[1] & b2[1]); } -#define ORBITS(dst, b1, b2) {\ - dst[0] = (b1[0] | b2[0]);\ - dst[1] = (b1[1] | b2[1]); } -#define UNSETBITS(dst, b1) {\ - dst[0] &= ~b1[0]; \ - dst[1] &= ~b1[1]; } -#define ANYSET(src) (src[0] || src[1]) -#endif - -#if (MSKCNT==3) -#define COPYBITS(src, dst) { dst[0] = src[0]; dst[1] = src[1]; \ - dst[2] = src[2]; } -#define CLEARBITS(buf) { buf[0] = 0; buf[1] = 0; buf[2] = 0; } -#define MASKANDSETBITS(dst, b1, b2) {\ - dst[0] = (b1[0] & b2[0]);\ - dst[1] = (b1[1] & b2[1]);\ - dst[2] = (b1[2] & b2[2]); } -#define ORBITS(dst, b1, b2) {\ - dst[0] = (b1[0] | b2[0]);\ - dst[1] = (b1[1] | b2[1]);\ - dst[2] = (b1[2] | b2[2]); } -#define UNSETBITS(dst, b1) {\ - dst[0] &= ~b1[0]; \ - dst[1] &= ~b1[1]; \ - dst[2] &= ~b1[2]; } -#define ANYSET(src) (src[0] || src[1] || src[2]) -#endif - -#if (MSKCNT==4) -#define COPYBITS(src, dst) dst[0] = src[0]; dst[1] = src[1]; \ - dst[2] = src[2]; dst[3] = src[3] -#define CLEARBITS(buf) buf[0] = 0; buf[1] = 0; buf[2] = 0; buf[3] = 0 -#define MASKANDSETBITS(dst, b1, b2) \ - dst[0] = (b1[0] & b2[0]);\ - dst[1] = (b1[1] & b2[1]);\ - dst[2] = (b1[2] & b2[2]);\ - dst[3] = (b1[3] & b2[3]) -#define ORBITS(dst, b1, b2) \ - dst[0] = (b1[0] | b2[0]);\ - dst[1] = (b1[1] | b2[1]);\ - dst[2] = (b1[2] | b2[2]);\ - dst[3] = (b1[3] | b2[3]) -#define UNSETBITS(dst, b1) \ - dst[0] &= ~b1[0]; \ - dst[1] &= ~b1[1]; \ - dst[2] &= ~b1[2]; \ - dst[3] &= ~b1[3] -#define ANYSET(src) (src[0] || src[1] || src[2] || src[3]) -#endif - -#if (MSKCNT>4) -#define COPYBITS(src, dst) memmove((caddr_t) dst, (caddr_t) src,\ - MSKCNT*sizeof(long)) -#define CLEARBITS(buf) bzero((caddr_t) buf, MSKCNT*sizeof(long)) -#define MASKANDSETBITS(dst, b1, b2) \ - { int cri; \ - for (cri=MSKCNT; --cri>=0; ) \ - dst[cri] = (b1[cri] & b2[cri]); } -#define ORBITS(dst, b1, b2) \ - { int cri; \ - for (cri=MSKCNT; --cri>=0; ) \ - dst[cri] = (b1[cri] | b2[cri]); } -#define UNSETBITS(dst, b1) \ - { int cri; \ - for (cri=MSKCNT; --cri>=0; ) \ - dst[cri] &= ~b1[cri]; } -#if (MSKCNT==8) -#define ANYSET(src) (src[0] || src[1] || src[2] || src[3] || \ - src[4] || src[5] || src[6] || src[7]) -#endif -#endif - -#else /* not WIN32 */ - -#include <X11/Xwinsock.h> -#include <X11/Xw32defs.h> - -typedef fd_set FdSet; -typedef FdSet *FdSetPtr; - -#define CLEARBITS(set) FD_ZERO(&set) -#define BITSET(set,s) FD_SET(s,&set) -#define BITCLEAR(set,s) FD_CLR(s,&set) -#define GETBIT(set,s) FD_ISSET(s,&set) -#define ANYSET(set) set->fd_count - -#endif +/*
+ * Copyright 1990 Network Computing Devices;
+ * Portions Copyright 1987 by Digital Equipment Corporation
+ */
+
+/*
+
+Copyright 1987, 1994, 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.
+
+*/
+
+/*
+ * FSlib networking & os include file
+ */
+
+#include <X11/Xtrans/Xtrans.h>
+
+#ifndef WIN32
+
+/*
+ * makedepend screws up on #undef OPEN_MAX, so we define a new symbol
+ */
+
+#ifndef FONT_OPEN_MAX
+
+#ifndef X_NOT_POSIX
+# ifdef _POSIX_SOURCE
+# include <limits.h>
+# else
+# define _POSIX_SOURCE
+# include <limits.h>
+# undef _POSIX_SOURCE
+# endif
+#endif
+#ifndef SIZE_MAX
+# ifdef ULONG_MAX
+# define SIZE_MAX ULONG_MAX
+# else
+# define SIZE_MAX UINT_MAX
+# endif
+#endif
+#ifndef OPEN_MAX
+#if defined(SVR4)
+#define OPEN_MAX 256
+#else
+#include <sys/param.h>
+#ifndef OPEN_MAX
+#ifdef __OSF1__
+#define OPEN_MAX 256
+#else
+#ifdef NOFILE
+#define OPEN_MAX NOFILE
+#else
+#define OPEN_MAX NOFILES_MAX
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#if OPEN_MAX > 256
+#define FONT_OPEN_MAX 256
+#else
+#define FONT_OPEN_MAX OPEN_MAX
+#endif
+
+#endif /* FONT_OPEN_MAX */
+
+#ifdef WORD64
+#define NMSKBITS 64
+#else
+#define NMSKBITS 32
+#endif
+
+#define MSKCNT ((FONT_OPEN_MAX + NMSKBITS - 1) / NMSKBITS)
+
+typedef unsigned long FdSet[MSKCNT];
+typedef FdSet FdSetPtr;
+
+#if (MSKCNT==1)
+#define BITMASK(i) (1 << (i))
+#define MASKIDX(i) 0
+#endif
+
+#if (MSKCNT>1)
+#define BITMASK(i) (1 << ((i) & (NMSKBITS - 1)))
+#define MASKIDX(i) ((i) / NMSKBITS)
+#endif
+
+#define MASKWORD(buf, i) buf[MASKIDX(i)]
+#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
+#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
+#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
+
+#if (MSKCNT==1)
+#define COPYBITS(src, dst) dst[0] = src[0]
+#define CLEARBITS(buf) buf[0] = 0
+#define MASKANDSETBITS(dst, b1, b2) dst[0] = (b1[0] & b2[0])
+#define ORBITS(dst, b1, b2) dst[0] = (b1[0] | b2[0])
+#define UNSETBITS(dst, b1) (dst[0] &= ~b1[0])
+#define ANYSET(src) (src[0])
+#endif
+
+#if (MSKCNT==2)
+#define COPYBITS(src, dst) { dst[0] = src[0]; dst[1] = src[1]; }
+#define CLEARBITS(buf) { buf[0] = 0; buf[1] = 0; }
+#define MASKANDSETBITS(dst, b1, b2) {\
+ dst[0] = (b1[0] & b2[0]);\
+ dst[1] = (b1[1] & b2[1]); }
+#define ORBITS(dst, b1, b2) {\
+ dst[0] = (b1[0] | b2[0]);\
+ dst[1] = (b1[1] | b2[1]); }
+#define UNSETBITS(dst, b1) {\
+ dst[0] &= ~b1[0]; \
+ dst[1] &= ~b1[1]; }
+#define ANYSET(src) (src[0] || src[1])
+#endif
+
+#if (MSKCNT==3)
+#define COPYBITS(src, dst) { dst[0] = src[0]; dst[1] = src[1]; \
+ dst[2] = src[2]; }
+#define CLEARBITS(buf) { buf[0] = 0; buf[1] = 0; buf[2] = 0; }
+#define MASKANDSETBITS(dst, b1, b2) {\
+ dst[0] = (b1[0] & b2[0]);\
+ dst[1] = (b1[1] & b2[1]);\
+ dst[2] = (b1[2] & b2[2]); }
+#define ORBITS(dst, b1, b2) {\
+ dst[0] = (b1[0] | b2[0]);\
+ dst[1] = (b1[1] | b2[1]);\
+ dst[2] = (b1[2] | b2[2]); }
+#define UNSETBITS(dst, b1) {\
+ dst[0] &= ~b1[0]; \
+ dst[1] &= ~b1[1]; \
+ dst[2] &= ~b1[2]; }
+#define ANYSET(src) (src[0] || src[1] || src[2])
+#endif
+
+#if (MSKCNT==4)
+#define COPYBITS(src, dst) dst[0] = src[0]; dst[1] = src[1]; \
+ dst[2] = src[2]; dst[3] = src[3]
+#define CLEARBITS(buf) buf[0] = 0; buf[1] = 0; buf[2] = 0; buf[3] = 0
+#define MASKANDSETBITS(dst, b1, b2) \
+ dst[0] = (b1[0] & b2[0]);\
+ dst[1] = (b1[1] & b2[1]);\
+ dst[2] = (b1[2] & b2[2]);\
+ dst[3] = (b1[3] & b2[3])
+#define ORBITS(dst, b1, b2) \
+ dst[0] = (b1[0] | b2[0]);\
+ dst[1] = (b1[1] | b2[1]);\
+ dst[2] = (b1[2] | b2[2]);\
+ dst[3] = (b1[3] | b2[3])
+#define UNSETBITS(dst, b1) \
+ dst[0] &= ~b1[0]; \
+ dst[1] &= ~b1[1]; \
+ dst[2] &= ~b1[2]; \
+ dst[3] &= ~b1[3]
+#define ANYSET(src) (src[0] || src[1] || src[2] || src[3])
+#endif
+
+#if (MSKCNT>4)
+#define COPYBITS(src, dst) memmove((caddr_t) dst, (caddr_t) src,\
+ MSKCNT*sizeof(long))
+#define CLEARBITS(buf) bzero((caddr_t) buf, MSKCNT*sizeof(long))
+#define MASKANDSETBITS(dst, b1, b2) \
+ { int cri; \
+ for (cri=MSKCNT; --cri>=0; ) \
+ dst[cri] = (b1[cri] & b2[cri]); }
+#define ORBITS(dst, b1, b2) \
+ { int cri; \
+ for (cri=MSKCNT; --cri>=0; ) \
+ dst[cri] = (b1[cri] | b2[cri]); }
+#define UNSETBITS(dst, b1) \
+ { int cri; \
+ for (cri=MSKCNT; --cri>=0; ) \
+ dst[cri] &= ~b1[cri]; }
+#if (MSKCNT==8)
+#define ANYSET(src) (src[0] || src[1] || src[2] || src[3] || \
+ src[4] || src[5] || src[6] || src[7])
+#endif
+#endif
+
+#else /* not WIN32 */
+
+#include <X11/Xwinsock.h>
+#include <X11/Xw32defs.h>
+
+typedef fd_set FdSet;
+typedef FdSet *FdSetPtr;
+
+#define CLEARBITS(set) FD_ZERO(&set)
+#define BITSET(set,s) FD_SET(s,&set)
+#define BITCLEAR(set,s) FD_CLR(s,&set)
+#define GETBIT(set,s) FD_ISSET(s,&set)
+#define ANYSET(set) set->fd_count
+
+#endif
diff --git a/libXfont/src/fc/fstrans.c b/libXfont/src/fc/fstrans.c index c334c2504..74a884e63 100644 --- a/libXfont/src/fc/fstrans.c +++ b/libXfont/src/fc/fstrans.c @@ -22,6 +22,7 @@ #ifdef HAVE_CONFIG_H #include <config.h> +#include <dix-config.h> #endif #define FONT_t #define TRANS_CLIENT diff --git a/libXfont/src/fc/makefile b/libXfont/src/fc/makefile new file mode 100644 index 000000000..a4b105d26 --- /dev/null +++ b/libXfont/src/fc/makefile @@ -0,0 +1,10 @@ + +INCLUDES := ../.. $(INCLUDES) + +LIBRARY = libfc + +CSRCS =\ + fsconvert.c \ + fserve.c \ + fsio.c \ + fstrans.c diff --git a/libXfont/src/fontfile/bitsource.c b/libXfont/src/fontfile/bitsource.c index 1b79c2bcb..f6ceb2aba 100644 --- a/libXfont/src/fontfile/bitsource.c +++ b/libXfont/src/fontfile/bitsource.c @@ -1,171 +1,171 @@ -/* - -Copyright 1991, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fntfilst.h> - -BitmapSourcesRec FontFileBitmapSources; - -Bool -FontFileRegisterBitmapSource (FontPathElementPtr fpe) -{ - FontPathElementPtr *new; - int i; - int newsize; - - for (i = 0; i < FontFileBitmapSources.count; i++) - if (FontFileBitmapSources.fpe[i] == fpe) - return TRUE; - if (FontFileBitmapSources.count == FontFileBitmapSources.size) - { - newsize = FontFileBitmapSources.size + 4; - new = realloc (FontFileBitmapSources.fpe, newsize * sizeof *new); - if (!new) - return FALSE; - FontFileBitmapSources.size = newsize; - FontFileBitmapSources.fpe = new; - } - FontFileBitmapSources.fpe[FontFileBitmapSources.count++] = fpe; - return TRUE; -} - -void -FontFileUnregisterBitmapSource (FontPathElementPtr fpe) -{ - int i; - - for (i = 0; i < FontFileBitmapSources.count; i++) - if (FontFileBitmapSources.fpe[i] == fpe) - { - FontFileBitmapSources.count--; - if (FontFileBitmapSources.count == 0) - { - FontFileBitmapSources.size = 0; - free (FontFileBitmapSources.fpe); - FontFileBitmapSources.fpe = 0; - } - else - { - for (; i < FontFileBitmapSources.count; i++) - FontFileBitmapSources.fpe[i] = FontFileBitmapSources.fpe[i+1]; - } - break; - } -} - -/* - * Our set_path_hook: unregister all bitmap sources. - * This is necessary because already open fonts will keep their FPEs - * allocated, but they may not be on the new font path. - * The bitmap sources in the new path will be registered by the init_func. - */ -void -FontFileEmptyBitmapSource(void) -{ - if (FontFileBitmapSources.count == 0) - return; - - FontFileBitmapSources.count = 0; - FontFileBitmapSources.size = 0; - free (FontFileBitmapSources.fpe); - FontFileBitmapSources.fpe = 0; -} - -int -FontFileMatchBitmapSource (FontPathElementPtr fpe, - FontPtr *pFont, - int flags, - FontEntryPtr entry, - FontNamePtr zeroPat, - FontScalablePtr vals, - fsBitmapFormat format, - fsBitmapFormatMask fmask, - Bool noSpecificSize) -{ - int source; - FontEntryPtr zero; - FontBitmapEntryPtr bitmap; - int ret; - FontDirectoryPtr dir; - FontScaledPtr scaled; - - /* - * Look through all the registered bitmap sources for - * the same zero name as ours; entries along that one - * can be scaled as desired. - */ - ret = BadFontName; - for (source = 0; source < FontFileBitmapSources.count; source++) - { - if (FontFileBitmapSources.fpe[source] == fpe) - continue; - dir = (FontDirectoryPtr) FontFileBitmapSources.fpe[source]->private; - zero = FontFileFindNameInDir (&dir->scalable, zeroPat); - if (!zero) - continue; - scaled = FontFileFindScaledInstance (zero, vals, noSpecificSize); - if (scaled) - { - if (scaled->pFont) - { - *pFont = scaled->pFont; - (*pFont)->fpe = FontFileBitmapSources.fpe[source]; - ret = Successful; - } - else if (scaled->bitmap) - { - entry = scaled->bitmap; - bitmap = &entry->u.bitmap; - if (bitmap->pFont) - { - *pFont = bitmap->pFont; - (*pFont)->fpe = FontFileBitmapSources.fpe[source]; - ret = Successful; - } - else - { - ret = FontFileOpenBitmap ( - FontFileBitmapSources.fpe[source], - pFont, flags, entry, format, fmask); - if (ret == Successful && *pFont) - (*pFont)->fpe = FontFileBitmapSources.fpe[source]; - } - } - else /* "cannot" happen */ - { - ret = BadFontName; - } - break; - } - } - return ret; -} +/*
+
+Copyright 1991, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fntfilst.h>
+
+BitmapSourcesRec FontFileBitmapSources;
+
+Bool
+FontFileRegisterBitmapSource (FontPathElementPtr fpe)
+{
+ FontPathElementPtr *new;
+ int i;
+ int newsize;
+
+ for (i = 0; i < FontFileBitmapSources.count; i++)
+ if (FontFileBitmapSources.fpe[i] == fpe)
+ return TRUE;
+ if (FontFileBitmapSources.count == FontFileBitmapSources.size)
+ {
+ newsize = FontFileBitmapSources.size + 4;
+ new = realloc (FontFileBitmapSources.fpe, newsize * sizeof *new);
+ if (!new)
+ return FALSE;
+ FontFileBitmapSources.size = newsize;
+ FontFileBitmapSources.fpe = new;
+ }
+ FontFileBitmapSources.fpe[FontFileBitmapSources.count++] = fpe;
+ return TRUE;
+}
+
+void
+FontFileUnregisterBitmapSource (FontPathElementPtr fpe)
+{
+ int i;
+
+ for (i = 0; i < FontFileBitmapSources.count; i++)
+ if (FontFileBitmapSources.fpe[i] == fpe)
+ {
+ FontFileBitmapSources.count--;
+ if (FontFileBitmapSources.count == 0)
+ {
+ FontFileBitmapSources.size = 0;
+ free (FontFileBitmapSources.fpe);
+ FontFileBitmapSources.fpe = 0;
+ }
+ else
+ {
+ for (; i < FontFileBitmapSources.count; i++)
+ FontFileBitmapSources.fpe[i] = FontFileBitmapSources.fpe[i+1];
+ }
+ break;
+ }
+}
+
+/*
+ * Our set_path_hook: unregister all bitmap sources.
+ * This is necessary because already open fonts will keep their FPEs
+ * allocated, but they may not be on the new font path.
+ * The bitmap sources in the new path will be registered by the init_func.
+ */
+void
+FontFileEmptyBitmapSource(void)
+{
+ if (FontFileBitmapSources.count == 0)
+ return;
+
+ FontFileBitmapSources.count = 0;
+ FontFileBitmapSources.size = 0;
+ free (FontFileBitmapSources.fpe);
+ FontFileBitmapSources.fpe = 0;
+}
+
+int
+FontFileMatchBitmapSource (FontPathElementPtr fpe,
+ FontPtr *pFont,
+ int flags,
+ FontEntryPtr entry,
+ FontNamePtr zeroPat,
+ FontScalablePtr vals,
+ fsBitmapFormat format,
+ fsBitmapFormatMask fmask,
+ Bool noSpecificSize)
+{
+ int source;
+ FontEntryPtr zero;
+ FontBitmapEntryPtr bitmap;
+ int ret;
+ FontDirectoryPtr dir;
+ FontScaledPtr scaled;
+
+ /*
+ * Look through all the registered bitmap sources for
+ * the same zero name as ours; entries along that one
+ * can be scaled as desired.
+ */
+ ret = BadFontName;
+ for (source = 0; source < FontFileBitmapSources.count; source++)
+ {
+ if (FontFileBitmapSources.fpe[source] == fpe)
+ continue;
+ dir = (FontDirectoryPtr) FontFileBitmapSources.fpe[source]->private;
+ zero = FontFileFindNameInDir (&dir->scalable, zeroPat);
+ if (!zero)
+ continue;
+ scaled = FontFileFindScaledInstance (zero, vals, noSpecificSize);
+ if (scaled)
+ {
+ if (scaled->pFont)
+ {
+ *pFont = scaled->pFont;
+ (*pFont)->fpe = FontFileBitmapSources.fpe[source];
+ ret = Successful;
+ }
+ else if (scaled->bitmap)
+ {
+ entry = scaled->bitmap;
+ bitmap = &entry->u.bitmap;
+ if (bitmap->pFont)
+ {
+ *pFont = bitmap->pFont;
+ (*pFont)->fpe = FontFileBitmapSources.fpe[source];
+ ret = Successful;
+ }
+ else
+ {
+ ret = FontFileOpenBitmap (
+ FontFileBitmapSources.fpe[source],
+ pFont, flags, entry, format, fmask);
+ if (ret == Successful && *pFont)
+ (*pFont)->fpe = FontFileBitmapSources.fpe[source];
+ }
+ }
+ else /* "cannot" happen */
+ {
+ ret = BadFontName;
+ }
+ break;
+ }
+ }
+ return ret;
+}
diff --git a/libXfont/src/fontfile/bufio.c b/libXfont/src/fontfile/bufio.c index 34b7f3665..8b880e150 100644 --- a/libXfont/src/fontfile/bufio.c +++ b/libXfont/src/fontfile/bufio.c @@ -1,203 +1,203 @@ -/* - -Copyright 1991, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/Xos.h> -#include <X11/fonts/fontmisc.h> -#include <X11/fonts/bufio.h> -#include <errno.h> - -BufFilePtr -BufFileCreate (char *private, - int (*input)(BufFilePtr), - int (*output)(int, BufFilePtr), - int (*skip)(BufFilePtr, int), - int (*close)(BufFilePtr, int)) -{ - BufFilePtr f; - - f = malloc (sizeof *f); - if (!f) - return 0; - f->private = private; - f->bufp = f->buffer; - f->left = 0; - f->input = input; - f->output = output; - f->skip = skip; - f->eof = 0; - f->close = close; - return f; -} - -#define FileDes(f) ((int)(long) (f)->private) - -static int -BufFileRawFill (BufFilePtr f) -{ - int left; - - left = read (FileDes(f), (char *)f->buffer, BUFFILESIZE); - if (left <= 0) { - f->left = 0; - return BUFFILEEOF; - } - f->left = left - 1; - f->bufp = f->buffer + 1; - return f->buffer[0]; -} - -static int -BufFileRawSkip (BufFilePtr f, int count) -{ - int curoff; - int fileoff; - int todo; - - curoff = f->bufp - f->buffer; - fileoff = curoff + f->left; - if (curoff + count <= fileoff) { - f->bufp += count; - f->left -= count; - } else { - todo = count - (fileoff - curoff); - if (lseek (FileDes(f), todo, 1) == -1) { - if (errno != ESPIPE) - return BUFFILEEOF; - while (todo) { - curoff = BUFFILESIZE; - if (curoff > todo) - curoff = todo; - fileoff = read (FileDes(f), (char *)f->buffer, curoff); - if (fileoff <= 0) - return BUFFILEEOF; - todo -= fileoff; - } - } - f->left = 0; - } - return count; -} - -static int -BufFileRawClose (BufFilePtr f, int doClose) -{ - if (doClose) - close (FileDes (f)); - return 1; -} - -BufFilePtr -BufFileOpenRead (int fd) -{ -#if defined (WIN32) - /* hv: I'd bet WIN32 has the same effect here */ - setmode(fd,O_BINARY); -#endif - return BufFileCreate ((char *)(long) fd, BufFileRawFill, 0, BufFileRawSkip, BufFileRawClose); -} - -static int -BufFileRawFlush (int c, BufFilePtr f) -{ - int cnt; - - if (c != BUFFILEEOF) - *f->bufp++ = c; - cnt = f->bufp - f->buffer; - f->bufp = f->buffer; - f->left = BUFFILESIZE; - if (write (FileDes(f), (char *)f->buffer, cnt) != cnt) - return BUFFILEEOF; - return c; -} - -static int -BufFileFlush (BufFilePtr f, int doClose) -{ - if (f->bufp != f->buffer) - return (*f->output) (BUFFILEEOF, f); - return 0; -} - -BufFilePtr -BufFileOpenWrite (int fd) -{ - BufFilePtr f; - -#if defined(WIN32) - /* hv: I'd bet WIN32 has the same effect here */ - setmode(fd,O_BINARY); -#endif - f = BufFileCreate ((char *)(long) fd, 0, BufFileRawFlush, 0, BufFileFlush); - f->bufp = f->buffer; - f->left = BUFFILESIZE; - return f; -} - -int -BufFileRead (BufFilePtr f, char *b, int n) -{ - int c, cnt; - cnt = n; - while (cnt--) { - c = BufFileGet (f); - if (c == BUFFILEEOF) - break; - *b++ = c; - } - return n - cnt - 1; -} - -int -BufFileWrite (BufFilePtr f, char *b, int n) -{ - int cnt; - cnt = n; - while (cnt--) { - if (BufFilePut (*b++, f) == BUFFILEEOF) - return BUFFILEEOF; - } - return n; -} - -int -BufFileClose (BufFilePtr f, int doClose) -{ - int ret; - ret = (*f->close) (f, doClose); - free (f); - return ret; -} +/*
+
+Copyright 1991, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/Xos.h>
+#include <X11/fonts/fontmisc.h>
+#include <X11/fonts/bufio.h>
+#include <errno.h>
+
+BufFilePtr
+BufFileCreate (char *private,
+ int (*input)(BufFilePtr),
+ int (*output)(int, BufFilePtr),
+ int (*skip)(BufFilePtr, int),
+ int (*close)(BufFilePtr, int))
+{
+ BufFilePtr f;
+
+ f = malloc (sizeof *f);
+ if (!f)
+ return 0;
+ f->private = private;
+ f->bufp = f->buffer;
+ f->left = 0;
+ f->input = input;
+ f->output = output;
+ f->skip = skip;
+ f->eof = 0;
+ f->close = close;
+ return f;
+}
+
+#define FileDes(f) ((int)(long) (f)->private)
+
+static int
+BufFileRawFill (BufFilePtr f)
+{
+ int left;
+
+ left = read (FileDes(f), (char *)f->buffer, BUFFILESIZE);
+ if (left <= 0) {
+ f->left = 0;
+ return BUFFILEEOF;
+ }
+ f->left = left - 1;
+ f->bufp = f->buffer + 1;
+ return f->buffer[0];
+}
+
+static int
+BufFileRawSkip (BufFilePtr f, int count)
+{
+ int curoff;
+ int fileoff;
+ int todo;
+
+ curoff = f->bufp - f->buffer;
+ fileoff = curoff + f->left;
+ if (curoff + count <= fileoff) {
+ f->bufp += count;
+ f->left -= count;
+ } else {
+ todo = count - (fileoff - curoff);
+ if (lseek (FileDes(f), todo, 1) == -1) {
+ if (errno != ESPIPE)
+ return BUFFILEEOF;
+ while (todo) {
+ curoff = BUFFILESIZE;
+ if (curoff > todo)
+ curoff = todo;
+ fileoff = read (FileDes(f), (char *)f->buffer, curoff);
+ if (fileoff <= 0)
+ return BUFFILEEOF;
+ todo -= fileoff;
+ }
+ }
+ f->left = 0;
+ }
+ return count;
+}
+
+static int
+BufFileRawClose (BufFilePtr f, int doClose)
+{
+ if (doClose)
+ close (FileDes (f));
+ return 1;
+}
+
+BufFilePtr
+BufFileOpenRead (int fd)
+{
+#if defined (WIN32)
+ /* hv: I'd bet WIN32 has the same effect here */
+ setmode(fd,O_BINARY);
+#endif
+ return BufFileCreate ((char *)(long) fd, BufFileRawFill, 0, BufFileRawSkip, BufFileRawClose);
+}
+
+static int
+BufFileRawFlush (int c, BufFilePtr f)
+{
+ int cnt;
+
+ if (c != BUFFILEEOF)
+ *f->bufp++ = c;
+ cnt = f->bufp - f->buffer;
+ f->bufp = f->buffer;
+ f->left = BUFFILESIZE;
+ if (write (FileDes(f), (char *)f->buffer, cnt) != cnt)
+ return BUFFILEEOF;
+ return c;
+}
+
+static int
+BufFileFlush (BufFilePtr f, int doClose)
+{
+ if (f->bufp != f->buffer)
+ return (*f->output) (BUFFILEEOF, f);
+ return 0;
+}
+
+BufFilePtr
+BufFileOpenWrite (int fd)
+{
+ BufFilePtr f;
+
+#if defined(WIN32)
+ /* hv: I'd bet WIN32 has the same effect here */
+ setmode(fd,O_BINARY);
+#endif
+ f = BufFileCreate ((char *)(long) fd, 0, BufFileRawFlush, 0, BufFileFlush);
+ f->bufp = f->buffer;
+ f->left = BUFFILESIZE;
+ return f;
+}
+
+int
+BufFileRead (BufFilePtr f, char *b, int n)
+{
+ int c, cnt;
+ cnt = n;
+ while (cnt--) {
+ c = BufFileGet (f);
+ if (c == BUFFILEEOF)
+ break;
+ *b++ = c;
+ }
+ return n - cnt - 1;
+}
+
+int
+BufFileWrite (BufFilePtr f, char *b, int n)
+{
+ int cnt;
+ cnt = n;
+ while (cnt--) {
+ if (BufFilePut (*b++, f) == BUFFILEEOF)
+ return BUFFILEEOF;
+ }
+ return n;
+}
+
+int
+BufFileClose (BufFilePtr f, int doClose)
+{
+ int ret;
+ ret = (*f->close) (f, doClose);
+ free (f);
+ return ret;
+}
diff --git a/libXfont/src/fontfile/catalogue.c b/libXfont/src/fontfile/catalogue.c index 3a04a754d..5ce8a0799 100644 --- a/libXfont/src/fontfile/catalogue.c +++ b/libXfont/src/fontfile/catalogue.c @@ -27,6 +27,7 @@ #ifdef HAVE_CONFIG_H #include <config.h> #endif +#include <X11/Xwindows.h> #include <X11/fonts/fntfilst.h> #include <sys/types.h> #include <sys/stat.h> @@ -140,7 +141,7 @@ CatalogueRescan (FontPathElementPtr fpe, Bool forceScan) int pathlen; path = fpe->name + strlen(CataloguePrefix); - if (stat(path, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode)) + if (stat(path, &statbuf) < 0 || (statbuf.st_mode&_S_IFDIR)) return BadFontPath; if ((forceScan == FALSE) && (statbuf.st_mtime <= cat->mtime)) @@ -154,6 +155,7 @@ CatalogueRescan (FontPathElementPtr fpe, Bool forceScan) } CatalogueUnrefFPEs (fpe); + #ifndef _MSC_VER while (entry = readdir(dir), entry != NULL) { snprintf(link, sizeof link, "%s/%s", path, entry->d_name); @@ -218,6 +220,7 @@ CatalogueRescan (FontPathElementPtr fpe, Bool forceScan) continue; } } + #endif closedir(dir); diff --git a/libXfont/src/fontfile/decompress.c b/libXfont/src/fontfile/decompress.c index b1fc37b85..b2fe6c707 100644 --- a/libXfont/src/fontfile/decompress.c +++ b/libXfont/src/fontfile/decompress.c @@ -1,408 +1,408 @@ -/* - * Copyright 1985, 1986 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * James A. Woods, derived from original work by Spencer Thomas - * and Joseph Orost. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -/* - -Copyright 1993, 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. - -*/ -/* - * decompress - cat a compressed file - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fontmisc.h> -#include <X11/fonts/bufio.h> - -#define BITS 16 - -/* - * a code_int must be able to hold 2**BITS values of type int, and also -1 - */ -#if BITS > 15 -typedef long int code_int; -#else -typedef int code_int; -#endif - -typedef long int count_int; - -#ifdef NO_UCHAR - typedef char char_type; -#else - typedef unsigned char char_type; -#endif /* UCHAR */ - -static char_type magic_header[] = { "\037\235" }; /* 1F 9D */ - -/* Defines for third byte of header */ -#define BIT_MASK 0x1f -#define BLOCK_MASK 0x80 -/* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is - a fourth header byte (for expansion). -*/ - -#define INIT_BITS 9 /* initial number of bits/code */ - -#ifdef COMPATIBLE /* But wrong! */ -# define MAXCODE(n_bits) (1 << (n_bits) - 1) -#else -# define MAXCODE(n_bits) ((1 << (n_bits)) - 1) -#endif /* COMPATIBLE */ - -/* - * the next two codes should not be changed lightly, as they must not - * lie within the contiguous general code space. - */ -#define FIRST 257 /* first free entry */ -#define CLEAR 256 /* table clear output code */ - -#define STACK_SIZE 8192 - -typedef struct _compressedFILE { - BufFilePtr file; - - char_type *stackp; - code_int oldcode; - char_type finchar; - - int block_compress; - int maxbits; - code_int maxcode, maxmaxcode; - - code_int free_ent; - int clear_flg; - int n_bits; - - /* bit buffer */ - int offset, size; - char_type buf[BITS]; - - char_type de_stack[STACK_SIZE]; - char_type *tab_suffix; - unsigned short *tab_prefix; -} CompressedFile; - - -static int hsize_table[] = { - 5003, /* 12 bits - 80% occupancy */ - 9001, /* 13 bits - 91% occupancy */ - 18013, /* 14 bits - 91% occupancy */ - 35023, /* 15 bits - 94% occupancy */ - 69001 /* 16 bits - 95% occupancy */ -}; - -static int BufCompressedClose ( BufFilePtr f, int doClose ); -static int BufCompressedFill ( BufFilePtr f ); -static code_int getcode ( CompressedFile *file ); -static int BufCompressedSkip ( BufFilePtr f, int bytes ); - -BufFilePtr -BufFilePushCompressed (BufFilePtr f) -{ - int code; - int maxbits; - int hsize; - CompressedFile *file; - int extra; - - if ((BufFileGet(f) != (magic_header[0] & 0xFF)) || - (BufFileGet(f) != (magic_header[1] & 0xFF))) - { - return 0; - } - code = BufFileGet (f); - if (code == BUFFILEEOF) return 0; - - maxbits = code & BIT_MASK; - if (maxbits > BITS || maxbits < 12) - return 0; - hsize = hsize_table[maxbits - 12]; - extra = (1 << maxbits) * sizeof (char_type) + - hsize * sizeof (unsigned short); - file = malloc (sizeof (CompressedFile) + extra); - if (!file) - return 0; - file->file = f; - file->maxbits = maxbits; - file->block_compress = code & BLOCK_MASK; - file->maxmaxcode = 1 << file->maxbits; - file->tab_suffix = (char_type *) &file[1]; - file->tab_prefix = (unsigned short *) (file->tab_suffix + file->maxmaxcode); - /* - * As above, initialize the first 256 entries in the table. - */ - file->maxcode = MAXCODE(file->n_bits = INIT_BITS); - for ( code = 255; code >= 0; code-- ) { - file->tab_prefix[code] = 0; - file->tab_suffix[code] = (char_type) code; - } - file->free_ent = ((file->block_compress) ? FIRST : 256 ); - file->clear_flg = 0; - file->offset = 0; - file->size = 0; - file->stackp = file->de_stack; - bzero(file->buf, BITS); - file->finchar = file->oldcode = getcode (file); - if (file->oldcode != -1) - *file->stackp++ = file->finchar; - return BufFileCreate ((char *) file, - BufCompressedFill, - 0, - BufCompressedSkip, - BufCompressedClose); -} - -static int -BufCompressedClose (BufFilePtr f, int doClose) -{ - CompressedFile *file; - BufFilePtr raw; - - file = (CompressedFile *) f->private; - raw = file->file; - free (file); - BufFileClose (raw, doClose); - return 1; -} - -static int -BufCompressedFill (BufFilePtr f) -{ - CompressedFile *file; - register char_type *stackp, *de_stack; - register char_type finchar; - register code_int code, oldcode, incode; - BufChar *buf, *bufend; - - file = (CompressedFile *) f->private; - - buf = f->buffer; - bufend = buf + BUFFILESIZE; - stackp = file->stackp; - de_stack = file->de_stack; - finchar = file->finchar; - oldcode = file->oldcode; - while (buf < bufend) { - while (stackp > de_stack && buf < bufend) - *buf++ = *--stackp; - - if (buf == bufend) - break; - - if (oldcode == -1) - break; - - code = getcode (file); - if (code == -1) - break; - - if ( (code == CLEAR) && file->block_compress ) { - for ( code = 255; code >= 0; code-- ) - file->tab_prefix[code] = 0; - file->clear_flg = 1; - file->free_ent = FIRST - 1; - if ( (code = getcode (file)) == -1 ) /* O, untimely death! */ - break; - } - incode = code; - /* - * Special case for KwKwK string. - */ - if ( code >= file->free_ent ) { - *stackp++ = finchar; - code = oldcode; - } - - /* - * Generate output characters in reverse order - */ - while ( code >= 256 ) - { - *stackp++ = file->tab_suffix[code]; - code = file->tab_prefix[code]; - } - finchar = file->tab_suffix[code]; - *stackp++ = finchar; - - /* - * Generate the new entry. - */ - if ( (code=file->free_ent) < file->maxmaxcode ) { - file->tab_prefix[code] = (unsigned short)oldcode; - file->tab_suffix[code] = finchar; - file->free_ent = code+1; - } - /* - * Remember previous code. - */ - oldcode = incode; - } - file->oldcode = oldcode; - file->stackp = stackp; - file->finchar = finchar; - if (buf == f->buffer) { - f->left = 0; - return BUFFILEEOF; - } - f->bufp = f->buffer + 1; - f->left = (buf - f->buffer) - 1; - return f->buffer[0]; -} - -/***************************************************************** - * TAG( getcode ) - * - * Read one code from the standard input. If BUFFILEEOF, return -1. - * Inputs: - * stdin - * Outputs: - * code or -1 is returned. - */ - -static char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; - -static code_int -getcode(CompressedFile *file) -{ - register code_int code; - register int r_off, bits; - register char_type *bp = file->buf; - register BufFilePtr raw; - - if ( file->clear_flg > 0 || file->offset >= file->size || - file->free_ent > file->maxcode ) - { - /* - * If the next entry will be too big for the current code - * size, then we must increase the size. This implies reading - * a new buffer full, too. - */ - if ( file->free_ent > file->maxcode ) { - file->n_bits++; - if ( file->n_bits == file->maxbits ) - file->maxcode = file->maxmaxcode; /* won't get any bigger now */ - else - file->maxcode = MAXCODE(file->n_bits); - } - if ( file->clear_flg > 0) { - file->maxcode = MAXCODE (file->n_bits = INIT_BITS); - file->clear_flg = 0; - } - bits = file->n_bits; - raw = file->file; - while (bits > 0 && (code = BufFileGet (raw)) != BUFFILEEOF) - { - *bp++ = code; - --bits; - } - bp = file->buf; - if (bits == file->n_bits) - return -1; /* end of file */ - file->size = file->n_bits - bits; - file->offset = 0; - /* Round size down to integral number of codes */ - file->size = (file->size << 3) - (file->n_bits - 1); - } - r_off = file->offset; - bits = file->n_bits; - /* - * Get to the first byte. - */ - bp += (r_off >> 3); - r_off &= 7; - /* Get first part (low order bits) */ -#ifdef NO_UCHAR - code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff; -#else - code = (*bp++ >> r_off); -#endif /* NO_UCHAR */ - bits -= (8 - r_off); - r_off = 8 - r_off; /* now, offset into code word */ - /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ - if ( bits >= 8 ) { -#ifdef NO_UCHAR - code |= (*bp++ & 0xff) << r_off; -#else - code |= *bp++ << r_off; -#endif /* NO_UCHAR */ - r_off += 8; - bits -= 8; - } - /* high order bits. */ - code |= (*bp & rmask[bits]) << r_off; - file->offset += file->n_bits; - - return code; -} - -static int -BufCompressedSkip (BufFilePtr f, int bytes) -{ - int c; - while (bytes--) - { - c = BufFileGet(f); - if (c == BUFFILEEOF) - return BUFFILEEOF; - } - return 0; -} - -#ifdef TEST -int -main (int argc, char *argv[]) -{ - BufFilePtr inputraw, input, output; - int c; - - inputraw = BufFileOpenRead (0); - input = BufFilePushCompressed (inputraw); - output = BufFileOpenWrite (1); - while ((c = BufFileGet (input)) != BUFFILEEOF) - BufFilePut (c, output); - BufFileClose (input, FALSE); - BufFileClose (output, FALSE); - return 0; -} -#endif +/*
+ * Copyright 1985, 1986 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James A. Woods, derived from original work by Spencer Thomas
+ * and Joseph Orost.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+
+Copyright 1993, 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.
+
+*/
+/*
+ * decompress - cat a compressed file
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fontmisc.h>
+#include <X11/fonts/bufio.h>
+
+#define BITS 16
+
+/*
+ * a code_int must be able to hold 2**BITS values of type int, and also -1
+ */
+#if BITS > 15
+typedef long int code_int;
+#else
+typedef int code_int;
+#endif
+
+typedef long int count_int;
+
+#ifdef NO_UCHAR
+ typedef char char_type;
+#else
+ typedef unsigned char char_type;
+#endif /* UCHAR */
+
+static char_type magic_header[] = { "\037\235" }; /* 1F 9D */
+
+/* Defines for third byte of header */
+#define BIT_MASK 0x1f
+#define BLOCK_MASK 0x80
+/* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
+ a fourth header byte (for expansion).
+*/
+
+#define INIT_BITS 9 /* initial number of bits/code */
+
+#ifdef COMPATIBLE /* But wrong! */
+# define MAXCODE(n_bits) (1 << (n_bits) - 1)
+#else
+# define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
+#endif /* COMPATIBLE */
+
+/*
+ * the next two codes should not be changed lightly, as they must not
+ * lie within the contiguous general code space.
+ */
+#define FIRST 257 /* first free entry */
+#define CLEAR 256 /* table clear output code */
+
+#define STACK_SIZE 8192
+
+typedef struct _compressedFILE {
+ BufFilePtr file;
+
+ char_type *stackp;
+ code_int oldcode;
+ char_type finchar;
+
+ int block_compress;
+ int maxbits;
+ code_int maxcode, maxmaxcode;
+
+ code_int free_ent;
+ int clear_flg;
+ int n_bits;
+
+ /* bit buffer */
+ int offset, size;
+ char_type buf[BITS];
+
+ char_type de_stack[STACK_SIZE];
+ char_type *tab_suffix;
+ unsigned short *tab_prefix;
+} CompressedFile;
+
+
+static int hsize_table[] = {
+ 5003, /* 12 bits - 80% occupancy */
+ 9001, /* 13 bits - 91% occupancy */
+ 18013, /* 14 bits - 91% occupancy */
+ 35023, /* 15 bits - 94% occupancy */
+ 69001 /* 16 bits - 95% occupancy */
+};
+
+static int BufCompressedClose ( BufFilePtr f, int doClose );
+static int BufCompressedFill ( BufFilePtr f );
+static code_int getcode ( CompressedFile *file );
+static int BufCompressedSkip ( BufFilePtr f, int bytes );
+
+BufFilePtr
+BufFilePushCompressed (BufFilePtr f)
+{
+ int code;
+ int maxbits;
+ int hsize;
+ CompressedFile *file;
+ int extra;
+
+ if ((BufFileGet(f) != (magic_header[0] & 0xFF)) ||
+ (BufFileGet(f) != (magic_header[1] & 0xFF)))
+ {
+ return 0;
+ }
+ code = BufFileGet (f);
+ if (code == BUFFILEEOF) return 0;
+
+ maxbits = code & BIT_MASK;
+ if (maxbits > BITS || maxbits < 12)
+ return 0;
+ hsize = hsize_table[maxbits - 12];
+ extra = (1 << maxbits) * sizeof (char_type) +
+ hsize * sizeof (unsigned short);
+ file = malloc (sizeof (CompressedFile) + extra);
+ if (!file)
+ return 0;
+ file->file = f;
+ file->maxbits = maxbits;
+ file->block_compress = code & BLOCK_MASK;
+ file->maxmaxcode = 1 << file->maxbits;
+ file->tab_suffix = (char_type *) &file[1];
+ file->tab_prefix = (unsigned short *) (file->tab_suffix + file->maxmaxcode);
+ /*
+ * As above, initialize the first 256 entries in the table.
+ */
+ file->maxcode = MAXCODE(file->n_bits = INIT_BITS);
+ for ( code = 255; code >= 0; code-- ) {
+ file->tab_prefix[code] = 0;
+ file->tab_suffix[code] = (char_type) code;
+ }
+ file->free_ent = ((file->block_compress) ? FIRST : 256 );
+ file->clear_flg = 0;
+ file->offset = 0;
+ file->size = 0;
+ file->stackp = file->de_stack;
+ bzero(file->buf, BITS);
+ file->finchar = file->oldcode = getcode (file);
+ if (file->oldcode != -1)
+ *file->stackp++ = file->finchar;
+ return BufFileCreate ((char *) file,
+ BufCompressedFill,
+ 0,
+ BufCompressedSkip,
+ BufCompressedClose);
+}
+
+static int
+BufCompressedClose (BufFilePtr f, int doClose)
+{
+ CompressedFile *file;
+ BufFilePtr raw;
+
+ file = (CompressedFile *) f->private;
+ raw = file->file;
+ free (file);
+ BufFileClose (raw, doClose);
+ return 1;
+}
+
+static int
+BufCompressedFill (BufFilePtr f)
+{
+ CompressedFile *file;
+ register char_type *stackp, *de_stack;
+ register char_type finchar;
+ register code_int code, oldcode, incode;
+ BufChar *buf, *bufend;
+
+ file = (CompressedFile *) f->private;
+
+ buf = f->buffer;
+ bufend = buf + BUFFILESIZE;
+ stackp = file->stackp;
+ de_stack = file->de_stack;
+ finchar = file->finchar;
+ oldcode = file->oldcode;
+ while (buf < bufend) {
+ while (stackp > de_stack && buf < bufend)
+ *buf++ = *--stackp;
+
+ if (buf == bufend)
+ break;
+
+ if (oldcode == -1)
+ break;
+
+ code = getcode (file);
+ if (code == -1)
+ break;
+
+ if ( (code == CLEAR) && file->block_compress ) {
+ for ( code = 255; code >= 0; code-- )
+ file->tab_prefix[code] = 0;
+ file->clear_flg = 1;
+ file->free_ent = FIRST - 1;
+ if ( (code = getcode (file)) == -1 ) /* O, untimely death! */
+ break;
+ }
+ incode = code;
+ /*
+ * Special case for KwKwK string.
+ */
+ if ( code >= file->free_ent ) {
+ *stackp++ = finchar;
+ code = oldcode;
+ }
+
+ /*
+ * Generate output characters in reverse order
+ */
+ while ( code >= 256 )
+ {
+ *stackp++ = file->tab_suffix[code];
+ code = file->tab_prefix[code];
+ }
+ finchar = file->tab_suffix[code];
+ *stackp++ = finchar;
+
+ /*
+ * Generate the new entry.
+ */
+ if ( (code=file->free_ent) < file->maxmaxcode ) {
+ file->tab_prefix[code] = (unsigned short)oldcode;
+ file->tab_suffix[code] = finchar;
+ file->free_ent = code+1;
+ }
+ /*
+ * Remember previous code.
+ */
+ oldcode = incode;
+ }
+ file->oldcode = oldcode;
+ file->stackp = stackp;
+ file->finchar = finchar;
+ if (buf == f->buffer) {
+ f->left = 0;
+ return BUFFILEEOF;
+ }
+ f->bufp = f->buffer + 1;
+ f->left = (buf - f->buffer) - 1;
+ return f->buffer[0];
+}
+
+/*****************************************************************
+ * TAG( getcode )
+ *
+ * Read one code from the standard input. If BUFFILEEOF, return -1.
+ * Inputs:
+ * stdin
+ * Outputs:
+ * code or -1 is returned.
+ */
+
+static char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
+
+static code_int
+getcode(CompressedFile *file)
+{
+ register code_int code;
+ register int r_off, bits;
+ register char_type *bp = file->buf;
+ register BufFilePtr raw;
+
+ if ( file->clear_flg > 0 || file->offset >= file->size ||
+ file->free_ent > file->maxcode )
+ {
+ /*
+ * If the next entry will be too big for the current code
+ * size, then we must increase the size. This implies reading
+ * a new buffer full, too.
+ */
+ if ( file->free_ent > file->maxcode ) {
+ file->n_bits++;
+ if ( file->n_bits == file->maxbits )
+ file->maxcode = file->maxmaxcode; /* won't get any bigger now */
+ else
+ file->maxcode = MAXCODE(file->n_bits);
+ }
+ if ( file->clear_flg > 0) {
+ file->maxcode = MAXCODE (file->n_bits = INIT_BITS);
+ file->clear_flg = 0;
+ }
+ bits = file->n_bits;
+ raw = file->file;
+ while (bits > 0 && (code = BufFileGet (raw)) != BUFFILEEOF)
+ {
+ *bp++ = code;
+ --bits;
+ }
+ bp = file->buf;
+ if (bits == file->n_bits)
+ return -1; /* end of file */
+ file->size = file->n_bits - bits;
+ file->offset = 0;
+ /* Round size down to integral number of codes */
+ file->size = (file->size << 3) - (file->n_bits - 1);
+ }
+ r_off = file->offset;
+ bits = file->n_bits;
+ /*
+ * Get to the first byte.
+ */
+ bp += (r_off >> 3);
+ r_off &= 7;
+ /* Get first part (low order bits) */
+#ifdef NO_UCHAR
+ code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
+#else
+ code = (*bp++ >> r_off);
+#endif /* NO_UCHAR */
+ bits -= (8 - r_off);
+ r_off = 8 - r_off; /* now, offset into code word */
+ /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
+ if ( bits >= 8 ) {
+#ifdef NO_UCHAR
+ code |= (*bp++ & 0xff) << r_off;
+#else
+ code |= *bp++ << r_off;
+#endif /* NO_UCHAR */
+ r_off += 8;
+ bits -= 8;
+ }
+ /* high order bits. */
+ code |= (*bp & rmask[bits]) << r_off;
+ file->offset += file->n_bits;
+
+ return code;
+}
+
+static int
+BufCompressedSkip (BufFilePtr f, int bytes)
+{
+ int c;
+ while (bytes--)
+ {
+ c = BufFileGet(f);
+ if (c == BUFFILEEOF)
+ return BUFFILEEOF;
+ }
+ return 0;
+}
+
+#ifdef TEST
+int
+main (int argc, char *argv[])
+{
+ BufFilePtr inputraw, input, output;
+ int c;
+
+ inputraw = BufFileOpenRead (0);
+ input = BufFilePushCompressed (inputraw);
+ output = BufFileOpenWrite (1);
+ while ((c = BufFileGet (input)) != BUFFILEEOF)
+ BufFilePut (c, output);
+ BufFileClose (input, FALSE);
+ BufFileClose (output, FALSE);
+ return 0;
+}
+#endif
diff --git a/libXfont/src/fontfile/defaults.c b/libXfont/src/fontfile/defaults.c index 1ad7d7ce5..b42024df3 100644 --- a/libXfont/src/fontfile/defaults.c +++ b/libXfont/src/fontfile/defaults.c @@ -1,74 +1,74 @@ -/* - -Copyright 1990, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/X.h> -#include <X11/Xproto.h> - -#ifndef DEFAULT_BIT_ORDER -#ifdef BITMAP_BIT_ORDER -#define DEFAULT_BIT_ORDER BITMAP_BIT_ORDER -#else -#define DEFAULT_BIT_ORDER MSBFirst -#endif -#endif - -#ifndef DEFAULT_BYTE_ORDER -#ifdef IMAGE_BYTE_ORDER -#define DEFAULT_BYTE_ORDER IMAGE_BYTE_ORDER -#else -#define DEFAULT_BYTE_ORDER MSBFirst -#endif -#endif - -#ifndef DEFAULT_GLYPH_PAD -#ifdef GLYPHPADBYTES -#define DEFAULT_GLYPH_PAD GLYPHPADBYTES -#else -#define DEFAULT_GLYPH_PAD 4 -#endif -#endif - -#ifndef DEFAULT_SCAN_UNIT -#define DEFAULT_SCAN_UNIT 1 -#endif - -#include <X11/fonts/fntfilst.h> - -void -FontDefaultFormat (int *bit, int *byte, int *glyph, int *scan) -{ - *bit = DEFAULT_BIT_ORDER; - *byte = DEFAULT_BYTE_ORDER; - *glyph = DEFAULT_GLYPH_PAD; - *scan = DEFAULT_SCAN_UNIT; -} +/*
+
+Copyright 1990, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/X.h>
+#include <X11/Xproto.h>
+
+#ifndef DEFAULT_BIT_ORDER
+#ifdef BITMAP_BIT_ORDER
+#define DEFAULT_BIT_ORDER BITMAP_BIT_ORDER
+#else
+#define DEFAULT_BIT_ORDER MSBFirst
+#endif
+#endif
+
+#ifndef DEFAULT_BYTE_ORDER
+#ifdef IMAGE_BYTE_ORDER
+#define DEFAULT_BYTE_ORDER IMAGE_BYTE_ORDER
+#else
+#define DEFAULT_BYTE_ORDER MSBFirst
+#endif
+#endif
+
+#ifndef DEFAULT_GLYPH_PAD
+#ifdef GLYPHPADBYTES
+#define DEFAULT_GLYPH_PAD GLYPHPADBYTES
+#else
+#define DEFAULT_GLYPH_PAD 4
+#endif
+#endif
+
+#ifndef DEFAULT_SCAN_UNIT
+#define DEFAULT_SCAN_UNIT 1
+#endif
+
+#include <X11/fonts/fntfilst.h>
+
+void
+FontDefaultFormat (int *bit, int *byte, int *glyph, int *scan)
+{
+ *bit = DEFAULT_BIT_ORDER;
+ *byte = DEFAULT_BYTE_ORDER;
+ *glyph = DEFAULT_GLYPH_PAD;
+ *scan = DEFAULT_SCAN_UNIT;
+}
diff --git a/libXfont/src/fontfile/dirfile.c b/libXfont/src/fontfile/dirfile.c index c8aff6f4f..50eb2faf5 100644 --- a/libXfont/src/fontfile/dirfile.c +++ b/libXfont/src/fontfile/dirfile.c @@ -1,492 +1,492 @@ -/* - -Copyright 1991, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -/* - * dirfile.c - * - * Read fonts.dir and fonts.alias files - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fntfilst.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> - -static Bool AddFileNameAliases ( FontDirectoryPtr dir ); -static int ReadFontAlias ( char *directory, Bool isFile, - FontDirectoryPtr *pdir ); -static int lexAlias ( FILE *file, char **lexToken ); -static int lexc ( FILE *file ); - -int -FontFileReadDirectory (char *directory, FontDirectoryPtr *pdir) -{ - char file_name[MAXFONTFILENAMELEN]; - char font_name[MAXFONTNAMELEN]; - char dir_file[MAXFONTFILENAMELEN]; - char dir_path[MAXFONTFILENAMELEN]; - char *ptr; - FILE *file; - int count, - num_fonts, - status; - struct stat statb; - static char format[24] = ""; -#if defined(WIN32) - int i; -#endif - - FontDirectoryPtr dir = NullFontDirectory; - - if (strlen(directory) + 1 + sizeof(FontDirFile) > sizeof(dir_file)) - return BadFontPath; - - /* Check for font directory attributes */ -#if !defined(WIN32) - if ((ptr = strchr(directory, ':'))) { -#else - /* OS/2 and WIN32 path might start with a drive letter, don't clip this */ - if ((ptr = strchr(directory+2, ':'))) { -#endif - strncpy(dir_path, directory, ptr - directory); - dir_path[ptr - directory] = '\0'; - } else { - strcpy(dir_path, directory); - } - strcpy(dir_file, dir_path); - if (dir_file[strlen(dir_file) - 1] != '/') - strcat(dir_file, "/"); - strcat(dir_file, FontDirFile); - file = fopen(dir_file, "rt"); - if (file) { -#ifndef WIN32 - if (fstat (fileno(file), &statb) == -1) -#else - if (stat (dir_file, &statb) == -1) -#endif - { - fclose(file); - return BadFontPath; - } - count = fscanf(file, "%d\n", &num_fonts); - if ((count == EOF) || (count != 1)) { - fclose(file); - return BadFontPath; - } - dir = FontFileMakeDir(directory, num_fonts); - if (dir == NULL) { - fclose(file); - return BadFontPath; - } - dir->dir_mtime = statb.st_mtime; - if (format[0] == '\0') - sprintf(format, "%%%ds %%%d[^\n]\n", - MAXFONTFILENAMELEN-1, MAXFONTNAMELEN-1); - - while ((count = fscanf(file, format, file_name, font_name)) != EOF) { -#if defined(WIN32) - /* strip any existing trailing CR */ - for (i=0; i<strlen(font_name); i++) { - if (font_name[i]=='\r') font_name[i] = '\0'; - } -#endif - if (count != 2) { - FontFileFreeDir (dir); - fclose(file); - return BadFontPath; - } - - /* - * We blindly try to load all the font files specified. - * In theory, we might want to warn that some of the fonts - * couldn't be loaded. - */ - FontFileAddFontFile (dir, font_name, file_name); - } - fclose(file); - - } else if (errno != ENOENT) { - return BadFontPath; - } - status = ReadFontAlias(dir_path, FALSE, &dir); - if (status != Successful) { - if (dir) - FontFileFreeDir (dir); - return status; - } - if (!dir) - return BadFontPath; - - FontFileSortDir(dir); - - *pdir = dir; - return Successful; -} - -Bool -FontFileDirectoryChanged(FontDirectoryPtr dir) -{ - char dir_file[MAXFONTFILENAMELEN]; - struct stat statb; - - if (strlen(dir->directory) + sizeof(FontDirFile) > sizeof(dir_file)) - return FALSE; - - strcpy (dir_file, dir->directory); - strcat (dir_file, FontDirFile); - if (stat (dir_file, &statb) == -1) - { - if (errno != ENOENT || dir->dir_mtime != 0) - return TRUE; - return FALSE; /* doesn't exist and never did: no change */ - } - if (dir->dir_mtime != statb.st_mtime) - return TRUE; - - if ((strlen(dir->directory) + sizeof(FontAliasFile)) > sizeof(dir_file)) - return FALSE; - strcpy (dir_file, dir->directory); - strcat (dir_file, FontAliasFile); - if (stat (dir_file, &statb) == -1) - { - if (errno != ENOENT || dir->alias_mtime != 0) - return TRUE; - return FALSE; /* doesn't exist and never did: no change */ - } - if (dir->alias_mtime != statb.st_mtime) - return TRUE; - return FALSE; -} - -/* - * Make each of the file names an automatic alias for each of the files. - */ - -static Bool -AddFileNameAliases(FontDirectoryPtr dir) -{ - int i; - char copy[MAXFONTFILENAMELEN]; - char *fileName; - FontTablePtr table; - FontRendererPtr renderer; - int len; - FontNameRec name; - - table = &dir->nonScalable; - for (i = 0; i < table->used; i++) { - if (table->entries[i].type != FONT_ENTRY_BITMAP) - continue; - fileName = table->entries[i].u.bitmap.fileName; - renderer = FontFileMatchRenderer (fileName); - if (!renderer) - continue; - - len = strlen (fileName) - renderer->fileSuffixLen; - if (len >= sizeof(copy)) - continue; - CopyISOLatin1Lowered (copy, fileName, len); - copy[len] = '\0'; - name.name = copy; - name.length = len; - name.ndashes = FontFileCountDashes (copy, len); - - if (!FontFileFindNameInDir(table, &name)) { - if (!FontFileAddFontAlias (dir, copy, table->entries[i].name.name)) - return FALSE; - } - } - return TRUE; -} - -/* - * parse the font.alias file. Format is: - * - * alias font-name - * - * To imbed white-space in an alias name, enclose it like "font name" - * in double quotes. \ escapes and character, so - * "font name \"With Double Quotes\" \\ and \\ back-slashes" - * works just fine. - * - * A line beginning with a ! denotes a newline-terminated comment. - */ - -/* - * token types - */ - -#define NAME 0 -#define NEWLINE 1 -#define DONE 2 -#define EALLOC 3 - -static int -ReadFontAlias(char *directory, Bool isFile, FontDirectoryPtr *pdir) -{ - char alias[MAXFONTNAMELEN]; - char font_name[MAXFONTNAMELEN]; - char alias_file[MAXFONTFILENAMELEN]; - FILE *file; - FontDirectoryPtr dir; - int token; - char *lexToken; - int status = Successful; - struct stat statb; - - if (strlen(directory) >= sizeof(alias_file)) - return BadFontPath; - dir = *pdir; - strcpy(alias_file, directory); - if (!isFile) { - if (strlen(directory) + 1 + sizeof(FontAliasFile) > sizeof(alias_file)) - return BadFontPath; - if (directory[strlen(directory) - 1] != '/') - strcat(alias_file, "/"); - strcat(alias_file, FontAliasFile); - } - file = fopen(alias_file, "rt"); - if (!file) - return ((errno == ENOENT) ? Successful : BadFontPath); - if (!dir) - *pdir = dir = FontFileMakeDir(directory, 10); - if (!dir) - { - fclose (file); - return AllocError; - } -#ifndef WIN32 - if (fstat (fileno (file), &statb) == -1) -#else - if (stat (alias_file, &statb) == -1) -#endif - { - fclose (file); - return BadFontPath; - } - dir->alias_mtime = statb.st_mtime; - while (status == Successful) { - token = lexAlias(file, &lexToken); - switch (token) { - case NEWLINE: - break; - case DONE: - fclose(file); - return Successful; - case EALLOC: - status = AllocError; - break; - case NAME: - if (strlen(lexToken) >= sizeof(alias)) { - status = BadFontPath; - break; - } - strcpy(alias, lexToken); - token = lexAlias(file, &lexToken); - switch (token) { - case NEWLINE: - if (strcmp(alias, "FILE_NAMES_ALIASES")) - status = BadFontPath; - else if (!AddFileNameAliases(dir)) - status = AllocError; - break; - case DONE: - status = BadFontPath; - break; - case EALLOC: - status = AllocError; - break; - case NAME: - if (strlen(lexToken) >= sizeof(font_name)) { - status = BadFontPath; - break; - } - CopyISOLatin1Lowered(alias, alias, strlen(alias)); - CopyISOLatin1Lowered(font_name, lexToken, strlen(lexToken)); - if (!FontFileAddFontAlias (dir, alias, font_name)) - status = AllocError; - break; - } - } - } - fclose(file); - return status; -} - -#define QUOTE 0 -#define WHITE 1 -#define NORMAL 2 -#define END 3 -#define NL 4 -#define BANG 5 - -static int charClass; - -static int -lexAlias(FILE *file, char **lexToken) -{ - int c; - char *t; - enum state { - Begin, Normal, Quoted, Comment - } state; - int count; - - static char *tokenBuf = (char *) NULL; - static int tokenSize = 0; - - t = tokenBuf; - count = 0; - state = Begin; - for (;;) { - if (count == tokenSize) { - int nsize; - char *nbuf; - - nsize = tokenSize ? (tokenSize << 1) : 64; - nbuf = realloc(tokenBuf, nsize); - if (!nbuf) - return EALLOC; - tokenBuf = nbuf; - tokenSize = nsize; - t = tokenBuf + count; - } - c = lexc(file); - switch (charClass) { - case QUOTE: - switch (state) { - case Begin: - case Normal: - state = Quoted; - break; - case Quoted: - state = Normal; - break; - case Comment: - break; - } - break; - case WHITE: - switch (state) { - case Begin: - case Comment: - continue; - case Normal: - *t = '\0'; - *lexToken = tokenBuf; - return NAME; - case Quoted: - break; - } - /* fall through */ - case NORMAL: - switch (state) { - case Begin: - state = Normal; - break; - case Comment: - continue; - default: - break; - } - *t++ = c; - ++count; - break; - case END: - case NL: - switch (state) { - case Begin: - case Comment: - *lexToken = (char *) NULL; - return charClass == END ? DONE : NEWLINE; - default: - *t = '\0'; - *lexToken = tokenBuf; - ungetc(c, file); - return NAME; - } - break; - case BANG: - switch (state) { - case Begin: - state = Comment; - break; - case Comment: - break; - default: - *t++ = c; - ++count; - } - break; - } - } -} - -static int -lexc(FILE *file) -{ - int c; - - c = getc(file); - switch (c) { - case EOF: - charClass = END; - break; - case '\\': - c = getc(file); - if (c == EOF) - charClass = END; - else - charClass = NORMAL; - break; - case '"': - charClass = QUOTE; - break; - case ' ': - case '\t': - charClass = WHITE; - break; - case '\r': - case '\n': - charClass = NL; - break; - case '!': - charClass = BANG; - break; - default: - charClass = NORMAL; - break; - } - return c; -} +/*
+
+Copyright 1991, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+/*
+ * dirfile.c
+ *
+ * Read fonts.dir and fonts.alias files
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fntfilst.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+static Bool AddFileNameAliases ( FontDirectoryPtr dir );
+static int ReadFontAlias ( char *directory, Bool isFile,
+ FontDirectoryPtr *pdir );
+static int lexAlias ( FILE *file, char **lexToken );
+static int lexc ( FILE *file );
+
+int
+FontFileReadDirectory (char *directory, FontDirectoryPtr *pdir)
+{
+ char file_name[MAXFONTFILENAMELEN];
+ char font_name[MAXFONTNAMELEN];
+ char dir_file[MAXFONTFILENAMELEN];
+ char dir_path[MAXFONTFILENAMELEN];
+ char *ptr;
+ FILE *file;
+ int count,
+ num_fonts,
+ status;
+ struct stat statb;
+ static char format[24] = "";
+#if defined(WIN32)
+ int i;
+#endif
+
+ FontDirectoryPtr dir = NullFontDirectory;
+
+ if (strlen(directory) + 1 + sizeof(FontDirFile) > sizeof(dir_file))
+ return BadFontPath;
+
+ /* Check for font directory attributes */
+#if !defined(WIN32)
+ if ((ptr = strchr(directory, ':'))) {
+#else
+ /* OS/2 and WIN32 path might start with a drive letter, don't clip this */
+ if ((ptr = strchr(directory+2, ':'))) {
+#endif
+ strncpy(dir_path, directory, ptr - directory);
+ dir_path[ptr - directory] = '\0';
+ } else {
+ strcpy(dir_path, directory);
+ }
+ strcpy(dir_file, dir_path);
+ if (dir_file[strlen(dir_file) - 1] != '/')
+ strcat(dir_file, "/");
+ strcat(dir_file, FontDirFile);
+ file = fopen(dir_file, "rt");
+ if (file) {
+#ifndef WIN32
+ if (fstat (fileno(file), &statb) == -1)
+#else
+ if (stat (dir_file, &statb) == -1)
+#endif
+ {
+ fclose(file);
+ return BadFontPath;
+ }
+ count = fscanf(file, "%d\n", &num_fonts);
+ if ((count == EOF) || (count != 1)) {
+ fclose(file);
+ return BadFontPath;
+ }
+ dir = FontFileMakeDir(directory, num_fonts);
+ if (dir == NULL) {
+ fclose(file);
+ return BadFontPath;
+ }
+ dir->dir_mtime = statb.st_mtime;
+ if (format[0] == '\0')
+ sprintf(format, "%%%ds %%%d[^\n]\n",
+ MAXFONTFILENAMELEN-1, MAXFONTNAMELEN-1);
+
+ while ((count = fscanf(file, format, file_name, font_name)) != EOF) {
+#if defined(WIN32)
+ /* strip any existing trailing CR */
+ for (i=0; i<strlen(font_name); i++) {
+ if (font_name[i]=='\r') font_name[i] = '\0';
+ }
+#endif
+ if (count != 2) {
+ FontFileFreeDir (dir);
+ fclose(file);
+ return BadFontPath;
+ }
+
+ /*
+ * We blindly try to load all the font files specified.
+ * In theory, we might want to warn that some of the fonts
+ * couldn't be loaded.
+ */
+ FontFileAddFontFile (dir, font_name, file_name);
+ }
+ fclose(file);
+
+ } else if (errno != ENOENT) {
+ return BadFontPath;
+ }
+ status = ReadFontAlias(dir_path, FALSE, &dir);
+ if (status != Successful) {
+ if (dir)
+ FontFileFreeDir (dir);
+ return status;
+ }
+ if (!dir)
+ return BadFontPath;
+
+ FontFileSortDir(dir);
+
+ *pdir = dir;
+ return Successful;
+}
+
+Bool
+FontFileDirectoryChanged(FontDirectoryPtr dir)
+{
+ char dir_file[MAXFONTFILENAMELEN];
+ struct stat statb;
+
+ if (strlen(dir->directory) + sizeof(FontDirFile) > sizeof(dir_file))
+ return FALSE;
+
+ strcpy (dir_file, dir->directory);
+ strcat (dir_file, FontDirFile);
+ if (stat (dir_file, &statb) == -1)
+ {
+ if (errno != ENOENT || dir->dir_mtime != 0)
+ return TRUE;
+ return FALSE; /* doesn't exist and never did: no change */
+ }
+ if (dir->dir_mtime != statb.st_mtime)
+ return TRUE;
+
+ if ((strlen(dir->directory) + sizeof(FontAliasFile)) > sizeof(dir_file))
+ return FALSE;
+ strcpy (dir_file, dir->directory);
+ strcat (dir_file, FontAliasFile);
+ if (stat (dir_file, &statb) == -1)
+ {
+ if (errno != ENOENT || dir->alias_mtime != 0)
+ return TRUE;
+ return FALSE; /* doesn't exist and never did: no change */
+ }
+ if (dir->alias_mtime != statb.st_mtime)
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * Make each of the file names an automatic alias for each of the files.
+ */
+
+static Bool
+AddFileNameAliases(FontDirectoryPtr dir)
+{
+ int i;
+ char copy[MAXFONTFILENAMELEN];
+ char *fileName;
+ FontTablePtr table;
+ FontRendererPtr renderer;
+ int len;
+ FontNameRec name;
+
+ table = &dir->nonScalable;
+ for (i = 0; i < table->used; i++) {
+ if (table->entries[i].type != FONT_ENTRY_BITMAP)
+ continue;
+ fileName = table->entries[i].u.bitmap.fileName;
+ renderer = FontFileMatchRenderer (fileName);
+ if (!renderer)
+ continue;
+
+ len = strlen (fileName) - renderer->fileSuffixLen;
+ if (len >= sizeof(copy))
+ continue;
+ CopyISOLatin1Lowered (copy, fileName, len);
+ copy[len] = '\0';
+ name.name = copy;
+ name.length = len;
+ name.ndashes = FontFileCountDashes (copy, len);
+
+ if (!FontFileFindNameInDir(table, &name)) {
+ if (!FontFileAddFontAlias (dir, copy, table->entries[i].name.name))
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/*
+ * parse the font.alias file. Format is:
+ *
+ * alias font-name
+ *
+ * To imbed white-space in an alias name, enclose it like "font name"
+ * in double quotes. \ escapes and character, so
+ * "font name \"With Double Quotes\" \\ and \\ back-slashes"
+ * works just fine.
+ *
+ * A line beginning with a ! denotes a newline-terminated comment.
+ */
+
+/*
+ * token types
+ */
+
+#define NAME 0
+#define NEWLINE 1
+#define DONE 2
+#define EALLOC 3
+
+static int
+ReadFontAlias(char *directory, Bool isFile, FontDirectoryPtr *pdir)
+{
+ char alias[MAXFONTNAMELEN];
+ char font_name[MAXFONTNAMELEN];
+ char alias_file[MAXFONTFILENAMELEN];
+ FILE *file;
+ FontDirectoryPtr dir;
+ int token;
+ char *lexToken;
+ int status = Successful;
+ struct stat statb;
+
+ if (strlen(directory) >= sizeof(alias_file))
+ return BadFontPath;
+ dir = *pdir;
+ strcpy(alias_file, directory);
+ if (!isFile) {
+ if (strlen(directory) + 1 + sizeof(FontAliasFile) > sizeof(alias_file))
+ return BadFontPath;
+ if (directory[strlen(directory) - 1] != '/')
+ strcat(alias_file, "/");
+ strcat(alias_file, FontAliasFile);
+ }
+ file = fopen(alias_file, "rt");
+ if (!file)
+ return ((errno == ENOENT) ? Successful : BadFontPath);
+ if (!dir)
+ *pdir = dir = FontFileMakeDir(directory, 10);
+ if (!dir)
+ {
+ fclose (file);
+ return AllocError;
+ }
+#ifndef WIN32
+ if (fstat (fileno (file), &statb) == -1)
+#else
+ if (stat (alias_file, &statb) == -1)
+#endif
+ {
+ fclose (file);
+ return BadFontPath;
+ }
+ dir->alias_mtime = statb.st_mtime;
+ while (status == Successful) {
+ token = lexAlias(file, &lexToken);
+ switch (token) {
+ case NEWLINE:
+ break;
+ case DONE:
+ fclose(file);
+ return Successful;
+ case EALLOC:
+ status = AllocError;
+ break;
+ case NAME:
+ if (strlen(lexToken) >= sizeof(alias)) {
+ status = BadFontPath;
+ break;
+ }
+ strcpy(alias, lexToken);
+ token = lexAlias(file, &lexToken);
+ switch (token) {
+ case NEWLINE:
+ if (strcmp(alias, "FILE_NAMES_ALIASES"))
+ status = BadFontPath;
+ else if (!AddFileNameAliases(dir))
+ status = AllocError;
+ break;
+ case DONE:
+ status = BadFontPath;
+ break;
+ case EALLOC:
+ status = AllocError;
+ break;
+ case NAME:
+ if (strlen(lexToken) >= sizeof(font_name)) {
+ status = BadFontPath;
+ break;
+ }
+ CopyISOLatin1Lowered(alias, alias, strlen(alias));
+ CopyISOLatin1Lowered(font_name, lexToken, strlen(lexToken));
+ if (!FontFileAddFontAlias (dir, alias, font_name))
+ status = AllocError;
+ break;
+ }
+ }
+ }
+ fclose(file);
+ return status;
+}
+
+#define QUOTE 0
+#define WHITE 1
+#define NORMAL 2
+#define END 3
+#define NL 4
+#define BANG 5
+
+static int charClass;
+
+static int
+lexAlias(FILE *file, char **lexToken)
+{
+ int c;
+ char *t;
+ enum state {
+ Begin, Normal, Quoted, Comment
+ } state;
+ int count;
+
+ static char *tokenBuf = (char *) NULL;
+ static int tokenSize = 0;
+
+ t = tokenBuf;
+ count = 0;
+ state = Begin;
+ for (;;) {
+ if (count == tokenSize) {
+ int nsize;
+ char *nbuf;
+
+ nsize = tokenSize ? (tokenSize << 1) : 64;
+ nbuf = realloc(tokenBuf, nsize);
+ if (!nbuf)
+ return EALLOC;
+ tokenBuf = nbuf;
+ tokenSize = nsize;
+ t = tokenBuf + count;
+ }
+ c = lexc(file);
+ switch (charClass) {
+ case QUOTE:
+ switch (state) {
+ case Begin:
+ case Normal:
+ state = Quoted;
+ break;
+ case Quoted:
+ state = Normal;
+ break;
+ case Comment:
+ break;
+ }
+ break;
+ case WHITE:
+ switch (state) {
+ case Begin:
+ case Comment:
+ continue;
+ case Normal:
+ *t = '\0';
+ *lexToken = tokenBuf;
+ return NAME;
+ case Quoted:
+ break;
+ }
+ /* fall through */
+ case NORMAL:
+ switch (state) {
+ case Begin:
+ state = Normal;
+ break;
+ case Comment:
+ continue;
+ default:
+ break;
+ }
+ *t++ = c;
+ ++count;
+ break;
+ case END:
+ case NL:
+ switch (state) {
+ case Begin:
+ case Comment:
+ *lexToken = (char *) NULL;
+ return charClass == END ? DONE : NEWLINE;
+ default:
+ *t = '\0';
+ *lexToken = tokenBuf;
+ ungetc(c, file);
+ return NAME;
+ }
+ break;
+ case BANG:
+ switch (state) {
+ case Begin:
+ state = Comment;
+ break;
+ case Comment:
+ break;
+ default:
+ *t++ = c;
+ ++count;
+ }
+ break;
+ }
+ }
+}
+
+static int
+lexc(FILE *file)
+{
+ int c;
+
+ c = getc(file);
+ switch (c) {
+ case EOF:
+ charClass = END;
+ break;
+ case '\\':
+ c = getc(file);
+ if (c == EOF)
+ charClass = END;
+ else
+ charClass = NORMAL;
+ break;
+ case '"':
+ charClass = QUOTE;
+ break;
+ case ' ':
+ case '\t':
+ charClass = WHITE;
+ break;
+ case '\r':
+ case '\n':
+ charClass = NL;
+ break;
+ case '!':
+ charClass = BANG;
+ break;
+ default:
+ charClass = NORMAL;
+ break;
+ }
+ return c;
+}
diff --git a/libXfont/src/fontfile/fileio.c b/libXfont/src/fontfile/fileio.c index 80af51193..136087ca5 100644 --- a/libXfont/src/fontfile/fileio.c +++ b/libXfont/src/fontfile/fileio.c @@ -1,91 +1,91 @@ -/* - -Copyright 1991, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fntfilio.h> -#include <X11/Xos.h> -#ifndef O_BINARY -#define O_BINARY O_RDONLY -#endif - -FontFilePtr -FontFileOpen (const char *name) -{ - int fd; - int len; - BufFilePtr raw, cooked; - - fd = open (name, O_BINARY); - if (fd < 0) - return 0; - raw = BufFileOpenRead (fd); - if (!raw) - { - close (fd); - return 0; - } - len = strlen (name); - if (len > 2 && !strcmp (name + len - 2, ".Z")) { - cooked = BufFilePushCompressed (raw); - if (!cooked) { - BufFileClose (raw, TRUE); - return 0; - } - raw = cooked; -#ifdef X_GZIP_FONT_COMPRESSION - } else if (len > 3 && !strcmp (name + len - 3, ".gz")) { - cooked = BufFilePushZIP (raw); - if (!cooked) { - BufFileClose (raw, TRUE); - return 0; - } - raw = cooked; -#endif -#ifdef X_BZIP2_FONT_COMPRESSION - } else if (len > 4 && !strcmp (name + len - 4, ".bz2")) { - cooked = BufFilePushBZIP2 (raw); - if (!cooked) { - BufFileClose (raw, TRUE); - return 0; - } - raw = cooked; -#endif - } - return (FontFilePtr) raw; -} - -int -FontFileClose (FontFilePtr f) -{ - return BufFileClose ((BufFilePtr) f, TRUE); -} - +/*
+
+Copyright 1991, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fntfilio.h>
+#include <X11/Xos.h>
+#ifndef O_BINARY
+#define O_BINARY O_RDONLY
+#endif
+
+FontFilePtr
+FontFileOpen (const char *name)
+{
+ int fd;
+ int len;
+ BufFilePtr raw, cooked;
+
+ fd = open (name, O_BINARY);
+ if (fd < 0)
+ return 0;
+ raw = BufFileOpenRead (fd);
+ if (!raw)
+ {
+ close (fd);
+ return 0;
+ }
+ len = strlen (name);
+ if (len > 2 && !strcmp (name + len - 2, ".Z")) {
+ cooked = BufFilePushCompressed (raw);
+ if (!cooked) {
+ BufFileClose (raw, TRUE);
+ return 0;
+ }
+ raw = cooked;
+#ifdef X_GZIP_FONT_COMPRESSION
+ } else if (len > 3 && !strcmp (name + len - 3, ".gz")) {
+ cooked = BufFilePushZIP (raw);
+ if (!cooked) {
+ BufFileClose (raw, TRUE);
+ return 0;
+ }
+ raw = cooked;
+#endif
+#ifdef X_BZIP2_FONT_COMPRESSION
+ } else if (len > 4 && !strcmp (name + len - 4, ".bz2")) {
+ cooked = BufFilePushBZIP2 (raw);
+ if (!cooked) {
+ BufFileClose (raw, TRUE);
+ return 0;
+ }
+ raw = cooked;
+#endif
+ }
+ return (FontFilePtr) raw;
+}
+
+int
+FontFileClose (FontFilePtr f)
+{
+ return BufFileClose ((BufFilePtr) f, TRUE);
+}
+
diff --git a/libXfont/src/fontfile/filewr.c b/libXfont/src/fontfile/filewr.c index bcc7b1eda..ad99e744b 100644 --- a/libXfont/src/fontfile/filewr.c +++ b/libXfont/src/fontfile/filewr.c @@ -1,62 +1,62 @@ -/* - -Copyright 1991, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fntfilio.h> -#include <X11/Xos.h> - -FontFilePtr -FontFileOpenWrite (const char *name) -{ - int fd; - -#if defined(WIN32) || defined(__CYGWIN__) - fd = open (name, O_CREAT|O_TRUNC|O_RDWR|O_BINARY, 0666); -#else - fd = creat (name, 0666); -#endif - if (fd < 0) - return 0; - return (FontFilePtr) BufFileOpenWrite (fd); -} - -FontFilePtr -FontFileOpenWriteFd (int fd) -{ - return (FontFilePtr) BufFileOpenWrite (fd); -} - -FontFilePtr -FontFileOpenFd (int fd) -{ - return (FontFilePtr) BufFileOpenRead (fd); -} +/*
+
+Copyright 1991, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fntfilio.h>
+#include <X11/Xos.h>
+
+FontFilePtr
+FontFileOpenWrite (const char *name)
+{
+ int fd;
+
+#if defined(WIN32) || defined(__CYGWIN__)
+ fd = open (name, O_CREAT|O_TRUNC|O_RDWR|O_BINARY, 0666);
+#else
+ fd = creat (name, 0666);
+#endif
+ if (fd < 0)
+ return 0;
+ return (FontFilePtr) BufFileOpenWrite (fd);
+}
+
+FontFilePtr
+FontFileOpenWriteFd (int fd)
+{
+ return (FontFilePtr) BufFileOpenWrite (fd);
+}
+
+FontFilePtr
+FontFileOpenFd (int fd)
+{
+ return (FontFilePtr) BufFileOpenRead (fd);
+}
diff --git a/libXfont/src/fontfile/fontdir.c b/libXfont/src/fontfile/fontdir.c index e052bb371..c4f8bc023 100644 --- a/libXfont/src/fontfile/fontdir.c +++ b/libXfont/src/fontfile/fontdir.c @@ -1,825 +1,825 @@ -/* - -Copyright 1991, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fntfilst.h> -#include <X11/keysym.h> - -#if HAVE_STDINT_H -#include <stdint.h> -#elif !defined(INT32_MAX) -#define INT32_MAX 0x7fffffff -#endif - -Bool -FontFileInitTable (FontTablePtr table, int size) -{ - if (size < 0 || (size > INT32_MAX/sizeof(FontEntryRec))) - return FALSE; - if (size) - { - table->entries = malloc(sizeof(FontEntryRec) * size); - if (!table->entries) - return FALSE; - } - else - table->entries = 0; - table->used = 0; - table->size = size; - table->sorted = FALSE; - return TRUE; -} - -void -FontFileFreeEntry (FontEntryPtr entry) -{ - FontScalableExtraPtr extra; - int i; - - if (entry->name.name) - free(entry->name.name); - entry->name.name = NULL; - - switch (entry->type) - { - case FONT_ENTRY_SCALABLE: - free (entry->u.scalable.fileName); - extra = entry->u.scalable.extra; - for (i = 0; i < extra->numScaled; i++) - if (extra->scaled[i].vals.ranges) - free (extra->scaled[i].vals.ranges); - free (extra->scaled); - free (extra); - break; - case FONT_ENTRY_BITMAP: - free (entry->u.bitmap.fileName); - entry->u.bitmap.fileName = NULL; - break; - case FONT_ENTRY_ALIAS: - free (entry->u.alias.resolved); - entry->u.alias.resolved = NULL; - break; - } -} - -void -FontFileFreeTable (FontTablePtr table) -{ - int i; - - for (i = 0; i < table->used; i++) - FontFileFreeEntry (&table->entries[i]); - free (table->entries); -} - -FontDirectoryPtr -FontFileMakeDir(char *dirName, int size) -{ - FontDirectoryPtr dir; - int dirlen; - int needslash = 0; - char *attrib; - int attriblen; - -#if !defined(WIN32) - attrib = strchr(dirName, ':'); -#else - /* OS/2 uses the colon in the drive letter descriptor, skip this */ - attrib = strchr(dirName+2, ':'); -#endif - if (attrib) { - dirlen = attrib - dirName; - attriblen = strlen(attrib); - } else { - dirlen = strlen(dirName); - attriblen = 0; - } - if (dirName[dirlen - 1] != '/') -#ifdef NCD - if (dirlen) /* leave out slash for builtins */ -#endif - needslash = 1; - dir = malloc(sizeof *dir + dirlen + needslash + 1 + - (attriblen ? attriblen + 1 : 0)); - if (!dir) - return (FontDirectoryPtr)0; - if (!FontFileInitTable (&dir->scalable, 0)) - { - free (dir); - return (FontDirectoryPtr)0; - } - if (!FontFileInitTable (&dir->nonScalable, size)) - { - FontFileFreeTable (&dir->scalable); - free (dir); - return (FontDirectoryPtr)0; - } - dir->directory = (char *) (dir + 1); - dir->dir_mtime = 0; - dir->alias_mtime = 0; - if (attriblen) - dir->attributes = dir->directory + dirlen + needslash + 1; - else - dir->attributes = NULL; - strncpy(dir->directory, dirName, dirlen); - dir->directory[dirlen] = '\0'; - if (dir->attributes) - strcpy(dir->attributes, attrib); - if (needslash) - strcat(dir->directory, "/"); - return dir; -} - -void -FontFileFreeDir (FontDirectoryPtr dir) -{ - FontFileFreeTable (&dir->scalable); - FontFileFreeTable (&dir->nonScalable); - free(dir); -} - -FontEntryPtr -FontFileAddEntry(FontTablePtr table, FontEntryPtr prototype) -{ - FontEntryPtr entry; - int newsize; - - /* can't add entries to a sorted table, pointers get broken! */ - if (table->sorted) - return (FontEntryPtr) 0; /* "cannot" happen */ - if (table->used == table->size) { - newsize = table->size + 100; - entry = realloc(table->entries, newsize * sizeof(FontEntryRec)); - if (!entry) - return (FontEntryPtr)0; - table->size = newsize; - table->entries = entry; - } - entry = &table->entries[table->used]; - *entry = *prototype; - entry->name.name = malloc(prototype->name.length + 1); - if (!entry->name.name) - return (FontEntryPtr)0; - memcpy (entry->name.name, prototype->name.name, prototype->name.length); - entry->name.name[entry->name.length] = '\0'; - table->used++; - return entry; -} - -/* - * Compare two strings just like strcmp, but preserve decimal integer - * sorting order, i.e. "2" < "10" or "iso8859-2" < "iso8859-10" < - * "iso10646-1". Strings are sorted as if sequences of digits were - * prefixed by a length indicator (i.e., does not ignore leading zeroes). - * - * Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk> - */ -#define Xisdigit(c) ('\060' <= (c) && (c) <= '\071') - -static int strcmpn(const char *s1, const char *s2) -{ - int digits, predigits = 0; - const char *ss1, *ss2; - - while (1) { - if (*s1 == 0 && *s2 == 0) - return 0; - digits = Xisdigit(*s1) && Xisdigit(*s2); - if (digits && !predigits) { - ss1 = s1; - ss2 = s2; - while (Xisdigit(*ss1) && Xisdigit(*ss2)) - ss1++, ss2++; - if (!Xisdigit(*ss1) && Xisdigit(*ss2)) - return -1; - if (Xisdigit(*ss1) && !Xisdigit(*ss2)) - return 1; - } - if ((unsigned char)*s1 < (unsigned char)*s2) - return -1; - if ((unsigned char)*s1 > (unsigned char)*s2) - return 1; - predigits = digits; - s1++, s2++; - } -} - - -static int -FontFileNameCompare(const void* a, const void* b) -{ - FontEntryPtr a_name = (FontEntryPtr) a, - b_name = (FontEntryPtr) b; - - return strcmpn(a_name->name.name, b_name->name.name); -} - -void -FontFileSortTable (FontTablePtr table) -{ - if (!table->sorted) { - qsort((char *) table->entries, table->used, sizeof(FontEntryRec), - FontFileNameCompare); - table->sorted = TRUE; - } -} - -void -FontFileSortDir(FontDirectoryPtr dir) -{ - FontFileSortTable (&dir->scalable); - FontFileSortTable (&dir->nonScalable); - /* now that the table is fixed in size, swizzle the pointers */ - FontFileSwitchStringsToBitmapPointers (dir); -} - -/* - Given a Font Table, SetupWildMatch() sets up various pointers and state - information so the table can be searched for name(s) that match a given - fontname pattern -- which may contain wildcards. Under certain - circumstances, SetupWildMatch() will find the one table entry that - matches the pattern. If those circumstances do not pertain, - SetupWildMatch() returns a range within the the table that should be - searched for matching name(s). With the information established by - SetupWildMatch(), including state information in "private", the - PatternMatch() procedure is then used to test names in the range for a - match. -*/ - -#define isWild(c) ((c) == XK_asterisk || (c) == XK_question) -#define isDigit(c) (XK_0 <= (c) && (c) <= XK_9) - -static int -SetupWildMatch(FontTablePtr table, FontNamePtr pat, - int *leftp, int *rightp, int *privatep) -{ - int nDashes; - char c; - char *t; - char *firstWild; - char *firstDigit; - int first; - int center, - left, - right; - int result; - char *name; - - name = pat->name; - nDashes = pat->ndashes; - firstWild = 0; - firstDigit = 0; - t = name; - while ((c = *t++)) { - if (isWild(c)) { - if (!firstWild) - firstWild = t - 1; - } - if (isDigit(c)) { - if (!firstDigit) - firstDigit = t - 1; - } - } - left = 0; - right = table->used; - if (firstWild) - *privatep = nDashes; - else - *privatep = -1; - if (!table->sorted) { - *leftp = left; - *rightp = right; - return -1; - } else if (firstWild) { - if (firstDigit && firstDigit < firstWild) - first = firstDigit - name; - else - first = firstWild - name; - while (left < right) { - center = (left + right) / 2; - result = strncmp(name, table->entries[center].name.name, first); - if (result == 0) - break; - if (result < 0) - right = center; - else - left = center + 1; - } - *leftp = left; - *rightp = right; - return -1; - } else { - while (left < right) { - center = (left + right) / 2; - result = strcmpn(name, table->entries[center].name.name); - if (result == 0) - return center; - if (result < 0) - right = center; - else - left = center + 1; - } - *leftp = 1; - *rightp = 0; - return -1; - } -} - -static int -PatternMatch(char *pat, int patdashes, char *string, int stringdashes) -{ - char c, - t; - - if (stringdashes < patdashes) - return 0; - for (;;) { - switch (c = *pat++) { - case '*': - if (!(c = *pat++)) - return 1; - if (c == XK_minus) { - patdashes--; - for (;;) { - while ((t = *string++) != XK_minus) - if (!t) - return 0; - stringdashes--; - if (PatternMatch(pat, patdashes, string, stringdashes)) - return 1; - if (stringdashes == patdashes) - return 0; - } - } else { - for (;;) { - while ((t = *string++) != c) { - if (!t) - return 0; - if (t == XK_minus) { - if (stringdashes-- < patdashes) - return 0; - } - } - if (PatternMatch(pat, patdashes, string, stringdashes)) - return 1; - } - } - case '?': - if (*string++ == XK_minus) - stringdashes--; - break; - case '\0': - return (*string == '\0'); - case XK_minus: - if (*string++ == XK_minus) { - patdashes--; - stringdashes--; - break; - } - return 0; - default: - if (c == *string++) - break; - return 0; - } - } -} - -int -FontFileCountDashes (char *name, int namelen) -{ - int ndashes = 0; - - while (namelen--) - if (*name++ == '\055') /* avoid non ascii systems */ - ++ndashes; - return ndashes; -} - -char * -FontFileSaveString (char *s) -{ - char *n; - - n = malloc (strlen (s) + 1); - if (!n) - return 0; - strcpy (n, s); - return n; -} - -FontEntryPtr -FontFileFindNameInScalableDir(FontTablePtr table, FontNamePtr pat, - FontScalablePtr vals) -{ - int i, - start, - stop, - res, - private; - FontNamePtr name; - - if (!table->entries) - return NULL; - if ((i = SetupWildMatch(table, pat, &start, &stop, &private)) >= 0) - return &table->entries[i]; - for (i = start; i < stop; i++) { - name = &table->entries[i].name; - res = PatternMatch(pat->name, private, name->name, name->ndashes); - if (res > 0) - { - /* Check to see if enhancements requested are available */ - if (vals) - { - int vs = vals->values_supplied; - int cap; - - if (table->entries[i].type == FONT_ENTRY_SCALABLE) - cap = table->entries[i].u.scalable.renderer->capabilities; - else if (table->entries[i].type == FONT_ENTRY_ALIAS) - cap = ~0; /* Calling code will have to see if true */ - else - cap = 0; - if ((((vs & PIXELSIZE_MASK) == PIXELSIZE_ARRAY || - (vs & POINTSIZE_MASK) == POINTSIZE_ARRAY) && - !(cap & CAP_MATRIX)) || - ((vs & CHARSUBSET_SPECIFIED) && - !(cap & CAP_CHARSUBSETTING))) - continue; - } - return &table->entries[i]; - } - if (res < 0) - break; - } - return (FontEntryPtr)0; -} - -FontEntryPtr -FontFileFindNameInDir(FontTablePtr table, FontNamePtr pat) -{ - return FontFileFindNameInScalableDir(table, pat, (FontScalablePtr)0); -} - -int -FontFileFindNamesInScalableDir(FontTablePtr table, FontNamePtr pat, int max, - FontNamesPtr names, FontScalablePtr vals, - int alias_behavior, int *newmax) -{ - int i, - start, - stop, - res, - private; - int ret = Successful; - FontEntryPtr fname; - FontNamePtr name; - - if (max <= 0) - return Successful; - if ((i = SetupWildMatch(table, pat, &start, &stop, &private)) >= 0) { - if (alias_behavior == NORMAL_ALIAS_BEHAVIOR || - table->entries[i].type != FONT_ENTRY_ALIAS) - { - name = &table->entries[i].name; - if (newmax) *newmax = max - 1; - return AddFontNamesName(names, name->name, name->length); - } - start = i; - stop = i + 1; - } - for (i = start, fname = &table->entries[start]; i < stop; i++, fname++) { - res = PatternMatch(pat->name, private, fname->name.name, fname->name.ndashes); - if (res > 0) { - if (vals) - { - int vs = vals->values_supplied; - int cap; - - if (fname->type == FONT_ENTRY_SCALABLE) - cap = fname->u.scalable.renderer->capabilities; - else if (fname->type == FONT_ENTRY_ALIAS) - cap = ~0; /* Calling code will have to see if true */ - else - cap = 0; - if ((((vs & PIXELSIZE_MASK) == PIXELSIZE_ARRAY || - (vs & POINTSIZE_MASK) == POINTSIZE_ARRAY) && - !(cap & CAP_MATRIX)) || - ((vs & CHARSUBSET_SPECIFIED) && - !(cap & CAP_CHARSUBSETTING))) - continue; - } - - if ((alias_behavior & IGNORE_SCALABLE_ALIASES) && - fname->type == FONT_ENTRY_ALIAS) - { - FontScalableRec tmpvals; - if (FontParseXLFDName (fname->name.name, &tmpvals, - FONT_XLFD_REPLACE_NONE) && - !(tmpvals.values_supplied & SIZE_SPECIFY_MASK)) - continue; - } - - ret = AddFontNamesName(names, fname->name.name, fname->name.length); - if (ret != Successful) - goto bail; - - /* If alias_behavior is LIST_ALIASES_AND_TARGET_NAMES, mark - this entry as an alias by negating its length and follow - it by the resolved name */ - if ((alias_behavior & LIST_ALIASES_AND_TARGET_NAMES) && - fname->type == FONT_ENTRY_ALIAS) - { - names->length[names->nnames - 1] = - -names->length[names->nnames - 1]; - ret = AddFontNamesName(names, fname->u.alias.resolved, - strlen(fname->u.alias.resolved)); - if (ret != Successful) - goto bail; - } - - if (--max <= 0) - break; - } else if (res < 0) - break; - } - bail: ; - if (newmax) *newmax = max; - return ret; -} - -int -FontFileFindNamesInDir(FontTablePtr table, FontNamePtr pat, - int max, FontNamesPtr names) -{ - return FontFileFindNamesInScalableDir(table, pat, max, names, - (FontScalablePtr)0, - NORMAL_ALIAS_BEHAVIOR, (int *)0); -} - -Bool -FontFileMatchName(char *name, int length, FontNamePtr pat) -{ - /* Perform a fontfile-type name match on a single name */ - FontTableRec table; - FontEntryRec entries[1]; - - /* Dummy up a table */ - table.used = 1; - table.size = 1; - table.sorted = TRUE; - table.entries = entries; - entries[0].name.name = name; - entries[0].name.length = length; - entries[0].name.ndashes = FontFileCountDashes(name, length); - - return FontFileFindNameInDir(&table, pat) != (FontEntryPtr)0; -} - -/* - * Add a font file to a directory. This handles bitmap and - * scalable names both - */ - -Bool -FontFileAddFontFile (FontDirectoryPtr dir, char *fontName, char *fileName) -{ - FontEntryRec entry; - FontScalableRec vals, zeroVals; - FontRendererPtr renderer; - FontEntryPtr existing; - FontScalableExtraPtr extra; - FontEntryPtr bitmap = 0, scalable; - Bool isscale; - Bool scalable_xlfd; - - renderer = FontFileMatchRenderer (fileName); - if (!renderer) - return FALSE; - entry.name.length = strlen (fontName); - if (entry.name.length > MAXFONTNAMELEN) - entry.name.length = MAXFONTNAMELEN; - entry.name.name = fontName; - CopyISOLatin1Lowered (entry.name.name, fontName, entry.name.length); - entry.name.ndashes = FontFileCountDashes (entry.name.name, entry.name.length); - entry.name.name[entry.name.length] = '\0'; - /* - * Add a bitmap name if the incoming name isn't an XLFD name, or - * if it isn't a scalable name (i.e. non-zero scalable fields) - * - * If name of bitmapped font contains XLFD enhancements, do not add - * a scalable version of the name... this can lead to confusion and - * ambiguity between the font name and the field enhancements. - */ - isscale = entry.name.ndashes == 14 && - FontParseXLFDName(entry.name.name, - &vals, FONT_XLFD_REPLACE_NONE) && - (vals.values_supplied & PIXELSIZE_MASK) != PIXELSIZE_ARRAY && - (vals.values_supplied & POINTSIZE_MASK) != POINTSIZE_ARRAY && - !(vals.values_supplied & ENHANCEMENT_SPECIFY_MASK); -#define UNSCALED_ATTRIB "unscaled" - scalable_xlfd = (isscale && - (((vals.values_supplied & PIXELSIZE_MASK) == 0) || - ((vals.values_supplied & POINTSIZE_MASK) == 0))); - /* - * For scalable fonts without a scalable XFLD, check if the "unscaled" - * attribute is present. - */ - if (isscale && !scalable_xlfd && - dir->attributes && dir->attributes[0] == ':') { - char *ptr1 = dir->attributes + 1; - char *ptr2; - int length; - int uslength = strlen(UNSCALED_ATTRIB); - - do { - ptr2 = strchr(ptr1, ':'); - if (ptr2) - length = ptr2 - ptr1; - else - length = dir->attributes + strlen(dir->attributes) - ptr1; - if (length == uslength && !strncmp(ptr1, UNSCALED_ATTRIB, uslength)) - isscale = FALSE; - if (ptr2) - ptr1 = ptr2 + 1; - } while (ptr2); - } - if (!isscale || (vals.values_supplied & SIZE_SPECIFY_MASK)) - { - /* - * If the renderer doesn't support OpenBitmap, FontFileOpenFont - * will still do the right thing. - */ - entry.type = FONT_ENTRY_BITMAP; - entry.u.bitmap.renderer = renderer; - entry.u.bitmap.pFont = NullFont; - if (!(entry.u.bitmap.fileName = FontFileSaveString (fileName))) - return FALSE; - if (!(bitmap = FontFileAddEntry (&dir->nonScalable, &entry))) - { - free (entry.u.bitmap.fileName); - return FALSE; - } - } - /* - * Parse out scalable fields from XLFD names - a scalable name - * just gets inserted, a scaled name has more things to do. - */ - if (isscale) - { - if (vals.values_supplied & SIZE_SPECIFY_MASK) - { - bzero((char *)&zeroVals, sizeof(zeroVals)); - zeroVals.x = vals.x; - zeroVals.y = vals.y; - zeroVals.values_supplied = PIXELSIZE_SCALAR | POINTSIZE_SCALAR; - FontParseXLFDName (entry.name.name, &zeroVals, - FONT_XLFD_REPLACE_VALUE); - entry.name.length = strlen (entry.name.name); - existing = FontFileFindNameInDir (&dir->scalable, &entry.name); - if (existing) - { - if ((vals.values_supplied & POINTSIZE_MASK) == - POINTSIZE_SCALAR && - (int)(vals.point_matrix[3] * 10) == GetDefaultPointSize()) - { - existing->u.scalable.extra->defaults = vals; - - free (existing->u.scalable.fileName); - if (!(existing->u.scalable.fileName = FontFileSaveString (fileName))) - return FALSE; - } - if(bitmap) - { - FontFileCompleteXLFD(&vals, &vals); - FontFileAddScaledInstance (existing, &vals, NullFont, - bitmap->name.name); - return TRUE; - } - } - } - if (!(entry.u.scalable.fileName = FontFileSaveString (fileName))) - return FALSE; - extra = malloc (sizeof (FontScalableExtraRec)); - if (!extra) - { - free (entry.u.scalable.fileName); - return FALSE; - } - bzero((char *)&extra->defaults, sizeof(extra->defaults)); - if ((vals.values_supplied & POINTSIZE_MASK) == POINTSIZE_SCALAR && - (int)(vals.point_matrix[3] * 10) == GetDefaultPointSize()) - extra->defaults = vals; - else - { - FontResolutionPtr resolution; - int num; - int default_point_size = GetDefaultPointSize(); - - extra->defaults.point_matrix[0] = - extra->defaults.point_matrix[3] = - (double)default_point_size / 10.0; - extra->defaults.point_matrix[1] = - extra->defaults.point_matrix[2] = 0.0; - extra->defaults.values_supplied = - POINTSIZE_SCALAR | PIXELSIZE_UNDEFINED; - extra->defaults.width = -1; - if (vals.x <= 0 || vals.y <= 0) - { - resolution = GetClientResolutions (&num); - if (resolution && num > 0) - { - extra->defaults.x = resolution->x_resolution; - extra->defaults.y = resolution->y_resolution; - } - else - { - extra->defaults.x = 75; - extra->defaults.y = 75; - } - } - else - { - extra->defaults.x = vals.x; - extra->defaults.y = vals.y; - } - FontFileCompleteXLFD (&extra->defaults, &extra->defaults); - } - extra->numScaled = 0; - extra->sizeScaled = 0; - extra->scaled = 0; - extra->private = 0; - entry.type = FONT_ENTRY_SCALABLE; - entry.u.scalable.renderer = renderer; - entry.u.scalable.extra = extra; - if (!(scalable = FontFileAddEntry (&dir->scalable, &entry))) - { - free (extra); - free (entry.u.scalable.fileName); - return FALSE; - } - if (vals.values_supplied & SIZE_SPECIFY_MASK) - { - if(bitmap) - { - FontFileCompleteXLFD(&vals, &vals); - FontFileAddScaledInstance (scalable, &vals, NullFont, - bitmap->name.name); - } - } - } - return TRUE; -} - -Bool -FontFileAddFontAlias (FontDirectoryPtr dir, char *aliasName, char *fontName) -{ - FontEntryRec entry; - - if (strcmp(aliasName,fontName) == 0) { - /* Don't allow an alias to point to itself and create a loop */ - return FALSE; - } - entry.name.length = strlen (aliasName); - CopyISOLatin1Lowered (aliasName, aliasName, entry.name.length); - entry.name.name = aliasName; - entry.name.ndashes = FontFileCountDashes (entry.name.name, entry.name.length); - entry.type = FONT_ENTRY_ALIAS; - if (!(entry.u.alias.resolved = FontFileSaveString (fontName))) - return FALSE; - if (!FontFileAddEntry (&dir->nonScalable, &entry)) - { - free (entry.u.alias.resolved); - return FALSE; - } - return TRUE; -} +/*
+
+Copyright 1991, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fntfilst.h>
+#include <X11/keysym.h>
+
+#if HAVE_STDINT_H
+#include <stdint.h>
+#elif !defined(INT32_MAX)
+#define INT32_MAX 0x7fffffff
+#endif
+
+Bool
+FontFileInitTable (FontTablePtr table, int size)
+{
+ if (size < 0 || (size > INT32_MAX/sizeof(FontEntryRec)))
+ return FALSE;
+ if (size)
+ {
+ table->entries = malloc(sizeof(FontEntryRec) * size);
+ if (!table->entries)
+ return FALSE;
+ }
+ else
+ table->entries = 0;
+ table->used = 0;
+ table->size = size;
+ table->sorted = FALSE;
+ return TRUE;
+}
+
+void
+FontFileFreeEntry (FontEntryPtr entry)
+{
+ FontScalableExtraPtr extra;
+ int i;
+
+ if (entry->name.name)
+ free(entry->name.name);
+ entry->name.name = NULL;
+
+ switch (entry->type)
+ {
+ case FONT_ENTRY_SCALABLE:
+ free (entry->u.scalable.fileName);
+ extra = entry->u.scalable.extra;
+ for (i = 0; i < extra->numScaled; i++)
+ if (extra->scaled[i].vals.ranges)
+ free (extra->scaled[i].vals.ranges);
+ free (extra->scaled);
+ free (extra);
+ break;
+ case FONT_ENTRY_BITMAP:
+ free (entry->u.bitmap.fileName);
+ entry->u.bitmap.fileName = NULL;
+ break;
+ case FONT_ENTRY_ALIAS:
+ free (entry->u.alias.resolved);
+ entry->u.alias.resolved = NULL;
+ break;
+ }
+}
+
+void
+FontFileFreeTable (FontTablePtr table)
+{
+ int i;
+
+ for (i = 0; i < table->used; i++)
+ FontFileFreeEntry (&table->entries[i]);
+ free (table->entries);
+}
+
+FontDirectoryPtr
+FontFileMakeDir(char *dirName, int size)
+{
+ FontDirectoryPtr dir;
+ int dirlen;
+ int needslash = 0;
+ char *attrib;
+ int attriblen;
+
+#if !defined(WIN32)
+ attrib = strchr(dirName, ':');
+#else
+ /* OS/2 uses the colon in the drive letter descriptor, skip this */
+ attrib = strchr(dirName+2, ':');
+#endif
+ if (attrib) {
+ dirlen = attrib - dirName;
+ attriblen = strlen(attrib);
+ } else {
+ dirlen = strlen(dirName);
+ attriblen = 0;
+ }
+ if (dirName[dirlen - 1] != '/')
+#ifdef NCD
+ if (dirlen) /* leave out slash for builtins */
+#endif
+ needslash = 1;
+ dir = malloc(sizeof *dir + dirlen + needslash + 1 +
+ (attriblen ? attriblen + 1 : 0));
+ if (!dir)
+ return (FontDirectoryPtr)0;
+ if (!FontFileInitTable (&dir->scalable, 0))
+ {
+ free (dir);
+ return (FontDirectoryPtr)0;
+ }
+ if (!FontFileInitTable (&dir->nonScalable, size))
+ {
+ FontFileFreeTable (&dir->scalable);
+ free (dir);
+ return (FontDirectoryPtr)0;
+ }
+ dir->directory = (char *) (dir + 1);
+ dir->dir_mtime = 0;
+ dir->alias_mtime = 0;
+ if (attriblen)
+ dir->attributes = dir->directory + dirlen + needslash + 1;
+ else
+ dir->attributes = NULL;
+ strncpy(dir->directory, dirName, dirlen);
+ dir->directory[dirlen] = '\0';
+ if (dir->attributes)
+ strcpy(dir->attributes, attrib);
+ if (needslash)
+ strcat(dir->directory, "/");
+ return dir;
+}
+
+void
+FontFileFreeDir (FontDirectoryPtr dir)
+{
+ FontFileFreeTable (&dir->scalable);
+ FontFileFreeTable (&dir->nonScalable);
+ free(dir);
+}
+
+FontEntryPtr
+FontFileAddEntry(FontTablePtr table, FontEntryPtr prototype)
+{
+ FontEntryPtr entry;
+ int newsize;
+
+ /* can't add entries to a sorted table, pointers get broken! */
+ if (table->sorted)
+ return (FontEntryPtr) 0; /* "cannot" happen */
+ if (table->used == table->size) {
+ newsize = table->size + 100;
+ entry = realloc(table->entries, newsize * sizeof(FontEntryRec));
+ if (!entry)
+ return (FontEntryPtr)0;
+ table->size = newsize;
+ table->entries = entry;
+ }
+ entry = &table->entries[table->used];
+ *entry = *prototype;
+ entry->name.name = malloc(prototype->name.length + 1);
+ if (!entry->name.name)
+ return (FontEntryPtr)0;
+ memcpy (entry->name.name, prototype->name.name, prototype->name.length);
+ entry->name.name[entry->name.length] = '\0';
+ table->used++;
+ return entry;
+}
+
+/*
+ * Compare two strings just like strcmp, but preserve decimal integer
+ * sorting order, i.e. "2" < "10" or "iso8859-2" < "iso8859-10" <
+ * "iso10646-1". Strings are sorted as if sequences of digits were
+ * prefixed by a length indicator (i.e., does not ignore leading zeroes).
+ *
+ * Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk>
+ */
+#define Xisdigit(c) ('\060' <= (c) && (c) <= '\071')
+
+static int strcmpn(const char *s1, const char *s2)
+{
+ int digits, predigits = 0;
+ const char *ss1, *ss2;
+
+ while (1) {
+ if (*s1 == 0 && *s2 == 0)
+ return 0;
+ digits = Xisdigit(*s1) && Xisdigit(*s2);
+ if (digits && !predigits) {
+ ss1 = s1;
+ ss2 = s2;
+ while (Xisdigit(*ss1) && Xisdigit(*ss2))
+ ss1++, ss2++;
+ if (!Xisdigit(*ss1) && Xisdigit(*ss2))
+ return -1;
+ if (Xisdigit(*ss1) && !Xisdigit(*ss2))
+ return 1;
+ }
+ if ((unsigned char)*s1 < (unsigned char)*s2)
+ return -1;
+ if ((unsigned char)*s1 > (unsigned char)*s2)
+ return 1;
+ predigits = digits;
+ s1++, s2++;
+ }
+}
+
+
+static int
+FontFileNameCompare(const void* a, const void* b)
+{
+ FontEntryPtr a_name = (FontEntryPtr) a,
+ b_name = (FontEntryPtr) b;
+
+ return strcmpn(a_name->name.name, b_name->name.name);
+}
+
+void
+FontFileSortTable (FontTablePtr table)
+{
+ if (!table->sorted) {
+ qsort((char *) table->entries, table->used, sizeof(FontEntryRec),
+ FontFileNameCompare);
+ table->sorted = TRUE;
+ }
+}
+
+void
+FontFileSortDir(FontDirectoryPtr dir)
+{
+ FontFileSortTable (&dir->scalable);
+ FontFileSortTable (&dir->nonScalable);
+ /* now that the table is fixed in size, swizzle the pointers */
+ FontFileSwitchStringsToBitmapPointers (dir);
+}
+
+/*
+ Given a Font Table, SetupWildMatch() sets up various pointers and state
+ information so the table can be searched for name(s) that match a given
+ fontname pattern -- which may contain wildcards. Under certain
+ circumstances, SetupWildMatch() will find the one table entry that
+ matches the pattern. If those circumstances do not pertain,
+ SetupWildMatch() returns a range within the the table that should be
+ searched for matching name(s). With the information established by
+ SetupWildMatch(), including state information in "private", the
+ PatternMatch() procedure is then used to test names in the range for a
+ match.
+*/
+
+#define isWild(c) ((c) == XK_asterisk || (c) == XK_question)
+#define isDigit(c) (XK_0 <= (c) && (c) <= XK_9)
+
+static int
+SetupWildMatch(FontTablePtr table, FontNamePtr pat,
+ int *leftp, int *rightp, int *privatep)
+{
+ int nDashes;
+ char c;
+ char *t;
+ char *firstWild;
+ char *firstDigit;
+ int first;
+ int center,
+ left,
+ right;
+ int result;
+ char *name;
+
+ name = pat->name;
+ nDashes = pat->ndashes;
+ firstWild = 0;
+ firstDigit = 0;
+ t = name;
+ while ((c = *t++)) {
+ if (isWild(c)) {
+ if (!firstWild)
+ firstWild = t - 1;
+ }
+ if (isDigit(c)) {
+ if (!firstDigit)
+ firstDigit = t - 1;
+ }
+ }
+ left = 0;
+ right = table->used;
+ if (firstWild)
+ *privatep = nDashes;
+ else
+ *privatep = -1;
+ if (!table->sorted) {
+ *leftp = left;
+ *rightp = right;
+ return -1;
+ } else if (firstWild) {
+ if (firstDigit && firstDigit < firstWild)
+ first = firstDigit - name;
+ else
+ first = firstWild - name;
+ while (left < right) {
+ center = (left + right) / 2;
+ result = strncmp(name, table->entries[center].name.name, first);
+ if (result == 0)
+ break;
+ if (result < 0)
+ right = center;
+ else
+ left = center + 1;
+ }
+ *leftp = left;
+ *rightp = right;
+ return -1;
+ } else {
+ while (left < right) {
+ center = (left + right) / 2;
+ result = strcmpn(name, table->entries[center].name.name);
+ if (result == 0)
+ return center;
+ if (result < 0)
+ right = center;
+ else
+ left = center + 1;
+ }
+ *leftp = 1;
+ *rightp = 0;
+ return -1;
+ }
+}
+
+static int
+PatternMatch(char *pat, int patdashes, char *string, int stringdashes)
+{
+ char c,
+ t;
+
+ if (stringdashes < patdashes)
+ return 0;
+ for (;;) {
+ switch (c = *pat++) {
+ case '*':
+ if (!(c = *pat++))
+ return 1;
+ if (c == XK_minus) {
+ patdashes--;
+ for (;;) {
+ while ((t = *string++) != XK_minus)
+ if (!t)
+ return 0;
+ stringdashes--;
+ if (PatternMatch(pat, patdashes, string, stringdashes))
+ return 1;
+ if (stringdashes == patdashes)
+ return 0;
+ }
+ } else {
+ for (;;) {
+ while ((t = *string++) != c) {
+ if (!t)
+ return 0;
+ if (t == XK_minus) {
+ if (stringdashes-- < patdashes)
+ return 0;
+ }
+ }
+ if (PatternMatch(pat, patdashes, string, stringdashes))
+ return 1;
+ }
+ }
+ case '?':
+ if (*string++ == XK_minus)
+ stringdashes--;
+ break;
+ case '\0':
+ return (*string == '\0');
+ case XK_minus:
+ if (*string++ == XK_minus) {
+ patdashes--;
+ stringdashes--;
+ break;
+ }
+ return 0;
+ default:
+ if (c == *string++)
+ break;
+ return 0;
+ }
+ }
+}
+
+int
+FontFileCountDashes (char *name, int namelen)
+{
+ int ndashes = 0;
+
+ while (namelen--)
+ if (*name++ == '\055') /* avoid non ascii systems */
+ ++ndashes;
+ return ndashes;
+}
+
+char *
+FontFileSaveString (char *s)
+{
+ char *n;
+
+ n = malloc (strlen (s) + 1);
+ if (!n)
+ return 0;
+ strcpy (n, s);
+ return n;
+}
+
+FontEntryPtr
+FontFileFindNameInScalableDir(FontTablePtr table, FontNamePtr pat,
+ FontScalablePtr vals)
+{
+ int i,
+ start,
+ stop,
+ res,
+ private;
+ FontNamePtr name;
+
+ if (!table->entries)
+ return NULL;
+ if ((i = SetupWildMatch(table, pat, &start, &stop, &private)) >= 0)
+ return &table->entries[i];
+ for (i = start; i < stop; i++) {
+ name = &table->entries[i].name;
+ res = PatternMatch(pat->name, private, name->name, name->ndashes);
+ if (res > 0)
+ {
+ /* Check to see if enhancements requested are available */
+ if (vals)
+ {
+ int vs = vals->values_supplied;
+ int cap;
+
+ if (table->entries[i].type == FONT_ENTRY_SCALABLE)
+ cap = table->entries[i].u.scalable.renderer->capabilities;
+ else if (table->entries[i].type == FONT_ENTRY_ALIAS)
+ cap = ~0; /* Calling code will have to see if true */
+ else
+ cap = 0;
+ if ((((vs & PIXELSIZE_MASK) == PIXELSIZE_ARRAY ||
+ (vs & POINTSIZE_MASK) == POINTSIZE_ARRAY) &&
+ !(cap & CAP_MATRIX)) ||
+ ((vs & CHARSUBSET_SPECIFIED) &&
+ !(cap & CAP_CHARSUBSETTING)))
+ continue;
+ }
+ return &table->entries[i];
+ }
+ if (res < 0)
+ break;
+ }
+ return (FontEntryPtr)0;
+}
+
+FontEntryPtr
+FontFileFindNameInDir(FontTablePtr table, FontNamePtr pat)
+{
+ return FontFileFindNameInScalableDir(table, pat, (FontScalablePtr)0);
+}
+
+int
+FontFileFindNamesInScalableDir(FontTablePtr table, FontNamePtr pat, int max,
+ FontNamesPtr names, FontScalablePtr vals,
+ int alias_behavior, int *newmax)
+{
+ int i,
+ start,
+ stop,
+ res,
+ private;
+ int ret = Successful;
+ FontEntryPtr fname;
+ FontNamePtr name;
+
+ if (max <= 0)
+ return Successful;
+ if ((i = SetupWildMatch(table, pat, &start, &stop, &private)) >= 0) {
+ if (alias_behavior == NORMAL_ALIAS_BEHAVIOR ||
+ table->entries[i].type != FONT_ENTRY_ALIAS)
+ {
+ name = &table->entries[i].name;
+ if (newmax) *newmax = max - 1;
+ return AddFontNamesName(names, name->name, name->length);
+ }
+ start = i;
+ stop = i + 1;
+ }
+ for (i = start, fname = &table->entries[start]; i < stop; i++, fname++) {
+ res = PatternMatch(pat->name, private, fname->name.name, fname->name.ndashes);
+ if (res > 0) {
+ if (vals)
+ {
+ int vs = vals->values_supplied;
+ int cap;
+
+ if (fname->type == FONT_ENTRY_SCALABLE)
+ cap = fname->u.scalable.renderer->capabilities;
+ else if (fname->type == FONT_ENTRY_ALIAS)
+ cap = ~0; /* Calling code will have to see if true */
+ else
+ cap = 0;
+ if ((((vs & PIXELSIZE_MASK) == PIXELSIZE_ARRAY ||
+ (vs & POINTSIZE_MASK) == POINTSIZE_ARRAY) &&
+ !(cap & CAP_MATRIX)) ||
+ ((vs & CHARSUBSET_SPECIFIED) &&
+ !(cap & CAP_CHARSUBSETTING)))
+ continue;
+ }
+
+ if ((alias_behavior & IGNORE_SCALABLE_ALIASES) &&
+ fname->type == FONT_ENTRY_ALIAS)
+ {
+ FontScalableRec tmpvals;
+ if (FontParseXLFDName (fname->name.name, &tmpvals,
+ FONT_XLFD_REPLACE_NONE) &&
+ !(tmpvals.values_supplied & SIZE_SPECIFY_MASK))
+ continue;
+ }
+
+ ret = AddFontNamesName(names, fname->name.name, fname->name.length);
+ if (ret != Successful)
+ goto bail;
+
+ /* If alias_behavior is LIST_ALIASES_AND_TARGET_NAMES, mark
+ this entry as an alias by negating its length and follow
+ it by the resolved name */
+ if ((alias_behavior & LIST_ALIASES_AND_TARGET_NAMES) &&
+ fname->type == FONT_ENTRY_ALIAS)
+ {
+ names->length[names->nnames - 1] =
+ -names->length[names->nnames - 1];
+ ret = AddFontNamesName(names, fname->u.alias.resolved,
+ strlen(fname->u.alias.resolved));
+ if (ret != Successful)
+ goto bail;
+ }
+
+ if (--max <= 0)
+ break;
+ } else if (res < 0)
+ break;
+ }
+ bail: ;
+ if (newmax) *newmax = max;
+ return ret;
+}
+
+int
+FontFileFindNamesInDir(FontTablePtr table, FontNamePtr pat,
+ int max, FontNamesPtr names)
+{
+ return FontFileFindNamesInScalableDir(table, pat, max, names,
+ (FontScalablePtr)0,
+ NORMAL_ALIAS_BEHAVIOR, (int *)0);
+}
+
+Bool
+FontFileMatchName(char *name, int length, FontNamePtr pat)
+{
+ /* Perform a fontfile-type name match on a single name */
+ FontTableRec table;
+ FontEntryRec entries[1];
+
+ /* Dummy up a table */
+ table.used = 1;
+ table.size = 1;
+ table.sorted = TRUE;
+ table.entries = entries;
+ entries[0].name.name = name;
+ entries[0].name.length = length;
+ entries[0].name.ndashes = FontFileCountDashes(name, length);
+
+ return FontFileFindNameInDir(&table, pat) != (FontEntryPtr)0;
+}
+
+/*
+ * Add a font file to a directory. This handles bitmap and
+ * scalable names both
+ */
+
+Bool
+FontFileAddFontFile (FontDirectoryPtr dir, char *fontName, char *fileName)
+{
+ FontEntryRec entry;
+ FontScalableRec vals, zeroVals;
+ FontRendererPtr renderer;
+ FontEntryPtr existing;
+ FontScalableExtraPtr extra;
+ FontEntryPtr bitmap = 0, scalable;
+ Bool isscale;
+ Bool scalable_xlfd;
+
+ renderer = FontFileMatchRenderer (fileName);
+ if (!renderer)
+ return FALSE;
+ entry.name.length = strlen (fontName);
+ if (entry.name.length > MAXFONTNAMELEN)
+ entry.name.length = MAXFONTNAMELEN;
+ entry.name.name = fontName;
+ CopyISOLatin1Lowered (entry.name.name, fontName, entry.name.length);
+ entry.name.ndashes = FontFileCountDashes (entry.name.name, entry.name.length);
+ entry.name.name[entry.name.length] = '\0';
+ /*
+ * Add a bitmap name if the incoming name isn't an XLFD name, or
+ * if it isn't a scalable name (i.e. non-zero scalable fields)
+ *
+ * If name of bitmapped font contains XLFD enhancements, do not add
+ * a scalable version of the name... this can lead to confusion and
+ * ambiguity between the font name and the field enhancements.
+ */
+ isscale = entry.name.ndashes == 14 &&
+ FontParseXLFDName(entry.name.name,
+ &vals, FONT_XLFD_REPLACE_NONE) &&
+ (vals.values_supplied & PIXELSIZE_MASK) != PIXELSIZE_ARRAY &&
+ (vals.values_supplied & POINTSIZE_MASK) != POINTSIZE_ARRAY &&
+ !(vals.values_supplied & ENHANCEMENT_SPECIFY_MASK);
+#define UNSCALED_ATTRIB "unscaled"
+ scalable_xlfd = (isscale &&
+ (((vals.values_supplied & PIXELSIZE_MASK) == 0) ||
+ ((vals.values_supplied & POINTSIZE_MASK) == 0)));
+ /*
+ * For scalable fonts without a scalable XFLD, check if the "unscaled"
+ * attribute is present.
+ */
+ if (isscale && !scalable_xlfd &&
+ dir->attributes && dir->attributes[0] == ':') {
+ char *ptr1 = dir->attributes + 1;
+ char *ptr2;
+ int length;
+ int uslength = strlen(UNSCALED_ATTRIB);
+
+ do {
+ ptr2 = strchr(ptr1, ':');
+ if (ptr2)
+ length = ptr2 - ptr1;
+ else
+ length = dir->attributes + strlen(dir->attributes) - ptr1;
+ if (length == uslength && !strncmp(ptr1, UNSCALED_ATTRIB, uslength))
+ isscale = FALSE;
+ if (ptr2)
+ ptr1 = ptr2 + 1;
+ } while (ptr2);
+ }
+ if (!isscale || (vals.values_supplied & SIZE_SPECIFY_MASK))
+ {
+ /*
+ * If the renderer doesn't support OpenBitmap, FontFileOpenFont
+ * will still do the right thing.
+ */
+ entry.type = FONT_ENTRY_BITMAP;
+ entry.u.bitmap.renderer = renderer;
+ entry.u.bitmap.pFont = NullFont;
+ if (!(entry.u.bitmap.fileName = FontFileSaveString (fileName)))
+ return FALSE;
+ if (!(bitmap = FontFileAddEntry (&dir->nonScalable, &entry)))
+ {
+ free (entry.u.bitmap.fileName);
+ return FALSE;
+ }
+ }
+ /*
+ * Parse out scalable fields from XLFD names - a scalable name
+ * just gets inserted, a scaled name has more things to do.
+ */
+ if (isscale)
+ {
+ if (vals.values_supplied & SIZE_SPECIFY_MASK)
+ {
+ bzero((char *)&zeroVals, sizeof(zeroVals));
+ zeroVals.x = vals.x;
+ zeroVals.y = vals.y;
+ zeroVals.values_supplied = PIXELSIZE_SCALAR | POINTSIZE_SCALAR;
+ FontParseXLFDName (entry.name.name, &zeroVals,
+ FONT_XLFD_REPLACE_VALUE);
+ entry.name.length = strlen (entry.name.name);
+ existing = FontFileFindNameInDir (&dir->scalable, &entry.name);
+ if (existing)
+ {
+ if ((vals.values_supplied & POINTSIZE_MASK) ==
+ POINTSIZE_SCALAR &&
+ (int)(vals.point_matrix[3] * 10) == GetDefaultPointSize())
+ {
+ existing->u.scalable.extra->defaults = vals;
+
+ free (existing->u.scalable.fileName);
+ if (!(existing->u.scalable.fileName = FontFileSaveString (fileName)))
+ return FALSE;
+ }
+ if(bitmap)
+ {
+ FontFileCompleteXLFD(&vals, &vals);
+ FontFileAddScaledInstance (existing, &vals, NullFont,
+ bitmap->name.name);
+ return TRUE;
+ }
+ }
+ }
+ if (!(entry.u.scalable.fileName = FontFileSaveString (fileName)))
+ return FALSE;
+ extra = malloc (sizeof (FontScalableExtraRec));
+ if (!extra)
+ {
+ free (entry.u.scalable.fileName);
+ return FALSE;
+ }
+ bzero((char *)&extra->defaults, sizeof(extra->defaults));
+ if ((vals.values_supplied & POINTSIZE_MASK) == POINTSIZE_SCALAR &&
+ (int)(vals.point_matrix[3] * 10) == GetDefaultPointSize())
+ extra->defaults = vals;
+ else
+ {
+ FontResolutionPtr resolution;
+ int num;
+ int default_point_size = GetDefaultPointSize();
+
+ extra->defaults.point_matrix[0] =
+ extra->defaults.point_matrix[3] =
+ (double)default_point_size / 10.0;
+ extra->defaults.point_matrix[1] =
+ extra->defaults.point_matrix[2] = 0.0;
+ extra->defaults.values_supplied =
+ POINTSIZE_SCALAR | PIXELSIZE_UNDEFINED;
+ extra->defaults.width = -1;
+ if (vals.x <= 0 || vals.y <= 0)
+ {
+ resolution = GetClientResolutions (&num);
+ if (resolution && num > 0)
+ {
+ extra->defaults.x = resolution->x_resolution;
+ extra->defaults.y = resolution->y_resolution;
+ }
+ else
+ {
+ extra->defaults.x = 75;
+ extra->defaults.y = 75;
+ }
+ }
+ else
+ {
+ extra->defaults.x = vals.x;
+ extra->defaults.y = vals.y;
+ }
+ FontFileCompleteXLFD (&extra->defaults, &extra->defaults);
+ }
+ extra->numScaled = 0;
+ extra->sizeScaled = 0;
+ extra->scaled = 0;
+ extra->private = 0;
+ entry.type = FONT_ENTRY_SCALABLE;
+ entry.u.scalable.renderer = renderer;
+ entry.u.scalable.extra = extra;
+ if (!(scalable = FontFileAddEntry (&dir->scalable, &entry)))
+ {
+ free (extra);
+ free (entry.u.scalable.fileName);
+ return FALSE;
+ }
+ if (vals.values_supplied & SIZE_SPECIFY_MASK)
+ {
+ if(bitmap)
+ {
+ FontFileCompleteXLFD(&vals, &vals);
+ FontFileAddScaledInstance (scalable, &vals, NullFont,
+ bitmap->name.name);
+ }
+ }
+ }
+ return TRUE;
+}
+
+Bool
+FontFileAddFontAlias (FontDirectoryPtr dir, char *aliasName, char *fontName)
+{
+ FontEntryRec entry;
+
+ if (strcmp(aliasName,fontName) == 0) {
+ /* Don't allow an alias to point to itself and create a loop */
+ return FALSE;
+ }
+ entry.name.length = strlen (aliasName);
+ CopyISOLatin1Lowered (aliasName, aliasName, entry.name.length);
+ entry.name.name = aliasName;
+ entry.name.ndashes = FontFileCountDashes (entry.name.name, entry.name.length);
+ entry.type = FONT_ENTRY_ALIAS;
+ if (!(entry.u.alias.resolved = FontFileSaveString (fontName)))
+ return FALSE;
+ if (!FontFileAddEntry (&dir->nonScalable, &entry))
+ {
+ free (entry.u.alias.resolved);
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/libXfont/src/fontfile/fontencc.c b/libXfont/src/fontfile/fontencc.c index 79977851d..ea91cd615 100644 --- a/libXfont/src/fontfile/fontencc.c +++ b/libXfont/src/fontfile/fontencc.c @@ -1,76 +1,76 @@ -/* -Copyright (c) 1998-2001 by Juliusz Chroboczek - -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. -*/ - -/* Binary compatibility code. */ - -/* This file includes code to make modules compiled for earlier - versions of the fontenc interfaces link with this one. It does - *not* provide source compatibility, as many of the data structures - now have different names. */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fontenc.h> -#include <X11/fonts/fontencc.h> - -extern void ErrorF(const char *f, ...); - -char * -font_encoding_from_xlfd(const char * name, int length) -{ - return FontEncFromXLFD(name, length); -} - -FontEncPtr -font_encoding_find(const char *encoding_name, const char *filename) -{ - return FontEncFind(encoding_name, filename); -} - -unsigned -font_encoding_recode(unsigned code, - FontEncPtr encoding, FontMapPtr mapping) -{ - if(encoding != mapping->encoding) { - ErrorF("Inconsistent mapping/encoding\n"); - return 0; - } - return FontEncRecode(code, mapping); -} - -char * -font_encoding_name(unsigned code, - FontEncPtr encoding, FontMapPtr mapping) -{ - if(encoding != mapping->encoding) { - ErrorF("Inconsistent mapping/encoding\n"); - return 0; - } - return FontEncName(code, mapping); -} - -char ** -identifyEncodingFile(const char *filename) -{ - return FontEncIdentify(filename); -} +/*
+Copyright (c) 1998-2001 by Juliusz Chroboczek
+
+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.
+*/
+
+/* Binary compatibility code. */
+
+/* This file includes code to make modules compiled for earlier
+ versions of the fontenc interfaces link with this one. It does
+ *not* provide source compatibility, as many of the data structures
+ now have different names. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fontenc.h>
+#include <X11/fonts/fontencc.h>
+
+extern void ErrorF(const char *f, ...);
+
+char *
+font_encoding_from_xlfd(const char * name, int length)
+{
+ return FontEncFromXLFD(name, length);
+}
+
+FontEncPtr
+font_encoding_find(const char *encoding_name, const char *filename)
+{
+ return FontEncFind(encoding_name, filename);
+}
+
+unsigned
+font_encoding_recode(unsigned code,
+ FontEncPtr encoding, FontMapPtr mapping)
+{
+ if(encoding != mapping->encoding) {
+ ErrorF("Inconsistent mapping/encoding\n");
+ return 0;
+ }
+ return FontEncRecode(code, mapping);
+}
+
+char *
+font_encoding_name(unsigned code,
+ FontEncPtr encoding, FontMapPtr mapping)
+{
+ if(encoding != mapping->encoding) {
+ ErrorF("Inconsistent mapping/encoding\n");
+ return 0;
+ }
+ return FontEncName(code, mapping);
+}
+
+char **
+identifyEncodingFile(const char *filename)
+{
+ return FontEncIdentify(filename);
+}
diff --git a/libXfont/src/fontfile/fontfile.c b/libXfont/src/fontfile/fontfile.c index eb37a8705..32b5097ac 100644 --- a/libXfont/src/fontfile/fontfile.c +++ b/libXfont/src/fontfile/fontfile.c @@ -1,1136 +1,1169 @@ -/* - -Copyright 1991, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fntfilst.h> -#include <X11/keysym.h> -#ifdef WIN32 -#include <ctype.h> -#endif - -static unsigned char -ISOLatin1ToLower(unsigned char source) -{ - if (source >= XK_A && source <= XK_Z) - return source + (XK_a - XK_A); - if (source >= XK_Agrave && source <= XK_Odiaeresis) - return source + (XK_agrave - XK_Agrave); - if (source >= XK_Ooblique && source <= XK_Thorn) - return source + (XK_oslash - XK_Ooblique); - return source; -} - -_X_HIDDEN void -CopyISOLatin1Lowered(char *dest, char *source, int length) -{ - int i; - for (i = 0; i < length; i++, source++, dest++) - *dest = ISOLatin1ToLower(*source); - *dest = '\0'; -} - -/* - * Map FPE functions to renderer functions - */ - -static int FontFileOpenBitmapNCF (FontPathElementPtr fpe, FontPtr *pFont, - int flags, FontEntryPtr entry, - fsBitmapFormat format, - fsBitmapFormatMask fmask, - FontPtr non_cachable_font); - -int -FontFileNameCheck (char *name) -{ -#ifndef NCD -#if defined(WIN32) - /* OS/2 uses D:/... as a path name for fonts, so accept this as a valid - * path if it starts with a letter and a colon. Same applies for WIN32 - */ - if (isalpha(*name) && name[1]==':') - return TRUE; -#endif - return *name == '/'; -#else - return ((strcmp(name, "built-ins") == 0) || (*name == '/')); -#endif -} - -int -FontFileInitFPE (FontPathElementPtr fpe) -{ - int status; - FontDirectoryPtr dir; - - status = FontFileReadDirectory (fpe->name, &dir); - if (status == Successful) - { - if (dir->nonScalable.used > 0) - if (!FontFileRegisterBitmapSource (fpe)) - { - FontFileFreeFPE (fpe); - return AllocError; - } - fpe->private = (pointer) dir; - } - return status; -} - -/* ARGSUSED */ -int -FontFileResetFPE (FontPathElementPtr fpe) -{ - FontDirectoryPtr dir; - - dir = (FontDirectoryPtr) fpe->private; - /* - * The reset must fail for bitmap fonts because they get cleared when - * the path is set. - */ - if (FontFileDirectoryChanged (dir)) - { - /* can't do it, so tell the caller to close and re-open */ - return FPEResetFailed; - } - else - { - if (dir->nonScalable.used > 0) - if (!FontFileRegisterBitmapSource (fpe)) - { - return FPEResetFailed; - } - return Successful; - } -} - -int -FontFileFreeFPE (FontPathElementPtr fpe) -{ - FontFileUnregisterBitmapSource (fpe); - FontFileFreeDir ((FontDirectoryPtr) fpe->private); - return Successful; -} - -static int -transfer_values_to_alias(char *entryname, int entrynamelength, - char *resolvedname, - char **aliasName, FontScalablePtr vals) -{ - static char aliasname[MAXFONTNAMELEN]; - int nameok = 1, len; - char lowerName[MAXFONTNAMELEN]; - - *aliasName = resolvedname; - if ((len = strlen(*aliasName)) <= MAXFONTNAMELEN && - (entrynamelength < MAXFONTNAMELEN) && - FontFileCountDashes (*aliasName, len) == 14) - { - FontScalableRec tmpVals; - FontScalableRec tmpVals2; - - tmpVals2 = *vals; - - /* If we're aliasing a scalable name, transfer values - from the name into the destination alias, multiplying - by matrices that appear in the alias. */ - - CopyISOLatin1Lowered (lowerName, entryname, - entrynamelength); - lowerName[entrynamelength] = '\0'; - - if (FontParseXLFDName(lowerName, &tmpVals, - FONT_XLFD_REPLACE_NONE) && - !tmpVals.values_supplied && - FontParseXLFDName(*aliasName, &tmpVals, - FONT_XLFD_REPLACE_NONE)) - { - double *matrix = 0, tempmatrix[4]; - - /* Use a matrix iff exactly one is defined */ - if ((tmpVals.values_supplied & PIXELSIZE_MASK) == - PIXELSIZE_ARRAY && - !(tmpVals.values_supplied & POINTSIZE_MASK)) - matrix = tmpVals.pixel_matrix; - else if ((tmpVals.values_supplied & POINTSIZE_MASK) == - POINTSIZE_ARRAY && - !(tmpVals.values_supplied & PIXELSIZE_MASK)) - matrix = tmpVals.point_matrix; - - /* If matrix given in the alias, compute new point - and/or pixel matrices */ - if (matrix) - { - /* Complete the XLFD name to avoid potential - gotchas */ - if (FontFileCompleteXLFD(&tmpVals2, &tmpVals2)) - { - tempmatrix[0] = - matrix[0] * tmpVals2.point_matrix[0] + - matrix[1] * tmpVals2.point_matrix[2]; - tempmatrix[1] = - matrix[0] * tmpVals2.point_matrix[1] + - matrix[1] * tmpVals2.point_matrix[3]; - tempmatrix[2] = - matrix[2] * tmpVals2.point_matrix[0] + - matrix[3] * tmpVals2.point_matrix[2]; - tempmatrix[3] = - matrix[2] * tmpVals2.point_matrix[1] + - matrix[3] * tmpVals2.point_matrix[3]; - tmpVals2.point_matrix[0] = tempmatrix[0]; - tmpVals2.point_matrix[1] = tempmatrix[1]; - tmpVals2.point_matrix[2] = tempmatrix[2]; - tmpVals2.point_matrix[3] = tempmatrix[3]; - - tempmatrix[0] = - matrix[0] * tmpVals2.pixel_matrix[0] + - matrix[1] * tmpVals2.pixel_matrix[2]; - tempmatrix[1] = - matrix[0] * tmpVals2.pixel_matrix[1] + - matrix[1] * tmpVals2.pixel_matrix[3]; - tempmatrix[2] = - matrix[2] * tmpVals2.pixel_matrix[0] + - matrix[3] * tmpVals2.pixel_matrix[2]; - tempmatrix[3] = - matrix[2] * tmpVals2.pixel_matrix[1] + - matrix[3] * tmpVals2.pixel_matrix[3]; - tmpVals2.pixel_matrix[0] = tempmatrix[0]; - tmpVals2.pixel_matrix[1] = tempmatrix[1]; - tmpVals2.pixel_matrix[2] = tempmatrix[2]; - tmpVals2.pixel_matrix[3] = tempmatrix[3]; - - tmpVals2.values_supplied = - (tmpVals2.values_supplied & - ~(PIXELSIZE_MASK | POINTSIZE_MASK)) | - PIXELSIZE_ARRAY | POINTSIZE_ARRAY; - } - else - nameok = 0; - } - - CopyISOLatin1Lowered (aliasname, *aliasName, len + 1); - if (nameok && FontParseXLFDName(aliasname, &tmpVals2, - FONT_XLFD_REPLACE_VALUE)) - /* Return a version of the aliasname that has - had the vals stuffed into it. To avoid - memory leak, this alias name lives in a - static buffer. The caller needs to be done - with this buffer before this procedure is - called again to avoid reentrancy problems. */ - *aliasName = aliasname; - } - } - return nameok; -} - -/* ARGSUSED */ -int -FontFileOpenFont (pointer client, FontPathElementPtr fpe, Mask flags, - char *name, int namelen, - fsBitmapFormat format, fsBitmapFormatMask fmask, - XID id, FontPtr *pFont, char **aliasName, - FontPtr non_cachable_font) -{ - FontDirectoryPtr dir; - char lowerName[MAXFONTNAMELEN]; - char fileName[MAXFONTFILENAMELEN*2 + 1]; - FontNameRec tmpName; - FontEntryPtr entry; - FontScalableRec vals; - FontScalableEntryPtr scalable; - FontScaledPtr scaled; - FontBitmapEntryPtr bitmap; - int ret; - Bool noSpecificSize; - int nranges; - fsRange *ranges; - - if (namelen >= MAXFONTNAMELEN) - return AllocError; - dir = (FontDirectoryPtr) fpe->private; - - /* Match non-scalable pattern */ - CopyISOLatin1Lowered (lowerName, name, namelen); - lowerName[namelen] = '\0'; - ranges = FontParseRanges(lowerName, &nranges); - tmpName.name = lowerName; - tmpName.length = namelen; - tmpName.ndashes = FontFileCountDashes (lowerName, namelen); - if (!FontParseXLFDName(lowerName, &vals, FONT_XLFD_REPLACE_NONE)) - bzero(&vals, sizeof(vals)); - if (!(entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName)) && - tmpName.ndashes == 14 && - FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO)) - { - tmpName.length = strlen(lowerName); - entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName); - } - - if (entry) - { - switch (entry->type) { - case FONT_ENTRY_BITMAP: - bitmap = &entry->u.bitmap; - if (bitmap->pFont) - { - *pFont = bitmap->pFont; - (*pFont)->fpe = fpe; - ret = Successful; - } - else - { - ret = FontFileOpenBitmapNCF (fpe, pFont, flags, entry, format, - fmask, non_cachable_font); - if (ret == Successful && *pFont) - (*pFont)->fpe = fpe; - } - break; - case FONT_ENTRY_ALIAS: - vals.nranges = nranges; - vals.ranges = ranges; - transfer_values_to_alias(entry->name.name, entry->name.length, - entry->u.alias.resolved, aliasName, &vals); - ret = FontNameAlias; - break; - default: - ret = BadFontName; - } - } - else - { - ret = BadFontName; - } - - if (ret != BadFontName) - { - if (ranges) free(ranges); - return ret; - } - - /* Match XLFD patterns */ - CopyISOLatin1Lowered (lowerName, name, namelen); - lowerName[namelen] = '\0'; - tmpName.name = lowerName; - tmpName.length = namelen; - tmpName.ndashes = FontFileCountDashes (lowerName, namelen); - if (!FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO) || - !(tmpName.length = strlen (lowerName), - entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName, - &vals))) { - CopyISOLatin1Lowered (lowerName, name, namelen); - lowerName[namelen] = '\0'; - tmpName.name = lowerName; - tmpName.length = namelen; - tmpName.ndashes = FontFileCountDashes (lowerName, namelen); - entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName, &vals); - if (entry) - { - strcpy(lowerName, entry->name.name); - tmpName.name = lowerName; - tmpName.length = entry->name.length; - tmpName.ndashes = entry->name.ndashes; - } - } - - if (entry) - { - noSpecificSize = FALSE; /* TRUE breaks XLFD enhancements */ - if (entry->type == FONT_ENTRY_SCALABLE && - FontFileCompleteXLFD (&vals, &entry->u.scalable.extra->defaults)) - { - scalable = &entry->u.scalable; - if ((vals.values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY || - (vals.values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY || - (vals.values_supplied & - ~SIZE_SPECIFY_MASK & ~CHARSUBSET_SPECIFIED)) - scaled = 0; - else - scaled = FontFileFindScaledInstance (entry, &vals, - noSpecificSize); - /* - * A scaled instance can occur one of two ways: - * - * Either the font has been scaled to this - * size already, in which case scaled->pFont - * will point at that font. - * - * Or a bitmap instance in this size exists, - * which is handled as if we got a pattern - * matching the bitmap font name. - */ - if (scaled) - { - if (scaled->pFont) - { - *pFont = scaled->pFont; - (*pFont)->fpe = fpe; - ret = Successful; - } - else if (scaled->bitmap) - { - entry = scaled->bitmap; - bitmap = &entry->u.bitmap; - if (bitmap->pFont) - { - *pFont = bitmap->pFont; - (*pFont)->fpe = fpe; - ret = Successful; - } - else - { - ret = FontFileOpenBitmapNCF (fpe, pFont, flags, entry, - format, fmask, - non_cachable_font); - if (ret == Successful && *pFont) - (*pFont)->fpe = fpe; - } - } - else /* "cannot" happen */ - { - ret = BadFontName; - } - } - else - { - ret = FontFileMatchBitmapSource (fpe, pFont, flags, entry, &tmpName, &vals, format, fmask, noSpecificSize); - if (ret != Successful) - { - char origName[MAXFONTNAMELEN]; - - CopyISOLatin1Lowered (origName, name, namelen); - origName[namelen] = '\0'; - - /* Pass the original XLFD name in the vals - structure; the rasterizer is free to examine it - for hidden meanings. This information will not - be saved in the scaled-instances table. */ - - vals.xlfdName = origName; - vals.ranges = ranges; - vals.nranges = nranges; - - if (strlen(dir->directory) + strlen(scalable->fileName) >= - sizeof(fileName)) { - ret = BadFontName; - } else { - strcpy (fileName, dir->directory); - strcat (fileName, scalable->fileName); - if (scalable->renderer->OpenScalable) { - ret = (*scalable->renderer->OpenScalable) (fpe, pFont, - flags, entry, fileName, &vals, format, fmask, - non_cachable_font); - } - else if (scalable->renderer->OpenBitmap) { - ret = (*scalable->renderer->OpenBitmap) (fpe, pFont, - flags, entry, fileName, format, fmask, - non_cachable_font); - } - } - - /* In case rasterizer does something bad because of - charset subsetting... */ - if (ret == Successful && - ((*pFont)->info.firstCol > (*pFont)->info.lastCol || - (*pFont)->info.firstRow > (*pFont)->info.lastRow)) - { - (*(*pFont)->unload_font)(*pFont); - ret = BadFontName; - } - /* Save the instance */ - if (ret == Successful) - { - if (FontFileAddScaledInstance (entry, &vals, - *pFont, (char *) 0)) - ranges = 0; - else - (*pFont)->fpePrivate = (pointer) 0; - (*pFont)->fpe = fpe; - } - } - } - } - } - else - ret = BadFontName; - - if (ranges) - free(ranges); - return ret; -} - -/* ARGSUSED */ -void -FontFileCloseFont (FontPathElementPtr fpe, FontPtr pFont) -{ - FontEntryPtr entry; - - if ((entry = (FontEntryPtr) pFont->fpePrivate)) { - switch (entry->type) { - case FONT_ENTRY_SCALABLE: - FontFileRemoveScaledInstance (entry, pFont); - break; - case FONT_ENTRY_BITMAP: - entry->u.bitmap.pFont = 0; - break; - default: - /* "cannot" happen */ - break; - } - pFont->fpePrivate = 0; - } - (*pFont->unload_font) (pFont); -} - -static int -FontFileOpenBitmapNCF (FontPathElementPtr fpe, FontPtr *pFont, - int flags, FontEntryPtr entry, - fsBitmapFormat format, fsBitmapFormatMask fmask, - FontPtr non_cachable_font) -{ - FontBitmapEntryPtr bitmap; - char fileName[MAXFONTFILENAMELEN*2+1]; - int ret; - FontDirectoryPtr dir; - - dir = (FontDirectoryPtr) fpe->private; - bitmap = &entry->u.bitmap; - if(!bitmap || !bitmap->renderer->OpenBitmap) - return BadFontName; - if (strlen(dir->directory) + strlen(bitmap->fileName) >= sizeof(fileName)) - return BadFontName; - strcpy (fileName, dir->directory); - strcat (fileName, bitmap->fileName); - ret = (*bitmap->renderer->OpenBitmap) - (fpe, pFont, flags, entry, fileName, format, fmask, - non_cachable_font); - if (ret == Successful) - { - bitmap->pFont = *pFont; - (*pFont)->fpePrivate = (pointer) entry; - } - return ret; -} - -int -FontFileOpenBitmap (FontPathElementPtr fpe, FontPtr *pFont, - int flags, FontEntryPtr entry, - fsBitmapFormat format, fsBitmapFormatMask fmask) -{ - return FontFileOpenBitmapNCF (fpe, pFont, flags, entry, format, fmask, - (FontPtr)0); -} - -static int -FontFileGetInfoBitmap (FontPathElementPtr fpe, FontInfoPtr pFontInfo, - FontEntryPtr entry) -{ - FontBitmapEntryPtr bitmap; - char fileName[MAXFONTFILENAMELEN*2+1]; - int ret; - FontDirectoryPtr dir; - - dir = (FontDirectoryPtr) fpe->private; - bitmap = &entry->u.bitmap; - if (!bitmap || !bitmap->renderer->GetInfoBitmap) - return BadFontName; - if (strlen(dir->directory) + strlen(bitmap->fileName) >= sizeof(fileName)) - return BadFontName; - strcpy (fileName, dir->directory); - strcat (fileName, bitmap->fileName); - ret = (*bitmap->renderer->GetInfoBitmap) (fpe, pFontInfo, entry, fileName); - return ret; -} - -static void -_FontFileAddScalableNames(FontNamesPtr names, FontNamesPtr scaleNames, - FontNamePtr nameptr, char *zeroChars, - FontScalablePtr vals, fsRange *ranges, - int nranges, int *max) -{ - int i; - FontScalableRec zeroVals, tmpVals; - for (i = 0; i < scaleNames->nnames; i++) - { - char nameChars[MAXFONTNAMELEN]; - if (!*max) - return; - FontParseXLFDName (scaleNames->names[i], &zeroVals, - FONT_XLFD_REPLACE_NONE); - tmpVals = *vals; - if (FontFileCompleteXLFD (&tmpVals, &zeroVals)) - { - --*max; - - strcpy (nameChars, scaleNames->names[i]); - if ((vals->values_supplied & PIXELSIZE_MASK) || - !(vals->values_supplied & PIXELSIZE_WILDCARD) || - vals->y == 0) - { - tmpVals.values_supplied = - (tmpVals.values_supplied & ~PIXELSIZE_MASK) | - (vals->values_supplied & PIXELSIZE_MASK); - tmpVals.pixel_matrix[0] = vals->pixel_matrix[0]; - tmpVals.pixel_matrix[1] = vals->pixel_matrix[1]; - tmpVals.pixel_matrix[2] = vals->pixel_matrix[2]; - tmpVals.pixel_matrix[3] = vals->pixel_matrix[3]; - } - if ((vals->values_supplied & POINTSIZE_MASK) || - !(vals->values_supplied & POINTSIZE_WILDCARD) || - vals->y == 0) - { - tmpVals.values_supplied = - (tmpVals.values_supplied & ~POINTSIZE_MASK) | - (vals->values_supplied & POINTSIZE_MASK); - tmpVals.point_matrix[0] = vals->point_matrix[0]; - tmpVals.point_matrix[1] = vals->point_matrix[1]; - tmpVals.point_matrix[2] = vals->point_matrix[2]; - tmpVals.point_matrix[3] = vals->point_matrix[3]; - } - if (vals->width <= 0) - tmpVals.width = 0; - if (vals->x == 0) - tmpVals.x = 0; - if (vals->y == 0) - tmpVals.y = 0; - tmpVals.ranges = ranges; - tmpVals.nranges = nranges; - FontParseXLFDName (nameChars, &tmpVals, - FONT_XLFD_REPLACE_VALUE); - /* If we're marking aliases with negative lengths, we - need to concoct a valid target name to follow it. - Otherwise we're done. */ - if (scaleNames->length[i] >= 0) - { - (void) AddFontNamesName (names, nameChars, - strlen (nameChars)); - /* If our original pattern matches the name from - the table and that name doesn't duplicate what - we just added, add the name from the table */ - if (strcmp(nameChars, scaleNames->names[i]) && - FontFileMatchName(scaleNames->names[i], - scaleNames->length[i], - nameptr) && - *max) - { - --*max; - (void) AddFontNamesName (names, scaleNames->names[i], - scaleNames->length[i]); - } - } - else - { - char *aliasName; - vals->ranges = ranges; - vals->nranges = nranges; - if (transfer_values_to_alias(zeroChars, - strlen(zeroChars), - scaleNames->names[++i], - &aliasName, vals)) - { - (void) AddFontNamesName (names, nameChars, - strlen (nameChars)); - names->length[names->nnames - 1] = - -names->length[names->nnames - 1]; - (void) AddFontNamesName (names, aliasName, - strlen (aliasName)); - /* If our original pattern matches the name from - the table and that name doesn't duplicate what - we just added, add the name from the table */ - if (strcmp(nameChars, scaleNames->names[i - 1]) && - FontFileMatchName(scaleNames->names[i - 1], - -scaleNames->length[i - 1], - nameptr) && - *max) - { - --*max; - (void) AddFontNamesName (names, - scaleNames->names[i - 1], - -scaleNames->length[i - 1]); - names->length[names->nnames - 1] = - -names->length[names->nnames - 1]; - (void) AddFontNamesName (names, aliasName, - strlen (aliasName)); - } - } - } - } - } -} - -/* ARGSUSED */ -static int -_FontFileListFonts (pointer client, FontPathElementPtr fpe, - char *pat, int len, int max, FontNamesPtr names, - int mark_aliases) -{ - FontDirectoryPtr dir; - char lowerChars[MAXFONTNAMELEN], zeroChars[MAXFONTNAMELEN]; - FontNameRec lowerName; - FontNameRec zeroName; - FontNamesPtr scaleNames; - FontScalableRec vals; - fsRange *ranges; - int nranges; - int result = BadFontName; - - if (len >= MAXFONTNAMELEN) - return AllocError; - dir = (FontDirectoryPtr) fpe->private; - CopyISOLatin1Lowered (lowerChars, pat, len); - lowerChars[len] = '\0'; - lowerName.name = lowerChars; - lowerName.length = len; - lowerName.ndashes = FontFileCountDashes (lowerChars, len); - - /* Match XLFD patterns */ - - strcpy (zeroChars, lowerChars); - if (lowerName.ndashes == 14 && - FontParseXLFDName (zeroChars, &vals, FONT_XLFD_REPLACE_ZERO)) - { - ranges = FontParseRanges(lowerChars, &nranges); - result = FontFileFindNamesInScalableDir (&dir->nonScalable, - &lowerName, max, names, - (FontScalablePtr)0, - (mark_aliases ? - LIST_ALIASES_AND_TARGET_NAMES : - NORMAL_ALIAS_BEHAVIOR) | - IGNORE_SCALABLE_ALIASES, - &max); - zeroName.name = zeroChars; - zeroName.length = strlen (zeroChars); - zeroName.ndashes = lowerName.ndashes; - - /* Look for scalable names and aliases, adding scaled instances of - them to the output */ - - /* Scalable names... */ - scaleNames = MakeFontNamesRecord (0); - if (!scaleNames) - { - if (ranges) free(ranges); - return AllocError; - } - FontFileFindNamesInScalableDir (&dir->scalable, &zeroName, max, - scaleNames, &vals, - mark_aliases ? - LIST_ALIASES_AND_TARGET_NAMES : - NORMAL_ALIAS_BEHAVIOR, (int *)0); - _FontFileAddScalableNames(names, scaleNames, &lowerName, - zeroChars, &vals, ranges, nranges, - &max); - FreeFontNames (scaleNames); - - /* Scalable aliases... */ - scaleNames = MakeFontNamesRecord (0); - if (!scaleNames) - { - if (ranges) free(ranges); - return AllocError; - } - FontFileFindNamesInScalableDir (&dir->nonScalable, &zeroName, - max, scaleNames, &vals, - mark_aliases ? - LIST_ALIASES_AND_TARGET_NAMES : - NORMAL_ALIAS_BEHAVIOR, (int *)0); - _FontFileAddScalableNames(names, scaleNames, &lowerName, - zeroChars, &vals, ranges, nranges, - &max); - FreeFontNames (scaleNames); - - if (ranges) free(ranges); - } - else - { - result = FontFileFindNamesInScalableDir (&dir->nonScalable, - &lowerName, max, names, - (FontScalablePtr)0, - mark_aliases ? - LIST_ALIASES_AND_TARGET_NAMES : - NORMAL_ALIAS_BEHAVIOR, - &max); - if (result == Successful) - result = FontFileFindNamesInScalableDir (&dir->scalable, - &lowerName, max, names, - (FontScalablePtr)0, - mark_aliases ? - LIST_ALIASES_AND_TARGET_NAMES : - NORMAL_ALIAS_BEHAVIOR, (int *)0); - } - return result; -} - -typedef struct _LFWIData { - FontNamesPtr names; - int current; -} LFWIDataRec, *LFWIDataPtr; - -int -FontFileListFonts (pointer client, FontPathElementPtr fpe, char *pat, - int len, int max, FontNamesPtr names) -{ - return _FontFileListFonts (client, fpe, pat, len, max, names, 0); -} - -int -FontFileStartListFonts(pointer client, FontPathElementPtr fpe, - char *pat, int len, int max, - pointer *privatep, int mark_aliases) -{ - LFWIDataPtr data; - int ret; - - data = malloc (sizeof *data); - if (!data) - return AllocError; - data->names = MakeFontNamesRecord (0); - if (!data->names) - { - free (data); - return AllocError; - } - ret = _FontFileListFonts (client, fpe, pat, len, - max, data->names, mark_aliases); - if (ret != Successful) - { - FreeFontNames (data->names); - free (data); - return ret; - } - data->current = 0; - *privatep = (pointer) data; - return Successful; -} - - -int -FontFileStartListFontsWithInfo(pointer client, FontPathElementPtr fpe, - char *pat, int len, int max, - pointer *privatep) -{ - return FontFileStartListFonts(client, fpe, pat, len, max, privatep, 0); -} - -/* ARGSUSED */ -static int -FontFileListOneFontWithInfo (pointer client, FontPathElementPtr fpe, - char **namep, int *namelenp, - FontInfoPtr *pFontInfo) -{ - FontDirectoryPtr dir; - char lowerName[MAXFONTNAMELEN]; - char fileName[MAXFONTFILENAMELEN*2 + 1]; - FontNameRec tmpName; - FontEntryPtr entry; - FontScalableRec vals; - FontScalableEntryPtr scalable; - FontScaledPtr scaled; - FontBitmapEntryPtr bitmap; - int ret; - Bool noSpecificSize; - int nranges; - fsRange *ranges; - - char *name = *namep; - int namelen = *namelenp; - - if (namelen >= MAXFONTNAMELEN) - return AllocError; - dir = (FontDirectoryPtr) fpe->private; - - /* Match non-scalable pattern */ - CopyISOLatin1Lowered (lowerName, name, namelen); - lowerName[namelen] = '\0'; - ranges = FontParseRanges(lowerName, &nranges); - tmpName.name = lowerName; - tmpName.length = namelen; - tmpName.ndashes = FontFileCountDashes (lowerName, namelen); - if (!FontParseXLFDName(lowerName, &vals, FONT_XLFD_REPLACE_NONE)) - bzero(&vals, sizeof(vals)); - if (!(entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName)) && - tmpName.ndashes == 14 && - FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO)) - { - tmpName.length = strlen(lowerName); - entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName); - } - - if (entry) - { - switch (entry->type) { - case FONT_ENTRY_BITMAP: - bitmap = &entry->u.bitmap; - if (bitmap->pFont) - { - *pFontInfo = &bitmap->pFont->info; - ret = Successful; - } - else - { - ret = FontFileGetInfoBitmap (fpe, *pFontInfo, entry); - } - break; - case FONT_ENTRY_ALIAS: - vals.nranges = nranges; - vals.ranges = ranges; - transfer_values_to_alias(entry->name.name, entry->name.length, - entry->u.alias.resolved, namep, &vals); - *namelenp = strlen (*namep); - ret = FontNameAlias; - break; - default: - ret = BadFontName; - } - } - else - { - ret = BadFontName; - } - - if (ret != BadFontName) - { - if (ranges) free(ranges); - return ret; - } - - /* Match XLFD patterns */ - CopyISOLatin1Lowered (lowerName, name, namelen); - lowerName[namelen] = '\0'; - tmpName.name = lowerName; - tmpName.length = namelen; - tmpName.ndashes = FontFileCountDashes (lowerName, namelen); - if (!FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO) || - !(tmpName.length = strlen (lowerName), - entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName, - &vals))) { - CopyISOLatin1Lowered (lowerName, name, namelen); - lowerName[namelen] = '\0'; - tmpName.name = lowerName; - tmpName.length = namelen; - tmpName.ndashes = FontFileCountDashes (lowerName, namelen); - entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName, &vals); - if (entry) - { - strcpy(lowerName, entry->name.name); - tmpName.name = lowerName; - tmpName.length = entry->name.length; - tmpName.ndashes = entry->name.ndashes; - } - } - - if (entry) - { - noSpecificSize = FALSE; /* TRUE breaks XLFD enhancements */ - if (entry && entry->type == FONT_ENTRY_SCALABLE && - FontFileCompleteXLFD (&vals, &entry->u.scalable.extra->defaults)) - { - scalable = &entry->u.scalable; - scaled = FontFileFindScaledInstance (entry, &vals, noSpecificSize); - /* - * A scaled instance can occur one of two ways: - * - * Either the font has been scaled to this - * size already, in which case scaled->pFont - * will point at that font. - * - * Or a bitmap instance in this size exists, - * which is handled as if we got a pattern - * matching the bitmap font name. - */ - if (scaled) - { - if (scaled->pFont) - { - *pFontInfo = &scaled->pFont->info; - ret = Successful; - } - else if (scaled->bitmap) - { - entry = scaled->bitmap; - bitmap = &entry->u.bitmap; - if (bitmap->pFont) - { - *pFontInfo = &bitmap->pFont->info; - ret = Successful; - } - else - { - ret = FontFileGetInfoBitmap (fpe, *pFontInfo, entry); - } - } - else /* "cannot" happen */ - { - ret = BadFontName; - } - } - else - { - { - char origName[MAXFONTNAMELEN]; - - CopyISOLatin1Lowered (origName, name, namelen); - origName[namelen] = '\0'; - vals.xlfdName = origName; - vals.ranges = ranges; - vals.nranges = nranges; - - /* Make a new scaled instance */ - if (strlen(dir->directory) + strlen(scalable->fileName) >= - sizeof(fileName)) { - ret = BadFontName; - } else { - strcpy (fileName, dir->directory); - strcat (fileName, scalable->fileName); - if (scalable->renderer->GetInfoScalable) - ret = (*scalable->renderer->GetInfoScalable) - (fpe, *pFontInfo, entry, &tmpName, fileName, - &vals); - else if (scalable->renderer->GetInfoBitmap) - ret = (*scalable->renderer->GetInfoBitmap) - (fpe, *pFontInfo, entry, fileName); - } - if (ranges) { - free(ranges); - ranges = NULL; - } - } - } - if (ret == Successful) return ret; - } - CopyISOLatin1Lowered (lowerName, name, namelen); - tmpName.length = namelen; - } - else - ret = BadFontName; - - if (ranges) - free(ranges); - return ret; -} - -int -FontFileListNextFontWithInfo(pointer client, FontPathElementPtr fpe, - char **namep, int *namelenp, - FontInfoPtr *pFontInfo, - int *numFonts, pointer private) -{ - LFWIDataPtr data = (LFWIDataPtr) private; - int ret; - char *name; - int namelen; - - if (data->current == data->names->nnames) - { - FreeFontNames (data->names); - free (data); - return BadFontName; - } - name = data->names->names[data->current]; - namelen = data->names->length[data->current]; - ret = FontFileListOneFontWithInfo (client, fpe, &name, &namelen, pFontInfo); - if (ret == BadFontName) - ret = AllocError; - *namep = name; - *namelenp = namelen; - ++data->current; - *numFonts = data->names->nnames - data->current; - return ret; -} - -int -FontFileStartListFontsAndAliases(pointer client, FontPathElementPtr fpe, - char *pat, int len, int max, - pointer *privatep) -{ - return FontFileStartListFonts(client, fpe, pat, len, max, privatep, 1); -} - -int -FontFileListNextFontOrAlias(pointer client, FontPathElementPtr fpe, - char **namep, int *namelenp, char **resolvedp, - int *resolvedlenp, pointer private) -{ - LFWIDataPtr data = (LFWIDataPtr) private; - int ret; - char *name; - int namelen; - - if (data->current == data->names->nnames) - { - FreeFontNames (data->names); - free (data); - return BadFontName; - } - name = data->names->names[data->current]; - namelen = data->names->length[data->current]; - - /* If this is a real font name... */ - if (namelen >= 0) - { - *namep = name; - *namelenp = namelen; - ret = Successful; - } - /* Else if an alias */ - else - { - /* Tell the caller that this is an alias... let him resolve it to - see if it's valid */ - *namep = name; - *namelenp = -namelen; - *resolvedp = data->names->names[++data->current]; - *resolvedlenp = data->names->length[data->current]; - ret = FontNameAlias; - } - - ++data->current; - return ret; -} - -void -FontFileRegisterLocalFpeFunctions (void) -{ - RegisterFPEFunctions(FontFileNameCheck, - FontFileInitFPE, - FontFileFreeFPE, - FontFileResetFPE, - FontFileOpenFont, - FontFileCloseFont, - FontFileListFonts, - FontFileStartListFontsWithInfo, - FontFileListNextFontWithInfo, - NULL, - NULL, - NULL, - FontFileStartListFontsAndAliases, - FontFileListNextFontOrAlias, - FontFileEmptyBitmapSource); -} +/*
+
+Copyright 1991, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fntfilst.h>
+#include <X11/keysym.h>
+#ifdef WIN32
+#include <ctype.h>
+#endif
+#ifdef _MSC_VER
+#define BOOL W32BOOL
+#include <windows.h>
+#undef _X_HIDDEN
+#define _X_HIDDEN static
+#endif
+
+static unsigned char
+ISOLatin1ToLower(unsigned char source)
+{
+ if (source >= XK_A && source <= XK_Z)
+ return source + (XK_a - XK_A);
+ if (source >= XK_Agrave && source <= XK_Odiaeresis)
+ return source + (XK_agrave - XK_Agrave);
+ if (source >= XK_Ooblique && source <= XK_Thorn)
+ return source + (XK_oslash - XK_Ooblique);
+ return source;
+}
+
+void
+CopyISOLatin1Lowered(char *dest, char *source, int length)
+{
+ int i;
+ for (i = 0; i < length; i++, source++, dest++)
+ *dest = ISOLatin1ToLower(*source);
+ *dest = '\0';
+}
+
+/*
+ * Map FPE functions to renderer functions
+ */
+
+static int FontFileOpenBitmapNCF (FontPathElementPtr fpe, FontPtr *pFont,
+ int flags, FontEntryPtr entry,
+ fsBitmapFormat format,
+ fsBitmapFormatMask fmask,
+ FontPtr non_cachable_font);
+
+int
+FontFileNameCheck (char *name)
+{
+#ifdef _MSC_VER
+ WIN32_FIND_DATA FindData;
+ HANDLE hFind;
+ char Tmp;
+ int LenName=strlen(name)-1;
+ Tmp=name[LenName];
+ if (Tmp=='/')
+ name[LenName]=0;
+ hFind=FindFirstFile(name,&FindData);
+ name[LenName]=Tmp;
+
+ if (hFind==INVALID_HANDLE_VALUE)
+ {
+ return 0;
+ }
+ else
+ {
+ FindClose(hFind);
+ if (FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
+ {
+ return 1;
+ }
+ return 0;
+ }
+
+#else
+#ifndef NCD
+#if defined(WIN32)
+ /* OS/2 uses D:/... as a path name for fonts, so accept this as a valid
+ * path if it starts with a letter and a colon. Same applies for WIN32
+ */
+ if (isalpha(*name) && name[1]==':')
+ return TRUE;
+#endif
+ return *name == '/';
+#else
+ return ((strcmp(name, "built-ins") == 0) || (*name == '/'));
+#endif
+#endif
+}
+
+int
+FontFileInitFPE (FontPathElementPtr fpe)
+{
+ int status;
+ FontDirectoryPtr dir;
+
+ status = FontFileReadDirectory (fpe->name, &dir);
+ if (status == Successful)
+ {
+ if (dir->nonScalable.used > 0)
+ if (!FontFileRegisterBitmapSource (fpe))
+ {
+ FontFileFreeFPE (fpe);
+ return AllocError;
+ }
+ fpe->private = (pointer) dir;
+ }
+ return status;
+}
+
+/* ARGSUSED */
+int
+FontFileResetFPE (FontPathElementPtr fpe)
+{
+ FontDirectoryPtr dir;
+
+ dir = (FontDirectoryPtr) fpe->private;
+ /*
+ * The reset must fail for bitmap fonts because they get cleared when
+ * the path is set.
+ */
+ if (FontFileDirectoryChanged (dir))
+ {
+ /* can't do it, so tell the caller to close and re-open */
+ return FPEResetFailed;
+ }
+ else
+ {
+ if (dir->nonScalable.used > 0)
+ if (!FontFileRegisterBitmapSource (fpe))
+ {
+ return FPEResetFailed;
+ }
+ return Successful;
+ }
+}
+
+int
+FontFileFreeFPE (FontPathElementPtr fpe)
+{
+ FontFileUnregisterBitmapSource (fpe);
+ FontFileFreeDir ((FontDirectoryPtr) fpe->private);
+ return Successful;
+}
+
+static int
+transfer_values_to_alias(char *entryname, int entrynamelength,
+ char *resolvedname,
+ char **aliasName, FontScalablePtr vals)
+{
+ static char aliasname[MAXFONTNAMELEN];
+ int nameok = 1, len;
+ char lowerName[MAXFONTNAMELEN];
+
+ *aliasName = resolvedname;
+ if ((len = strlen(*aliasName)) <= MAXFONTNAMELEN &&
+ (entrynamelength < MAXFONTNAMELEN) &&
+ FontFileCountDashes (*aliasName, len) == 14)
+ {
+ FontScalableRec tmpVals;
+ FontScalableRec tmpVals2;
+
+ tmpVals2 = *vals;
+
+ /* If we're aliasing a scalable name, transfer values
+ from the name into the destination alias, multiplying
+ by matrices that appear in the alias. */
+
+ CopyISOLatin1Lowered (lowerName, entryname,
+ entrynamelength);
+ lowerName[entrynamelength] = '\0';
+
+ if (FontParseXLFDName(lowerName, &tmpVals,
+ FONT_XLFD_REPLACE_NONE) &&
+ !tmpVals.values_supplied &&
+ FontParseXLFDName(*aliasName, &tmpVals,
+ FONT_XLFD_REPLACE_NONE))
+ {
+ double *matrix = 0, tempmatrix[4];
+
+ /* Use a matrix iff exactly one is defined */
+ if ((tmpVals.values_supplied & PIXELSIZE_MASK) ==
+ PIXELSIZE_ARRAY &&
+ !(tmpVals.values_supplied & POINTSIZE_MASK))
+ matrix = tmpVals.pixel_matrix;
+ else if ((tmpVals.values_supplied & POINTSIZE_MASK) ==
+ POINTSIZE_ARRAY &&
+ !(tmpVals.values_supplied & PIXELSIZE_MASK))
+ matrix = tmpVals.point_matrix;
+
+ /* If matrix given in the alias, compute new point
+ and/or pixel matrices */
+ if (matrix)
+ {
+ /* Complete the XLFD name to avoid potential
+ gotchas */
+ if (FontFileCompleteXLFD(&tmpVals2, &tmpVals2))
+ {
+ tempmatrix[0] =
+ matrix[0] * tmpVals2.point_matrix[0] +
+ matrix[1] * tmpVals2.point_matrix[2];
+ tempmatrix[1] =
+ matrix[0] * tmpVals2.point_matrix[1] +
+ matrix[1] * tmpVals2.point_matrix[3];
+ tempmatrix[2] =
+ matrix[2] * tmpVals2.point_matrix[0] +
+ matrix[3] * tmpVals2.point_matrix[2];
+ tempmatrix[3] =
+ matrix[2] * tmpVals2.point_matrix[1] +
+ matrix[3] * tmpVals2.point_matrix[3];
+ tmpVals2.point_matrix[0] = tempmatrix[0];
+ tmpVals2.point_matrix[1] = tempmatrix[1];
+ tmpVals2.point_matrix[2] = tempmatrix[2];
+ tmpVals2.point_matrix[3] = tempmatrix[3];
+
+ tempmatrix[0] =
+ matrix[0] * tmpVals2.pixel_matrix[0] +
+ matrix[1] * tmpVals2.pixel_matrix[2];
+ tempmatrix[1] =
+ matrix[0] * tmpVals2.pixel_matrix[1] +
+ matrix[1] * tmpVals2.pixel_matrix[3];
+ tempmatrix[2] =
+ matrix[2] * tmpVals2.pixel_matrix[0] +
+ matrix[3] * tmpVals2.pixel_matrix[2];
+ tempmatrix[3] =
+ matrix[2] * tmpVals2.pixel_matrix[1] +
+ matrix[3] * tmpVals2.pixel_matrix[3];
+ tmpVals2.pixel_matrix[0] = tempmatrix[0];
+ tmpVals2.pixel_matrix[1] = tempmatrix[1];
+ tmpVals2.pixel_matrix[2] = tempmatrix[2];
+ tmpVals2.pixel_matrix[3] = tempmatrix[3];
+
+ tmpVals2.values_supplied =
+ (tmpVals2.values_supplied &
+ ~(PIXELSIZE_MASK | POINTSIZE_MASK)) |
+ PIXELSIZE_ARRAY | POINTSIZE_ARRAY;
+ }
+ else
+ nameok = 0;
+ }
+
+ CopyISOLatin1Lowered (aliasname, *aliasName, len + 1);
+ if (nameok && FontParseXLFDName(aliasname, &tmpVals2,
+ FONT_XLFD_REPLACE_VALUE))
+ /* Return a version of the aliasname that has
+ had the vals stuffed into it. To avoid
+ memory leak, this alias name lives in a
+ static buffer. The caller needs to be done
+ with this buffer before this procedure is
+ called again to avoid reentrancy problems. */
+ *aliasName = aliasname;
+ }
+ }
+ return nameok;
+}
+
+/* ARGSUSED */
+int
+FontFileOpenFont (pointer client, FontPathElementPtr fpe, Mask flags,
+ char *name, int namelen,
+ fsBitmapFormat format, fsBitmapFormatMask fmask,
+ XID id, FontPtr *pFont, char **aliasName,
+ FontPtr non_cachable_font)
+{
+ FontDirectoryPtr dir;
+ char lowerName[MAXFONTNAMELEN];
+ char fileName[MAXFONTFILENAMELEN*2 + 1];
+ FontNameRec tmpName;
+ FontEntryPtr entry;
+ FontScalableRec vals;
+ FontScalableEntryPtr scalable;
+ FontScaledPtr scaled;
+ FontBitmapEntryPtr bitmap;
+ int ret;
+ Bool noSpecificSize;
+ int nranges;
+ fsRange *ranges;
+
+ if (namelen >= MAXFONTNAMELEN)
+ return AllocError;
+ dir = (FontDirectoryPtr) fpe->private;
+
+ /* Match non-scalable pattern */
+ CopyISOLatin1Lowered (lowerName, name, namelen);
+ lowerName[namelen] = '\0';
+ ranges = FontParseRanges(lowerName, &nranges);
+ tmpName.name = lowerName;
+ tmpName.length = namelen;
+ tmpName.ndashes = FontFileCountDashes (lowerName, namelen);
+ if (!FontParseXLFDName(lowerName, &vals, FONT_XLFD_REPLACE_NONE))
+ bzero(&vals, sizeof(vals));
+ if (!(entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName)) &&
+ tmpName.ndashes == 14 &&
+ FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO))
+ {
+ tmpName.length = strlen(lowerName);
+ entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName);
+ }
+
+ if (entry)
+ {
+ switch (entry->type) {
+ case FONT_ENTRY_BITMAP:
+ bitmap = &entry->u.bitmap;
+ if (bitmap->pFont)
+ {
+ *pFont = bitmap->pFont;
+ (*pFont)->fpe = fpe;
+ ret = Successful;
+ }
+ else
+ {
+ ret = FontFileOpenBitmapNCF (fpe, pFont, flags, entry, format,
+ fmask, non_cachable_font);
+ if (ret == Successful && *pFont)
+ (*pFont)->fpe = fpe;
+ }
+ break;
+ case FONT_ENTRY_ALIAS:
+ vals.nranges = nranges;
+ vals.ranges = ranges;
+ transfer_values_to_alias(entry->name.name, entry->name.length,
+ entry->u.alias.resolved, aliasName, &vals);
+ ret = FontNameAlias;
+ break;
+ default:
+ ret = BadFontName;
+ }
+ }
+ else
+ {
+ ret = BadFontName;
+ }
+
+ if (ret != BadFontName)
+ {
+ if (ranges) free(ranges);
+ return ret;
+ }
+
+ /* Match XLFD patterns */
+ CopyISOLatin1Lowered (lowerName, name, namelen);
+ lowerName[namelen] = '\0';
+ tmpName.name = lowerName;
+ tmpName.length = namelen;
+ tmpName.ndashes = FontFileCountDashes (lowerName, namelen);
+ if (!FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO) ||
+ !(tmpName.length = strlen (lowerName),
+ entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName,
+ &vals))) {
+ CopyISOLatin1Lowered (lowerName, name, namelen);
+ lowerName[namelen] = '\0';
+ tmpName.name = lowerName;
+ tmpName.length = namelen;
+ tmpName.ndashes = FontFileCountDashes (lowerName, namelen);
+ entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName, &vals);
+ if (entry)
+ {
+ strcpy(lowerName, entry->name.name);
+ tmpName.name = lowerName;
+ tmpName.length = entry->name.length;
+ tmpName.ndashes = entry->name.ndashes;
+ }
+ }
+
+ if (entry)
+ {
+ noSpecificSize = FALSE; /* TRUE breaks XLFD enhancements */
+ if (entry->type == FONT_ENTRY_SCALABLE &&
+ FontFileCompleteXLFD (&vals, &entry->u.scalable.extra->defaults))
+ {
+ scalable = &entry->u.scalable;
+ if ((vals.values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY ||
+ (vals.values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY ||
+ (vals.values_supplied &
+ ~SIZE_SPECIFY_MASK & ~CHARSUBSET_SPECIFIED))
+ scaled = 0;
+ else
+ scaled = FontFileFindScaledInstance (entry, &vals,
+ noSpecificSize);
+ /*
+ * A scaled instance can occur one of two ways:
+ *
+ * Either the font has been scaled to this
+ * size already, in which case scaled->pFont
+ * will point at that font.
+ *
+ * Or a bitmap instance in this size exists,
+ * which is handled as if we got a pattern
+ * matching the bitmap font name.
+ */
+ if (scaled)
+ {
+ if (scaled->pFont)
+ {
+ *pFont = scaled->pFont;
+ (*pFont)->fpe = fpe;
+ ret = Successful;
+ }
+ else if (scaled->bitmap)
+ {
+ entry = scaled->bitmap;
+ bitmap = &entry->u.bitmap;
+ if (bitmap->pFont)
+ {
+ *pFont = bitmap->pFont;
+ (*pFont)->fpe = fpe;
+ ret = Successful;
+ }
+ else
+ {
+ ret = FontFileOpenBitmapNCF (fpe, pFont, flags, entry,
+ format, fmask,
+ non_cachable_font);
+ if (ret == Successful && *pFont)
+ (*pFont)->fpe = fpe;
+ }
+ }
+ else /* "cannot" happen */
+ {
+ ret = BadFontName;
+ }
+ }
+ else
+ {
+ ret = FontFileMatchBitmapSource (fpe, pFont, flags, entry, &tmpName, &vals, format, fmask, noSpecificSize);
+ if (ret != Successful)
+ {
+ char origName[MAXFONTNAMELEN];
+
+ CopyISOLatin1Lowered (origName, name, namelen);
+ origName[namelen] = '\0';
+
+ /* Pass the original XLFD name in the vals
+ structure; the rasterizer is free to examine it
+ for hidden meanings. This information will not
+ be saved in the scaled-instances table. */
+
+ vals.xlfdName = origName;
+ vals.ranges = ranges;
+ vals.nranges = nranges;
+
+ if (strlen(dir->directory) + strlen(scalable->fileName) >=
+ sizeof(fileName)) {
+ ret = BadFontName;
+ } else {
+ strcpy (fileName, dir->directory);
+ strcat (fileName, scalable->fileName);
+ if (scalable->renderer->OpenScalable) {
+ ret = (*scalable->renderer->OpenScalable) (fpe, pFont,
+ flags, entry, fileName, &vals, format, fmask,
+ non_cachable_font);
+ }
+ else if (scalable->renderer->OpenBitmap) {
+ ret = (*scalable->renderer->OpenBitmap) (fpe, pFont,
+ flags, entry, fileName, format, fmask,
+ non_cachable_font);
+ }
+ }
+
+ /* In case rasterizer does something bad because of
+ charset subsetting... */
+ if (ret == Successful &&
+ ((*pFont)->info.firstCol > (*pFont)->info.lastCol ||
+ (*pFont)->info.firstRow > (*pFont)->info.lastRow))
+ {
+ (*(*pFont)->unload_font)(*pFont);
+ ret = BadFontName;
+ }
+ /* Save the instance */
+ if (ret == Successful)
+ {
+ if (FontFileAddScaledInstance (entry, &vals,
+ *pFont, (char *) 0))
+ ranges = 0;
+ else
+ (*pFont)->fpePrivate = (pointer) 0;
+ (*pFont)->fpe = fpe;
+ }
+ }
+ }
+ }
+ }
+ else
+ ret = BadFontName;
+
+ if (ranges)
+ free(ranges);
+ return ret;
+}
+
+/* ARGSUSED */
+void
+FontFileCloseFont (FontPathElementPtr fpe, FontPtr pFont)
+{
+ FontEntryPtr entry;
+
+ if ((entry = (FontEntryPtr) pFont->fpePrivate)) {
+ switch (entry->type) {
+ case FONT_ENTRY_SCALABLE:
+ FontFileRemoveScaledInstance (entry, pFont);
+ break;
+ case FONT_ENTRY_BITMAP:
+ entry->u.bitmap.pFont = 0;
+ break;
+ default:
+ /* "cannot" happen */
+ break;
+ }
+ pFont->fpePrivate = 0;
+ }
+ (*pFont->unload_font) (pFont);
+}
+
+static int
+FontFileOpenBitmapNCF (FontPathElementPtr fpe, FontPtr *pFont,
+ int flags, FontEntryPtr entry,
+ fsBitmapFormat format, fsBitmapFormatMask fmask,
+ FontPtr non_cachable_font)
+{
+ FontBitmapEntryPtr bitmap;
+ char fileName[MAXFONTFILENAMELEN*2+1];
+ int ret;
+ FontDirectoryPtr dir;
+
+ dir = (FontDirectoryPtr) fpe->private;
+ bitmap = &entry->u.bitmap;
+ if(!bitmap || !bitmap->renderer->OpenBitmap)
+ return BadFontName;
+ if (strlen(dir->directory) + strlen(bitmap->fileName) >= sizeof(fileName))
+ return BadFontName;
+ strcpy (fileName, dir->directory);
+ strcat (fileName, bitmap->fileName);
+ ret = (*bitmap->renderer->OpenBitmap)
+ (fpe, pFont, flags, entry, fileName, format, fmask,
+ non_cachable_font);
+ if (ret == Successful)
+ {
+ bitmap->pFont = *pFont;
+ (*pFont)->fpePrivate = (pointer) entry;
+ }
+ return ret;
+}
+
+int
+FontFileOpenBitmap (FontPathElementPtr fpe, FontPtr *pFont,
+ int flags, FontEntryPtr entry,
+ fsBitmapFormat format, fsBitmapFormatMask fmask)
+{
+ return FontFileOpenBitmapNCF (fpe, pFont, flags, entry, format, fmask,
+ (FontPtr)0);
+}
+
+static int
+FontFileGetInfoBitmap (FontPathElementPtr fpe, FontInfoPtr pFontInfo,
+ FontEntryPtr entry)
+{
+ FontBitmapEntryPtr bitmap;
+ char fileName[MAXFONTFILENAMELEN*2+1];
+ int ret;
+ FontDirectoryPtr dir;
+
+ dir = (FontDirectoryPtr) fpe->private;
+ bitmap = &entry->u.bitmap;
+ if (!bitmap || !bitmap->renderer->GetInfoBitmap)
+ return BadFontName;
+ if (strlen(dir->directory) + strlen(bitmap->fileName) >= sizeof(fileName))
+ return BadFontName;
+ strcpy (fileName, dir->directory);
+ strcat (fileName, bitmap->fileName);
+ ret = (*bitmap->renderer->GetInfoBitmap) (fpe, pFontInfo, entry, fileName);
+ return ret;
+}
+
+static void
+_FontFileAddScalableNames(FontNamesPtr names, FontNamesPtr scaleNames,
+ FontNamePtr nameptr, char *zeroChars,
+ FontScalablePtr vals, fsRange *ranges,
+ int nranges, int *max)
+{
+ int i;
+ FontScalableRec zeroVals, tmpVals;
+ for (i = 0; i < scaleNames->nnames; i++)
+ {
+ char nameChars[MAXFONTNAMELEN];
+ if (!*max)
+ return;
+ FontParseXLFDName (scaleNames->names[i], &zeroVals,
+ FONT_XLFD_REPLACE_NONE);
+ tmpVals = *vals;
+ if (FontFileCompleteXLFD (&tmpVals, &zeroVals))
+ {
+ --*max;
+
+ strcpy (nameChars, scaleNames->names[i]);
+ if ((vals->values_supplied & PIXELSIZE_MASK) ||
+ !(vals->values_supplied & PIXELSIZE_WILDCARD) ||
+ vals->y == 0)
+ {
+ tmpVals.values_supplied =
+ (tmpVals.values_supplied & ~PIXELSIZE_MASK) |
+ (vals->values_supplied & PIXELSIZE_MASK);
+ tmpVals.pixel_matrix[0] = vals->pixel_matrix[0];
+ tmpVals.pixel_matrix[1] = vals->pixel_matrix[1];
+ tmpVals.pixel_matrix[2] = vals->pixel_matrix[2];
+ tmpVals.pixel_matrix[3] = vals->pixel_matrix[3];
+ }
+ if ((vals->values_supplied & POINTSIZE_MASK) ||
+ !(vals->values_supplied & POINTSIZE_WILDCARD) ||
+ vals->y == 0)
+ {
+ tmpVals.values_supplied =
+ (tmpVals.values_supplied & ~POINTSIZE_MASK) |
+ (vals->values_supplied & POINTSIZE_MASK);
+ tmpVals.point_matrix[0] = vals->point_matrix[0];
+ tmpVals.point_matrix[1] = vals->point_matrix[1];
+ tmpVals.point_matrix[2] = vals->point_matrix[2];
+ tmpVals.point_matrix[3] = vals->point_matrix[3];
+ }
+ if (vals->width <= 0)
+ tmpVals.width = 0;
+ if (vals->x == 0)
+ tmpVals.x = 0;
+ if (vals->y == 0)
+ tmpVals.y = 0;
+ tmpVals.ranges = ranges;
+ tmpVals.nranges = nranges;
+ FontParseXLFDName (nameChars, &tmpVals,
+ FONT_XLFD_REPLACE_VALUE);
+ /* If we're marking aliases with negative lengths, we
+ need to concoct a valid target name to follow it.
+ Otherwise we're done. */
+ if (scaleNames->length[i] >= 0)
+ {
+ (void) AddFontNamesName (names, nameChars,
+ strlen (nameChars));
+ /* If our original pattern matches the name from
+ the table and that name doesn't duplicate what
+ we just added, add the name from the table */
+ if (strcmp(nameChars, scaleNames->names[i]) &&
+ FontFileMatchName(scaleNames->names[i],
+ scaleNames->length[i],
+ nameptr) &&
+ *max)
+ {
+ --*max;
+ (void) AddFontNamesName (names, scaleNames->names[i],
+ scaleNames->length[i]);
+ }
+ }
+ else
+ {
+ char *aliasName;
+ vals->ranges = ranges;
+ vals->nranges = nranges;
+ if (transfer_values_to_alias(zeroChars,
+ strlen(zeroChars),
+ scaleNames->names[++i],
+ &aliasName, vals))
+ {
+ (void) AddFontNamesName (names, nameChars,
+ strlen (nameChars));
+ names->length[names->nnames - 1] =
+ -names->length[names->nnames - 1];
+ (void) AddFontNamesName (names, aliasName,
+ strlen (aliasName));
+ /* If our original pattern matches the name from
+ the table and that name doesn't duplicate what
+ we just added, add the name from the table */
+ if (strcmp(nameChars, scaleNames->names[i - 1]) &&
+ FontFileMatchName(scaleNames->names[i - 1],
+ -scaleNames->length[i - 1],
+ nameptr) &&
+ *max)
+ {
+ --*max;
+ (void) AddFontNamesName (names,
+ scaleNames->names[i - 1],
+ -scaleNames->length[i - 1]);
+ names->length[names->nnames - 1] =
+ -names->length[names->nnames - 1];
+ (void) AddFontNamesName (names, aliasName,
+ strlen (aliasName));
+ }
+ }
+ }
+ }
+ }
+}
+
+/* ARGSUSED */
+static int
+_FontFileListFonts (pointer client, FontPathElementPtr fpe,
+ char *pat, int len, int max, FontNamesPtr names,
+ int mark_aliases)
+{
+ FontDirectoryPtr dir;
+ char lowerChars[MAXFONTNAMELEN], zeroChars[MAXFONTNAMELEN];
+ FontNameRec lowerName;
+ FontNameRec zeroName;
+ FontNamesPtr scaleNames;
+ FontScalableRec vals;
+ fsRange *ranges;
+ int nranges;
+ int result = BadFontName;
+
+ if (len >= MAXFONTNAMELEN)
+ return AllocError;
+ dir = (FontDirectoryPtr) fpe->private;
+ CopyISOLatin1Lowered (lowerChars, pat, len);
+ lowerChars[len] = '\0';
+ lowerName.name = lowerChars;
+ lowerName.length = len;
+ lowerName.ndashes = FontFileCountDashes (lowerChars, len);
+
+ /* Match XLFD patterns */
+
+ strcpy (zeroChars, lowerChars);
+ if (lowerName.ndashes == 14 &&
+ FontParseXLFDName (zeroChars, &vals, FONT_XLFD_REPLACE_ZERO))
+ {
+ ranges = FontParseRanges(lowerChars, &nranges);
+ result = FontFileFindNamesInScalableDir (&dir->nonScalable,
+ &lowerName, max, names,
+ (FontScalablePtr)0,
+ (mark_aliases ?
+ LIST_ALIASES_AND_TARGET_NAMES :
+ NORMAL_ALIAS_BEHAVIOR) |
+ IGNORE_SCALABLE_ALIASES,
+ &max);
+ zeroName.name = zeroChars;
+ zeroName.length = strlen (zeroChars);
+ zeroName.ndashes = lowerName.ndashes;
+
+ /* Look for scalable names and aliases, adding scaled instances of
+ them to the output */
+
+ /* Scalable names... */
+ scaleNames = MakeFontNamesRecord (0);
+ if (!scaleNames)
+ {
+ if (ranges) free(ranges);
+ return AllocError;
+ }
+ FontFileFindNamesInScalableDir (&dir->scalable, &zeroName, max,
+ scaleNames, &vals,
+ mark_aliases ?
+ LIST_ALIASES_AND_TARGET_NAMES :
+ NORMAL_ALIAS_BEHAVIOR, (int *)0);
+ _FontFileAddScalableNames(names, scaleNames, &lowerName,
+ zeroChars, &vals, ranges, nranges,
+ &max);
+ FreeFontNames (scaleNames);
+
+ /* Scalable aliases... */
+ scaleNames = MakeFontNamesRecord (0);
+ if (!scaleNames)
+ {
+ if (ranges) free(ranges);
+ return AllocError;
+ }
+ FontFileFindNamesInScalableDir (&dir->nonScalable, &zeroName,
+ max, scaleNames, &vals,
+ mark_aliases ?
+ LIST_ALIASES_AND_TARGET_NAMES :
+ NORMAL_ALIAS_BEHAVIOR, (int *)0);
+ _FontFileAddScalableNames(names, scaleNames, &lowerName,
+ zeroChars, &vals, ranges, nranges,
+ &max);
+ FreeFontNames (scaleNames);
+
+ if (ranges) free(ranges);
+ }
+ else
+ {
+ result = FontFileFindNamesInScalableDir (&dir->nonScalable,
+ &lowerName, max, names,
+ (FontScalablePtr)0,
+ mark_aliases ?
+ LIST_ALIASES_AND_TARGET_NAMES :
+ NORMAL_ALIAS_BEHAVIOR,
+ &max);
+ if (result == Successful)
+ result = FontFileFindNamesInScalableDir (&dir->scalable,
+ &lowerName, max, names,
+ (FontScalablePtr)0,
+ mark_aliases ?
+ LIST_ALIASES_AND_TARGET_NAMES :
+ NORMAL_ALIAS_BEHAVIOR, (int *)0);
+ }
+ return result;
+}
+
+typedef struct _LFWIData {
+ FontNamesPtr names;
+ int current;
+} LFWIDataRec, *LFWIDataPtr;
+
+int
+FontFileListFonts (pointer client, FontPathElementPtr fpe, char *pat,
+ int len, int max, FontNamesPtr names)
+{
+ return _FontFileListFonts (client, fpe, pat, len, max, names, 0);
+}
+
+int
+FontFileStartListFonts(pointer client, FontPathElementPtr fpe,
+ char *pat, int len, int max,
+ pointer *privatep, int mark_aliases)
+{
+ LFWIDataPtr data;
+ int ret;
+
+ data = malloc (sizeof *data);
+ if (!data)
+ return AllocError;
+ data->names = MakeFontNamesRecord (0);
+ if (!data->names)
+ {
+ free (data);
+ return AllocError;
+ }
+ ret = _FontFileListFonts (client, fpe, pat, len,
+ max, data->names, mark_aliases);
+ if (ret != Successful)
+ {
+ FreeFontNames (data->names);
+ free (data);
+ return ret;
+ }
+ data->current = 0;
+ *privatep = (pointer) data;
+ return Successful;
+}
+
+
+int
+FontFileStartListFontsWithInfo(pointer client, FontPathElementPtr fpe,
+ char *pat, int len, int max,
+ pointer *privatep)
+{
+ return FontFileStartListFonts(client, fpe, pat, len, max, privatep, 0);
+}
+
+/* ARGSUSED */
+static int
+FontFileListOneFontWithInfo (pointer client, FontPathElementPtr fpe,
+ char **namep, int *namelenp,
+ FontInfoPtr *pFontInfo)
+{
+ FontDirectoryPtr dir;
+ char lowerName[MAXFONTNAMELEN];
+ char fileName[MAXFONTFILENAMELEN*2 + 1];
+ FontNameRec tmpName;
+ FontEntryPtr entry;
+ FontScalableRec vals;
+ FontScalableEntryPtr scalable;
+ FontScaledPtr scaled;
+ FontBitmapEntryPtr bitmap;
+ int ret;
+ Bool noSpecificSize;
+ int nranges;
+ fsRange *ranges;
+
+ char *name = *namep;
+ int namelen = *namelenp;
+
+ if (namelen >= MAXFONTNAMELEN)
+ return AllocError;
+ dir = (FontDirectoryPtr) fpe->private;
+
+ /* Match non-scalable pattern */
+ CopyISOLatin1Lowered (lowerName, name, namelen);
+ lowerName[namelen] = '\0';
+ ranges = FontParseRanges(lowerName, &nranges);
+ tmpName.name = lowerName;
+ tmpName.length = namelen;
+ tmpName.ndashes = FontFileCountDashes (lowerName, namelen);
+ if (!FontParseXLFDName(lowerName, &vals, FONT_XLFD_REPLACE_NONE))
+ bzero(&vals, sizeof(vals));
+ if (!(entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName)) &&
+ tmpName.ndashes == 14 &&
+ FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO))
+ {
+ tmpName.length = strlen(lowerName);
+ entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName);
+ }
+
+ if (entry)
+ {
+ switch (entry->type) {
+ case FONT_ENTRY_BITMAP:
+ bitmap = &entry->u.bitmap;
+ if (bitmap->pFont)
+ {
+ *pFontInfo = &bitmap->pFont->info;
+ ret = Successful;
+ }
+ else
+ {
+ ret = FontFileGetInfoBitmap (fpe, *pFontInfo, entry);
+ }
+ break;
+ case FONT_ENTRY_ALIAS:
+ vals.nranges = nranges;
+ vals.ranges = ranges;
+ transfer_values_to_alias(entry->name.name, entry->name.length,
+ entry->u.alias.resolved, namep, &vals);
+ *namelenp = strlen (*namep);
+ ret = FontNameAlias;
+ break;
+ default:
+ ret = BadFontName;
+ }
+ }
+ else
+ {
+ ret = BadFontName;
+ }
+
+ if (ret != BadFontName)
+ {
+ if (ranges) free(ranges);
+ return ret;
+ }
+
+ /* Match XLFD patterns */
+ CopyISOLatin1Lowered (lowerName, name, namelen);
+ lowerName[namelen] = '\0';
+ tmpName.name = lowerName;
+ tmpName.length = namelen;
+ tmpName.ndashes = FontFileCountDashes (lowerName, namelen);
+ if (!FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO) ||
+ !(tmpName.length = strlen (lowerName),
+ entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName,
+ &vals))) {
+ CopyISOLatin1Lowered (lowerName, name, namelen);
+ lowerName[namelen] = '\0';
+ tmpName.name = lowerName;
+ tmpName.length = namelen;
+ tmpName.ndashes = FontFileCountDashes (lowerName, namelen);
+ entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName, &vals);
+ if (entry)
+ {
+ strcpy(lowerName, entry->name.name);
+ tmpName.name = lowerName;
+ tmpName.length = entry->name.length;
+ tmpName.ndashes = entry->name.ndashes;
+ }
+ }
+
+ if (entry)
+ {
+ noSpecificSize = FALSE; /* TRUE breaks XLFD enhancements */
+ if (entry && entry->type == FONT_ENTRY_SCALABLE &&
+ FontFileCompleteXLFD (&vals, &entry->u.scalable.extra->defaults))
+ {
+ scalable = &entry->u.scalable;
+ scaled = FontFileFindScaledInstance (entry, &vals, noSpecificSize);
+ /*
+ * A scaled instance can occur one of two ways:
+ *
+ * Either the font has been scaled to this
+ * size already, in which case scaled->pFont
+ * will point at that font.
+ *
+ * Or a bitmap instance in this size exists,
+ * which is handled as if we got a pattern
+ * matching the bitmap font name.
+ */
+ if (scaled)
+ {
+ if (scaled->pFont)
+ {
+ *pFontInfo = &scaled->pFont->info;
+ ret = Successful;
+ }
+ else if (scaled->bitmap)
+ {
+ entry = scaled->bitmap;
+ bitmap = &entry->u.bitmap;
+ if (bitmap->pFont)
+ {
+ *pFontInfo = &bitmap->pFont->info;
+ ret = Successful;
+ }
+ else
+ {
+ ret = FontFileGetInfoBitmap (fpe, *pFontInfo, entry);
+ }
+ }
+ else /* "cannot" happen */
+ {
+ ret = BadFontName;
+ }
+ }
+ else
+ {
+ {
+ char origName[MAXFONTNAMELEN];
+
+ CopyISOLatin1Lowered (origName, name, namelen);
+ origName[namelen] = '\0';
+ vals.xlfdName = origName;
+ vals.ranges = ranges;
+ vals.nranges = nranges;
+
+ /* Make a new scaled instance */
+ if (strlen(dir->directory) + strlen(scalable->fileName) >=
+ sizeof(fileName)) {
+ ret = BadFontName;
+ } else {
+ strcpy (fileName, dir->directory);
+ strcat (fileName, scalable->fileName);
+ if (scalable->renderer->GetInfoScalable)
+ ret = (*scalable->renderer->GetInfoScalable)
+ (fpe, *pFontInfo, entry, &tmpName, fileName,
+ &vals);
+ else if (scalable->renderer->GetInfoBitmap)
+ ret = (*scalable->renderer->GetInfoBitmap)
+ (fpe, *pFontInfo, entry, fileName);
+ }
+ if (ranges) {
+ free(ranges);
+ ranges = NULL;
+ }
+ }
+ }
+ if (ret == Successful) return ret;
+ }
+ CopyISOLatin1Lowered (lowerName, name, namelen);
+ tmpName.length = namelen;
+ }
+ else
+ ret = BadFontName;
+
+ if (ranges)
+ free(ranges);
+ return ret;
+}
+
+int
+FontFileListNextFontWithInfo(pointer client, FontPathElementPtr fpe,
+ char **namep, int *namelenp,
+ FontInfoPtr *pFontInfo,
+ int *numFonts, pointer private)
+{
+ LFWIDataPtr data = (LFWIDataPtr) private;
+ int ret;
+ char *name;
+ int namelen;
+
+ if (data->current == data->names->nnames)
+ {
+ FreeFontNames (data->names);
+ free (data);
+ return BadFontName;
+ }
+ name = data->names->names[data->current];
+ namelen = data->names->length[data->current];
+ ret = FontFileListOneFontWithInfo (client, fpe, &name, &namelen, pFontInfo);
+ if (ret == BadFontName)
+ ret = AllocError;
+ *namep = name;
+ *namelenp = namelen;
+ ++data->current;
+ *numFonts = data->names->nnames - data->current;
+ return ret;
+}
+
+int
+FontFileStartListFontsAndAliases(pointer client, FontPathElementPtr fpe,
+ char *pat, int len, int max,
+ pointer *privatep)
+{
+ return FontFileStartListFonts(client, fpe, pat, len, max, privatep, 1);
+}
+
+int
+FontFileListNextFontOrAlias(pointer client, FontPathElementPtr fpe,
+ char **namep, int *namelenp, char **resolvedp,
+ int *resolvedlenp, pointer private)
+{
+ LFWIDataPtr data = (LFWIDataPtr) private;
+ int ret;
+ char *name;
+ int namelen;
+
+ if (data->current == data->names->nnames)
+ {
+ FreeFontNames (data->names);
+ free (data);
+ return BadFontName;
+ }
+ name = data->names->names[data->current];
+ namelen = data->names->length[data->current];
+
+ /* If this is a real font name... */
+ if (namelen >= 0)
+ {
+ *namep = name;
+ *namelenp = namelen;
+ ret = Successful;
+ }
+ /* Else if an alias */
+ else
+ {
+ /* Tell the caller that this is an alias... let him resolve it to
+ see if it's valid */
+ *namep = name;
+ *namelenp = -namelen;
+ *resolvedp = data->names->names[++data->current];
+ *resolvedlenp = data->names->length[data->current];
+ ret = FontNameAlias;
+ }
+
+ ++data->current;
+ return ret;
+}
+
+void
+FontFileRegisterLocalFpeFunctions (void)
+{
+ RegisterFPEFunctions(FontFileNameCheck,
+ FontFileInitFPE,
+ FontFileFreeFPE,
+ FontFileResetFPE,
+ FontFileOpenFont,
+ FontFileCloseFont,
+ FontFileListFonts,
+ FontFileStartListFontsWithInfo,
+ FontFileListNextFontWithInfo,
+ NULL,
+ NULL,
+ NULL,
+ FontFileStartListFontsAndAliases,
+ FontFileListNextFontOrAlias,
+ FontFileEmptyBitmapSource);
+}
diff --git a/libXfont/src/fontfile/fontscale.c b/libXfont/src/fontfile/fontscale.c index 55aca298a..524db98d0 100644 --- a/libXfont/src/fontfile/fontscale.c +++ b/libXfont/src/fontfile/fontscale.c @@ -1,437 +1,441 @@ -/* - -Copyright 1991, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fntfilst.h> -#include <math.h> - -Bool -FontFileAddScaledInstance (FontEntryPtr entry, FontScalablePtr vals, - FontPtr pFont, char *bitmapName) -{ - FontScalableEntryPtr scalable; - FontScalableExtraPtr extra; - FontScaledPtr new; - int newsize; - - scalable = &entry->u.scalable; - extra = scalable->extra; - if (extra->numScaled == extra->sizeScaled) - { - newsize = extra->sizeScaled + 4; - new = realloc (extra->scaled, newsize * sizeof (FontScaledRec)); - if (!new) - return FALSE; - extra->sizeScaled = newsize; - extra->scaled = new; - } - new = &extra->scaled[extra->numScaled++]; - new->vals = *vals; - new->pFont = pFont; - new->bitmap = (FontEntryPtr) bitmapName; - if (pFont) - pFont->fpePrivate = (pointer) entry; - return TRUE; -} - -/* Must call this after the directory is sorted */ - -void -FontFileSwitchStringsToBitmapPointers (FontDirectoryPtr dir) -{ - int s; - int b; - int i; - FontEntryPtr scalable; - FontEntryPtr nonScalable; - FontScaledPtr scaled; - FontScalableExtraPtr extra; - - scalable = dir->scalable.entries; - nonScalable = dir->nonScalable.entries; - for (s = 0; s < dir->scalable.used; s++) - { - extra = scalable[s].u.scalable.extra; - scaled = extra->scaled; - for (i = 0; i < extra->numScaled; i++) - for (b = 0; b < dir->nonScalable.used; b++) - if (nonScalable[b].name.name == (char *) scaled[i].bitmap) - scaled[i].bitmap = &nonScalable[b]; - } -} - -void -FontFileRemoveScaledInstance (FontEntryPtr entry, FontPtr pFont) -{ - FontScalableEntryPtr scalable; - FontScalableExtraPtr extra; - int i; - - scalable = &entry->u.scalable; - extra = scalable->extra; - for (i = 0; i < extra->numScaled; i++) - { - if (extra->scaled[i].pFont == pFont) - { - if (extra->scaled[i].vals.ranges) - free (extra->scaled[i].vals.ranges); - extra->numScaled--; - for (; i < extra->numScaled; i++) - extra->scaled[i] = extra->scaled[i+1]; - } - } -} - -Bool -FontFileCompleteXLFD (FontScalablePtr vals, FontScalablePtr def) -{ - FontResolutionPtr res; - int num_res; - double sx, sy, temp_matrix[4]; - double pixel_setsize_adjustment = 1.0; - /* - * If two of the three vertical scale values are specified, compute the - * third. If all three are specified, make sure they are consistent - * (within a pixel) - * - * One purpose of this procedure is to complete XLFD names in a - * repeatable manner. That is, if the user partially specifies - * a name (say, pixelsize but not pointsize), the results generated - * here result in a fully specified name that will result in the - * same font. - */ - - res = GetClientResolutions(&num_res); - - if (!(vals->values_supplied & PIXELSIZE_MASK) || - !(vals->values_supplied & POINTSIZE_MASK)) - { - /* If resolution(s) unspecified and cannot be computed from - pixelsize and pointsize, get appropriate defaults. */ - - if (num_res) - { - if (vals->x <= 0) - vals->x = res->x_resolution; - if (vals->y <= 0) - vals->y = res->y_resolution; - } - - if (vals->x <= 0) - vals->x = def->x; - if (vals->y <= 0) - vals->y = def->y; - } - else - { - /* If needed, compute resolution values from the pixel and - pointsize information we were given. This problem is - overdetermined (four equations, two unknowns), but we don't - check for inconsistencies here. If they exist, they will - show up in later tests for the point and pixel sizes. */ - - if (vals->y <= 0) - { - double x = hypot(vals->pixel_matrix[1], vals->pixel_matrix[3]); - double y = hypot(vals->point_matrix[1], vals->point_matrix[3]); - if (y < EPS) return FALSE; - vals->y = (int)(x * 72.27 / y + .5); - } - if (vals->x <= 0) - { - /* If the pixelsize was given as an array, or as a scalar that - has been normalized for the pixel shape, we have enough - information to compute a separate horizontal resolution */ - - if ((vals->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY || - (vals->values_supplied & PIXELSIZE_MASK) == - PIXELSIZE_SCALAR_NORMALIZED) - { - double x = hypot(vals->pixel_matrix[0], vals->pixel_matrix[2]); - double y = hypot(vals->point_matrix[0], vals->point_matrix[2]); - if (y < EPS) return FALSE; - vals->x = (int)(x * 72.27 / y + .5); - } - else - { - /* Not enough information in the pixelsize array. Just - assume the pixels are square. */ - vals->x = vals->y; - } - } - } - - if (vals->x <= 0 || vals->y <= 0) return FALSE; - - /* If neither pixelsize nor pointsize is defined, take the pointsize - from the defaults structure we've been passed. */ - if (!(vals->values_supplied & PIXELSIZE_MASK) && - !(vals->values_supplied & POINTSIZE_MASK)) - { - if (num_res) - { - vals->point_matrix[0] = - vals->point_matrix[3] = (double)res->point_size / 10.0; - vals->point_matrix[1] = - vals->point_matrix[2] = 0; - vals->values_supplied = (vals->values_supplied & ~POINTSIZE_MASK) | - POINTSIZE_SCALAR; - } - else if (def->values_supplied & POINTSIZE_MASK) - { - vals->point_matrix[0] = def->point_matrix[0]; - vals->point_matrix[1] = def->point_matrix[1]; - vals->point_matrix[2] = def->point_matrix[2]; - vals->point_matrix[3] = def->point_matrix[3]; - vals->values_supplied = (vals->values_supplied & ~POINTSIZE_MASK) | - (def->values_supplied & POINTSIZE_MASK); - } - else return FALSE; - } - - /* At this point, at least two of the three vertical scale values - should be specified. Our job now is to compute the missing ones - and check for agreement between overspecified values */ - - /* If pixelsize was specified by a scalar, we need to fix the matrix - now that we know the resolutions. */ - if ((vals->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_SCALAR) - { - /* pixel_setsize_adjustment used below to modify permissible - error in pixel/pointsize matching, since multiplying a - number rounded to integer changes the amount of the error - caused by the rounding */ - - pixel_setsize_adjustment = (double)vals->x / (double)vals->y; - vals->pixel_matrix[0] *= pixel_setsize_adjustment; - vals->values_supplied = (vals->values_supplied & ~PIXELSIZE_MASK) | - PIXELSIZE_SCALAR_NORMALIZED; - } - - sx = (double)vals->x / 72.27; - sy = (double)vals->y / 72.27; - - /* If a pointsize was specified, make sure pixelsize is consistent - to within 1 pixel, then replace pixelsize with a consistent - floating-point value. */ - - if (vals->values_supplied & POINTSIZE_MASK) - { - recompute_pixelsize: ; - temp_matrix[0] = vals->point_matrix[0] * sx; - temp_matrix[1] = vals->point_matrix[1] * sy; - temp_matrix[2] = vals->point_matrix[2] * sx; - temp_matrix[3] = vals->point_matrix[3] * sy; - if (vals->values_supplied & PIXELSIZE_MASK) - { - if (fabs(vals->pixel_matrix[0] - temp_matrix[0]) > - pixel_setsize_adjustment || - fabs(vals->pixel_matrix[1] - temp_matrix[1]) > 1 || - fabs(vals->pixel_matrix[2] - temp_matrix[2]) > 1 || - fabs(vals->pixel_matrix[3] - temp_matrix[3]) > 1) - return FALSE; - } - if ((vals->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY && - (vals->values_supplied & POINTSIZE_MASK) == POINTSIZE_SCALAR) - { - /* In the special case that pixelsize came as an array and - pointsize as a scalar, recompute the pointsize matrix - from the pixelsize matrix. */ - goto recompute_pointsize; - } - - /* Refresh pixel matrix with precise values computed from - pointsize and resolution. */ - vals->pixel_matrix[0] = temp_matrix[0]; - vals->pixel_matrix[1] = temp_matrix[1]; - vals->pixel_matrix[2] = temp_matrix[2]; - vals->pixel_matrix[3] = temp_matrix[3]; - - /* Set values_supplied for pixel to match that for point */ - vals->values_supplied = - (vals->values_supplied & ~PIXELSIZE_MASK) | - (((vals->values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY) ? - PIXELSIZE_ARRAY : PIXELSIZE_SCALAR_NORMALIZED); - } - else - { - /* Pointsize unspecified... compute from pixel size and - resolutions */ - recompute_pointsize: ; - if (fabs(sx) < EPS || fabs(sy) < EPS) return FALSE; - vals->point_matrix[0] = vals->pixel_matrix[0] / sx; - vals->point_matrix[1] = vals->pixel_matrix[1] / sy; - vals->point_matrix[2] = vals->pixel_matrix[2] / sx; - vals->point_matrix[3] = vals->pixel_matrix[3] / sy; - - /* Set values_supplied for pixel to match that for point */ - vals->values_supplied = - (vals->values_supplied & ~POINTSIZE_MASK) | - (((vals->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY) ? - POINTSIZE_ARRAY : POINTSIZE_SCALAR); - - /* If we computed scalar pointsize from scalar pixelsize, round - pointsize to decipoints and recompute pixelsize so we end up - with a repeatable name */ - if ((vals->values_supplied & POINTSIZE_MASK) == POINTSIZE_SCALAR) - { - /* Off-diagonal elements should be zero since no matrix was - specified. */ - vals->point_matrix[0] = - (double)(int)(vals->point_matrix[0] * 10.0 + .5) / 10.0; - vals->point_matrix[3] = - (double)(int)(vals->point_matrix[3] * 10.0 + .5) / 10.0; - goto recompute_pixelsize; - } - } - - /* We've succeeded. Round everything to a few decimal places - for repeatability. */ - - vals->pixel_matrix[0] = xlfd_round_double(vals->pixel_matrix[0]); - vals->pixel_matrix[1] = xlfd_round_double(vals->pixel_matrix[1]); - vals->pixel_matrix[2] = xlfd_round_double(vals->pixel_matrix[2]); - vals->pixel_matrix[3] = xlfd_round_double(vals->pixel_matrix[3]); - vals->point_matrix[0] = xlfd_round_double(vals->point_matrix[0]); - vals->point_matrix[1] = xlfd_round_double(vals->point_matrix[1]); - vals->point_matrix[2] = xlfd_round_double(vals->point_matrix[2]); - vals->point_matrix[3] = xlfd_round_double(vals->point_matrix[3]); - - /* Fill in the deprecated fields for the benefit of rasterizers - that do not handle the matrices. */ - vals->point = vals->point_matrix[3] * 10; - vals->pixel = vals->pixel_matrix[3]; - - return TRUE; -} - -static Bool -MatchScalable (FontScalablePtr a, FontScalablePtr b) -{ - int i; - - /* Some asymmetry here: we assume that the first argument (a) is - the table entry and the second (b) the item we're trying to match - (the key). We'll consider the fonts matched if the relevant - metrics match *and* if a) the table entry doesn't have charset - subsetting or b) the table entry has identical charset subsetting - to that in the key. We could add logic to check if the table - entry has a superset of the charset required by the key, but - we'll resist the urge for now. */ - -#define EQUAL(a,b) ((a)[0] == (b)[0] && \ - (a)[1] == (b)[1] && \ - (a)[2] == (b)[2] && \ - (a)[3] == (b)[3]) - - if (!(a->x == b->x && - a->y == b->y && - (a->width == b->width || a->width == 0 || b->width == 0 || b->width == -1) && - (!(b->values_supplied & PIXELSIZE_MASK) || - ((a->values_supplied & PIXELSIZE_MASK) == - (b->values_supplied & PIXELSIZE_MASK) && - EQUAL(a->pixel_matrix, b->pixel_matrix))) && - (!(b->values_supplied & POINTSIZE_MASK) || - ((a->values_supplied & POINTSIZE_MASK) == - (b->values_supplied & POINTSIZE_MASK) && - EQUAL(a->point_matrix, b->point_matrix))) && - (a->nranges == 0 || a->nranges == b->nranges))) - return FALSE; - - for (i = 0; i < a->nranges; i++) - if (a->ranges[i].min_char_low != b->ranges[i].min_char_low || - a->ranges[i].min_char_high != b->ranges[i].min_char_high || - a->ranges[i].max_char_low != b->ranges[i].max_char_low || - a->ranges[i].max_char_high != b->ranges[i].max_char_high) - return FALSE; - - return TRUE; -} - -FontScaledPtr -FontFileFindScaledInstance (FontEntryPtr entry, FontScalablePtr vals, - int noSpecificSize) -{ - FontScalableEntryPtr scalable; - FontScalableExtraPtr extra; - FontScalablePtr mvals; - int dist, i; - int mini; - double mindist; - register double temp, sum=0.0; - -#define NORMDIFF(a, b) ( \ - temp = (a)[0] - (b)[0], \ - sum = temp * temp, \ - temp = (a)[1] - (b)[1], \ - sum += temp * temp, \ - temp = (a)[2] - (b)[2], \ - sum += temp * temp, \ - temp = (a)[3] - (b)[3], \ - sum + temp * temp ) - - scalable = &entry->u.scalable; - extra = scalable->extra; - if (noSpecificSize && extra->numScaled) - { - mini = 0; - mindist = NORMDIFF(extra->scaled[0].vals.point_matrix, - vals->point_matrix); - for (i = 1; i < extra->numScaled; i++) - { - if (extra->scaled[i].pFont && - !extra->scaled[i].pFont->info.cachable) continue; - mvals = &extra->scaled[i].vals; - dist = NORMDIFF(mvals->point_matrix, vals->point_matrix); - if (dist < mindist) - { - mindist = dist; - mini = i; - } - } - if (extra->scaled[mini].pFont && - !extra->scaled[mini].pFont->info.cachable) return 0; - return &extra->scaled[mini]; - } - else - { - /* See if we've scaled to this value yet */ - for (i = 0; i < extra->numScaled; i++) - { - if (extra->scaled[i].pFont && - !extra->scaled[i].pFont->info.cachable) continue; - if (MatchScalable (&extra->scaled[i].vals, vals)) - return &extra->scaled[i]; - } - } - return 0; -} +/*
+
+Copyright 1991, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fntfilst.h>
+#include <math.h>
+
+#ifdef _MSC_VER
+#define hypot _hypot
+#endif
+
+Bool
+FontFileAddScaledInstance (FontEntryPtr entry, FontScalablePtr vals,
+ FontPtr pFont, char *bitmapName)
+{
+ FontScalableEntryPtr scalable;
+ FontScalableExtraPtr extra;
+ FontScaledPtr new;
+ int newsize;
+
+ scalable = &entry->u.scalable;
+ extra = scalable->extra;
+ if (extra->numScaled == extra->sizeScaled)
+ {
+ newsize = extra->sizeScaled + 4;
+ new = realloc (extra->scaled, newsize * sizeof (FontScaledRec));
+ if (!new)
+ return FALSE;
+ extra->sizeScaled = newsize;
+ extra->scaled = new;
+ }
+ new = &extra->scaled[extra->numScaled++];
+ new->vals = *vals;
+ new->pFont = pFont;
+ new->bitmap = (FontEntryPtr) bitmapName;
+ if (pFont)
+ pFont->fpePrivate = (pointer) entry;
+ return TRUE;
+}
+
+/* Must call this after the directory is sorted */
+
+void
+FontFileSwitchStringsToBitmapPointers (FontDirectoryPtr dir)
+{
+ int s;
+ int b;
+ int i;
+ FontEntryPtr scalable;
+ FontEntryPtr nonScalable;
+ FontScaledPtr scaled;
+ FontScalableExtraPtr extra;
+
+ scalable = dir->scalable.entries;
+ nonScalable = dir->nonScalable.entries;
+ for (s = 0; s < dir->scalable.used; s++)
+ {
+ extra = scalable[s].u.scalable.extra;
+ scaled = extra->scaled;
+ for (i = 0; i < extra->numScaled; i++)
+ for (b = 0; b < dir->nonScalable.used; b++)
+ if (nonScalable[b].name.name == (char *) scaled[i].bitmap)
+ scaled[i].bitmap = &nonScalable[b];
+ }
+}
+
+void
+FontFileRemoveScaledInstance (FontEntryPtr entry, FontPtr pFont)
+{
+ FontScalableEntryPtr scalable;
+ FontScalableExtraPtr extra;
+ int i;
+
+ scalable = &entry->u.scalable;
+ extra = scalable->extra;
+ for (i = 0; i < extra->numScaled; i++)
+ {
+ if (extra->scaled[i].pFont == pFont)
+ {
+ if (extra->scaled[i].vals.ranges)
+ free (extra->scaled[i].vals.ranges);
+ extra->numScaled--;
+ for (; i < extra->numScaled; i++)
+ extra->scaled[i] = extra->scaled[i+1];
+ }
+ }
+}
+
+Bool
+FontFileCompleteXLFD (FontScalablePtr vals, FontScalablePtr def)
+{
+ FontResolutionPtr res;
+ int num_res;
+ double sx, sy, temp_matrix[4];
+ double pixel_setsize_adjustment = 1.0;
+ /*
+ * If two of the three vertical scale values are specified, compute the
+ * third. If all three are specified, make sure they are consistent
+ * (within a pixel)
+ *
+ * One purpose of this procedure is to complete XLFD names in a
+ * repeatable manner. That is, if the user partially specifies
+ * a name (say, pixelsize but not pointsize), the results generated
+ * here result in a fully specified name that will result in the
+ * same font.
+ */
+
+ res = GetClientResolutions(&num_res);
+
+ if (!(vals->values_supplied & PIXELSIZE_MASK) ||
+ !(vals->values_supplied & POINTSIZE_MASK))
+ {
+ /* If resolution(s) unspecified and cannot be computed from
+ pixelsize and pointsize, get appropriate defaults. */
+
+ if (num_res)
+ {
+ if (vals->x <= 0)
+ vals->x = res->x_resolution;
+ if (vals->y <= 0)
+ vals->y = res->y_resolution;
+ }
+
+ if (vals->x <= 0)
+ vals->x = def->x;
+ if (vals->y <= 0)
+ vals->y = def->y;
+ }
+ else
+ {
+ /* If needed, compute resolution values from the pixel and
+ pointsize information we were given. This problem is
+ overdetermined (four equations, two unknowns), but we don't
+ check for inconsistencies here. If they exist, they will
+ show up in later tests for the point and pixel sizes. */
+
+ if (vals->y <= 0)
+ {
+ double x = hypot(vals->pixel_matrix[1], vals->pixel_matrix[3]);
+ double y = hypot(vals->point_matrix[1], vals->point_matrix[3]);
+ if (y < EPS) return FALSE;
+ vals->y = (int)(x * 72.27 / y + .5);
+ }
+ if (vals->x <= 0)
+ {
+ /* If the pixelsize was given as an array, or as a scalar that
+ has been normalized for the pixel shape, we have enough
+ information to compute a separate horizontal resolution */
+
+ if ((vals->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY ||
+ (vals->values_supplied & PIXELSIZE_MASK) ==
+ PIXELSIZE_SCALAR_NORMALIZED)
+ {
+ double x = hypot(vals->pixel_matrix[0], vals->pixel_matrix[2]);
+ double y = hypot(vals->point_matrix[0], vals->point_matrix[2]);
+ if (y < EPS) return FALSE;
+ vals->x = (int)(x * 72.27 / y + .5);
+ }
+ else
+ {
+ /* Not enough information in the pixelsize array. Just
+ assume the pixels are square. */
+ vals->x = vals->y;
+ }
+ }
+ }
+
+ if (vals->x <= 0 || vals->y <= 0) return FALSE;
+
+ /* If neither pixelsize nor pointsize is defined, take the pointsize
+ from the defaults structure we've been passed. */
+ if (!(vals->values_supplied & PIXELSIZE_MASK) &&
+ !(vals->values_supplied & POINTSIZE_MASK))
+ {
+ if (num_res)
+ {
+ vals->point_matrix[0] =
+ vals->point_matrix[3] = (double)res->point_size / 10.0;
+ vals->point_matrix[1] =
+ vals->point_matrix[2] = 0;
+ vals->values_supplied = (vals->values_supplied & ~POINTSIZE_MASK) |
+ POINTSIZE_SCALAR;
+ }
+ else if (def->values_supplied & POINTSIZE_MASK)
+ {
+ vals->point_matrix[0] = def->point_matrix[0];
+ vals->point_matrix[1] = def->point_matrix[1];
+ vals->point_matrix[2] = def->point_matrix[2];
+ vals->point_matrix[3] = def->point_matrix[3];
+ vals->values_supplied = (vals->values_supplied & ~POINTSIZE_MASK) |
+ (def->values_supplied & POINTSIZE_MASK);
+ }
+ else return FALSE;
+ }
+
+ /* At this point, at least two of the three vertical scale values
+ should be specified. Our job now is to compute the missing ones
+ and check for agreement between overspecified values */
+
+ /* If pixelsize was specified by a scalar, we need to fix the matrix
+ now that we know the resolutions. */
+ if ((vals->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_SCALAR)
+ {
+ /* pixel_setsize_adjustment used below to modify permissible
+ error in pixel/pointsize matching, since multiplying a
+ number rounded to integer changes the amount of the error
+ caused by the rounding */
+
+ pixel_setsize_adjustment = (double)vals->x / (double)vals->y;
+ vals->pixel_matrix[0] *= pixel_setsize_adjustment;
+ vals->values_supplied = (vals->values_supplied & ~PIXELSIZE_MASK) |
+ PIXELSIZE_SCALAR_NORMALIZED;
+ }
+
+ sx = (double)vals->x / 72.27;
+ sy = (double)vals->y / 72.27;
+
+ /* If a pointsize was specified, make sure pixelsize is consistent
+ to within 1 pixel, then replace pixelsize with a consistent
+ floating-point value. */
+
+ if (vals->values_supplied & POINTSIZE_MASK)
+ {
+ recompute_pixelsize: ;
+ temp_matrix[0] = vals->point_matrix[0] * sx;
+ temp_matrix[1] = vals->point_matrix[1] * sy;
+ temp_matrix[2] = vals->point_matrix[2] * sx;
+ temp_matrix[3] = vals->point_matrix[3] * sy;
+ if (vals->values_supplied & PIXELSIZE_MASK)
+ {
+ if (fabs(vals->pixel_matrix[0] - temp_matrix[0]) >
+ pixel_setsize_adjustment ||
+ fabs(vals->pixel_matrix[1] - temp_matrix[1]) > 1 ||
+ fabs(vals->pixel_matrix[2] - temp_matrix[2]) > 1 ||
+ fabs(vals->pixel_matrix[3] - temp_matrix[3]) > 1)
+ return FALSE;
+ }
+ if ((vals->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY &&
+ (vals->values_supplied & POINTSIZE_MASK) == POINTSIZE_SCALAR)
+ {
+ /* In the special case that pixelsize came as an array and
+ pointsize as a scalar, recompute the pointsize matrix
+ from the pixelsize matrix. */
+ goto recompute_pointsize;
+ }
+
+ /* Refresh pixel matrix with precise values computed from
+ pointsize and resolution. */
+ vals->pixel_matrix[0] = temp_matrix[0];
+ vals->pixel_matrix[1] = temp_matrix[1];
+ vals->pixel_matrix[2] = temp_matrix[2];
+ vals->pixel_matrix[3] = temp_matrix[3];
+
+ /* Set values_supplied for pixel to match that for point */
+ vals->values_supplied =
+ (vals->values_supplied & ~PIXELSIZE_MASK) |
+ (((vals->values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY) ?
+ PIXELSIZE_ARRAY : PIXELSIZE_SCALAR_NORMALIZED);
+ }
+ else
+ {
+ /* Pointsize unspecified... compute from pixel size and
+ resolutions */
+ recompute_pointsize: ;
+ if (fabs(sx) < EPS || fabs(sy) < EPS) return FALSE;
+ vals->point_matrix[0] = vals->pixel_matrix[0] / sx;
+ vals->point_matrix[1] = vals->pixel_matrix[1] / sy;
+ vals->point_matrix[2] = vals->pixel_matrix[2] / sx;
+ vals->point_matrix[3] = vals->pixel_matrix[3] / sy;
+
+ /* Set values_supplied for pixel to match that for point */
+ vals->values_supplied =
+ (vals->values_supplied & ~POINTSIZE_MASK) |
+ (((vals->values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY) ?
+ POINTSIZE_ARRAY : POINTSIZE_SCALAR);
+
+ /* If we computed scalar pointsize from scalar pixelsize, round
+ pointsize to decipoints and recompute pixelsize so we end up
+ with a repeatable name */
+ if ((vals->values_supplied & POINTSIZE_MASK) == POINTSIZE_SCALAR)
+ {
+ /* Off-diagonal elements should be zero since no matrix was
+ specified. */
+ vals->point_matrix[0] =
+ (double)(int)(vals->point_matrix[0] * 10.0 + .5) / 10.0;
+ vals->point_matrix[3] =
+ (double)(int)(vals->point_matrix[3] * 10.0 + .5) / 10.0;
+ goto recompute_pixelsize;
+ }
+ }
+
+ /* We've succeeded. Round everything to a few decimal places
+ for repeatability. */
+
+ vals->pixel_matrix[0] = xlfd_round_double(vals->pixel_matrix[0]);
+ vals->pixel_matrix[1] = xlfd_round_double(vals->pixel_matrix[1]);
+ vals->pixel_matrix[2] = xlfd_round_double(vals->pixel_matrix[2]);
+ vals->pixel_matrix[3] = xlfd_round_double(vals->pixel_matrix[3]);
+ vals->point_matrix[0] = xlfd_round_double(vals->point_matrix[0]);
+ vals->point_matrix[1] = xlfd_round_double(vals->point_matrix[1]);
+ vals->point_matrix[2] = xlfd_round_double(vals->point_matrix[2]);
+ vals->point_matrix[3] = xlfd_round_double(vals->point_matrix[3]);
+
+ /* Fill in the deprecated fields for the benefit of rasterizers
+ that do not handle the matrices. */
+ vals->point = vals->point_matrix[3] * 10;
+ vals->pixel = vals->pixel_matrix[3];
+
+ return TRUE;
+}
+
+static Bool
+MatchScalable (FontScalablePtr a, FontScalablePtr b)
+{
+ int i;
+
+ /* Some asymmetry here: we assume that the first argument (a) is
+ the table entry and the second (b) the item we're trying to match
+ (the key). We'll consider the fonts matched if the relevant
+ metrics match *and* if a) the table entry doesn't have charset
+ subsetting or b) the table entry has identical charset subsetting
+ to that in the key. We could add logic to check if the table
+ entry has a superset of the charset required by the key, but
+ we'll resist the urge for now. */
+
+#define EQUAL(a,b) ((a)[0] == (b)[0] && \
+ (a)[1] == (b)[1] && \
+ (a)[2] == (b)[2] && \
+ (a)[3] == (b)[3])
+
+ if (!(a->x == b->x &&
+ a->y == b->y &&
+ (a->width == b->width || a->width == 0 || b->width == 0 || b->width == -1) &&
+ (!(b->values_supplied & PIXELSIZE_MASK) ||
+ ((a->values_supplied & PIXELSIZE_MASK) ==
+ (b->values_supplied & PIXELSIZE_MASK) &&
+ EQUAL(a->pixel_matrix, b->pixel_matrix))) &&
+ (!(b->values_supplied & POINTSIZE_MASK) ||
+ ((a->values_supplied & POINTSIZE_MASK) ==
+ (b->values_supplied & POINTSIZE_MASK) &&
+ EQUAL(a->point_matrix, b->point_matrix))) &&
+ (a->nranges == 0 || a->nranges == b->nranges)))
+ return FALSE;
+
+ for (i = 0; i < a->nranges; i++)
+ if (a->ranges[i].min_char_low != b->ranges[i].min_char_low ||
+ a->ranges[i].min_char_high != b->ranges[i].min_char_high ||
+ a->ranges[i].max_char_low != b->ranges[i].max_char_low ||
+ a->ranges[i].max_char_high != b->ranges[i].max_char_high)
+ return FALSE;
+
+ return TRUE;
+}
+
+FontScaledPtr
+FontFileFindScaledInstance (FontEntryPtr entry, FontScalablePtr vals,
+ int noSpecificSize)
+{
+ FontScalableEntryPtr scalable;
+ FontScalableExtraPtr extra;
+ FontScalablePtr mvals;
+ int dist, i;
+ int mini;
+ double mindist;
+ register double temp, sum=0.0;
+
+#define NORMDIFF(a, b) ( \
+ temp = (a)[0] - (b)[0], \
+ sum = temp * temp, \
+ temp = (a)[1] - (b)[1], \
+ sum += temp * temp, \
+ temp = (a)[2] - (b)[2], \
+ sum += temp * temp, \
+ temp = (a)[3] - (b)[3], \
+ sum + temp * temp )
+
+ scalable = &entry->u.scalable;
+ extra = scalable->extra;
+ if (noSpecificSize && extra->numScaled)
+ {
+ mini = 0;
+ mindist = NORMDIFF(extra->scaled[0].vals.point_matrix,
+ vals->point_matrix);
+ for (i = 1; i < extra->numScaled; i++)
+ {
+ if (extra->scaled[i].pFont &&
+ !extra->scaled[i].pFont->info.cachable) continue;
+ mvals = &extra->scaled[i].vals;
+ dist = NORMDIFF(mvals->point_matrix, vals->point_matrix);
+ if (dist < mindist)
+ {
+ mindist = dist;
+ mini = i;
+ }
+ }
+ if (extra->scaled[mini].pFont &&
+ !extra->scaled[mini].pFont->info.cachable) return 0;
+ return &extra->scaled[mini];
+ }
+ else
+ {
+ /* See if we've scaled to this value yet */
+ for (i = 0; i < extra->numScaled; i++)
+ {
+ if (extra->scaled[i].pFont &&
+ !extra->scaled[i].pFont->info.cachable) continue;
+ if (MatchScalable (&extra->scaled[i].vals, vals))
+ return &extra->scaled[i];
+ }
+ }
+ return 0;
+}
diff --git a/libXfont/src/fontfile/gunzip.c b/libXfont/src/fontfile/gunzip.c index 9fa3eed00..52b0a10be 100644 --- a/libXfont/src/fontfile/gunzip.c +++ b/libXfont/src/fontfile/gunzip.c @@ -1,225 +1,225 @@ -/* lib/font/fontfile/gunzip.c - written by Mark Eichin <eichin@kitten.gen.ma.us> September 1996. - intended for inclusion in X11 public releases. */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fontmisc.h> -#include <X11/fonts/bufio.h> -#include <zlib.h> - -typedef struct _xzip_buf { - z_stream z; - int zstat; - BufChar b[BUFFILESIZE]; - BufChar b_in[BUFFILESIZE]; - BufFilePtr f; -} xzip_buf; - -static int BufZipFileClose ( BufFilePtr f, int flag ); -static int BufZipFileFill ( BufFilePtr f ); -static int BufZipFileSkip ( BufFilePtr f, int c ); -static int BufCheckZipHeader ( BufFilePtr f ); - -BufFilePtr -BufFilePushZIP (BufFilePtr f) -{ - xzip_buf *x; - - x = malloc (sizeof (xzip_buf)); - if (!x) return 0; - /* these are just for raw calloc/free */ - x->z.zalloc = Z_NULL; - x->z.zfree = Z_NULL; - x->z.opaque = Z_NULL; - x->f = f; - - /* force inflateInit to allocate it's own history buffer */ - x->z.next_in = Z_NULL; - x->z.next_out = Z_NULL; - x->z.avail_in = x->z.avail_out = 0; - - /* using negative windowBits sets "nowrap" mode, which turns off - zlib header checking [undocumented, for gzip compatibility only?] */ - x->zstat = inflateInit2(&(x->z), -MAX_WBITS); - if (x->zstat != Z_OK) { - free(x); - return 0; - } - - /* now that the history buffer is allocated, we provide the data buffer */ - x->z.next_out = x->b; - x->z.avail_out = BUFFILESIZE; - x->z.next_out = x->b_in; - x->z.avail_in = 0; - - if (BufCheckZipHeader(x->f)) { - free(x); - return 0; - } - - return BufFileCreate((char *)x, - BufZipFileFill, - 0, - BufZipFileSkip, - BufZipFileClose); -} - -static int -BufZipFileClose(BufFilePtr f, int flag) -{ - xzip_buf *x = (xzip_buf *)f->private; - inflateEnd (&(x->z)); - BufFileClose (x->f, flag); - free (x); - return 1; -} - -/* here's the real work. - -- we need to put stuff in f.buffer, update f.left and f.bufp, - then return the first byte (or BUFFILEEOF). - -- to do this, we need to get stuff into avail_in, and next_in, - and call inflate appropriately. - -- we may also need to add CRC maintenance - if inflate tells us - Z_STREAM_END, we then have 4bytes CRC and 4bytes length... - gzio.c:gzread shows most of the mechanism. - */ -static int -BufZipFileFill (BufFilePtr f) -{ - xzip_buf *x = (xzip_buf *)f->private; - - /* we only get called when left == 0... */ - /* but just in case, deal */ - if (f->left >= 0) { - f->left--; - return *(f->bufp++); - } - /* did we run out last time? */ - switch (x->zstat) { - case Z_OK: - break; - case Z_STREAM_END: - case Z_DATA_ERROR: - case Z_ERRNO: - f->left = 0; - return BUFFILEEOF; - default: - return BUFFILEEOF; - } - /* now we work to consume what we can */ - /* let zlib know what we can handle */ - x->z.next_out = x->b; - x->z.avail_out = BUFFILESIZE; - - /* and try to consume all of it */ - while (x->z.avail_out > 0) { - /* if we don't have anything to work from... */ - if (x->z.avail_in == 0) { - /* ... fill the z buf from underlying file */ - int i, c; - for (i = 0; i < sizeof(x->b_in); i++) { - c = BufFileGet(x->f); - if (c == BUFFILEEOF) break; - x->b_in[i] = c; - } - x->z.avail_in += i; - x->z.next_in = x->b_in; - } - /* so now we have some output space and some input data */ - x->zstat = inflate(&(x->z), Z_NO_FLUSH); - /* the inflation output happens in the f buffer directly... */ - if (x->zstat == Z_STREAM_END) { - /* deal with EOF, crc */ - break; - } - if (x->zstat != Z_OK) { - break; - } - } - f->bufp = x->b; - f->left = BUFFILESIZE - x->z.avail_out; - - if (f->left >= 0) { - f->left--; - return *(f->bufp++); - } else { - return BUFFILEEOF; - } -} - -/* there should be a BufCommonSkip... */ -static int -BufZipFileSkip (BufFilePtr f, int c) -{ - /* BufFileRawSkip returns the count unchanged. - BufCompressedSkip returns 0. - That means it probably never gets called... */ - int retval = c; - while(c--) { - int get = BufFileGet(f); - if (get == BUFFILEEOF) return get; - } - return retval; -} - -/* now we need to duplicate check_header */ -/* contents: - 0x1f, 0x8b -- magic number - 1 byte -- method (Z_DEFLATED) - 1 byte -- flags (mask with RESERVED -> fail) - 4 byte -- time (discard) - 1 byte -- xflags (discard) - 1 byte -- "os" code (discard) - [if flags & EXTRA_FIELD: - 2 bytes -- LSBfirst length n - n bytes -- extra data (discard)] - [if flags & ORIG_NAME: - n bytes -- null terminated name (discard)] - [if flags & COMMENT: - n bytes -- null terminated comment (discard)] - [if flags & HEAD_CRC: - 2 bytes -- crc of headers? (discard)] - */ - -/* gzip flag byte -- from gzio.c */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ -#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define RESERVED 0xE0 /* bits 5..7: reserved */ - -#define GET(f) do {c = BufFileGet(f); if (c == BUFFILEEOF) return c;} while(0) -static int -BufCheckZipHeader(BufFilePtr f) -{ - int c, flags; - GET(f); if (c != 0x1f) return 1; /* magic 1 */ - GET(f); if (c != 0x8b) return 2; /* magic 2 */ - GET(f); if (c != Z_DEFLATED) return 3; /* method */ - GET(f); if (c & RESERVED) return 4; /* reserved flags */ - flags = c; - GET(f); GET(f); GET(f); GET(f); /* time */ - GET(f); /* xflags */ - GET(f); /* os code */ - if (flags & EXTRA_FIELD) { - int len; - GET(f); len = c; - GET(f); len += (c<<8); - while (len-- >= 0) { - GET(f); - } - } - if (flags & ORIG_NAME) { - do { GET(f); } while (c != 0); - } - if (flags & COMMENT) { - do { GET(f); } while (c != 0); - } - if (flags & HEAD_CRC) { - GET(f); GET(f); /* header crc */ - } - return 0; -} +/* lib/font/fontfile/gunzip.c
+ written by Mark Eichin <eichin@kitten.gen.ma.us> September 1996.
+ intended for inclusion in X11 public releases. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fontmisc.h>
+#include <X11/fonts/bufio.h>
+#include <zlib.h>
+
+typedef struct _xzip_buf {
+ z_stream z;
+ int zstat;
+ BufChar b[BUFFILESIZE];
+ BufChar b_in[BUFFILESIZE];
+ BufFilePtr f;
+} xzip_buf;
+
+static int BufZipFileClose ( BufFilePtr f, int flag );
+static int BufZipFileFill ( BufFilePtr f );
+static int BufZipFileSkip ( BufFilePtr f, int c );
+static int BufCheckZipHeader ( BufFilePtr f );
+
+BufFilePtr
+BufFilePushZIP (BufFilePtr f)
+{
+ xzip_buf *x;
+
+ x = malloc (sizeof (xzip_buf));
+ if (!x) return 0;
+ /* these are just for raw calloc/free */
+ x->z.zalloc = Z_NULL;
+ x->z.zfree = Z_NULL;
+ x->z.opaque = Z_NULL;
+ x->f = f;
+
+ /* force inflateInit to allocate it's own history buffer */
+ x->z.next_in = Z_NULL;
+ x->z.next_out = Z_NULL;
+ x->z.avail_in = x->z.avail_out = 0;
+
+ /* using negative windowBits sets "nowrap" mode, which turns off
+ zlib header checking [undocumented, for gzip compatibility only?] */
+ x->zstat = inflateInit2(&(x->z), -MAX_WBITS);
+ if (x->zstat != Z_OK) {
+ free(x);
+ return 0;
+ }
+
+ /* now that the history buffer is allocated, we provide the data buffer */
+ x->z.next_out = x->b;
+ x->z.avail_out = BUFFILESIZE;
+ x->z.next_out = x->b_in;
+ x->z.avail_in = 0;
+
+ if (BufCheckZipHeader(x->f)) {
+ free(x);
+ return 0;
+ }
+
+ return BufFileCreate((char *)x,
+ BufZipFileFill,
+ 0,
+ BufZipFileSkip,
+ BufZipFileClose);
+}
+
+static int
+BufZipFileClose(BufFilePtr f, int flag)
+{
+ xzip_buf *x = (xzip_buf *)f->private;
+ inflateEnd (&(x->z));
+ BufFileClose (x->f, flag);
+ free (x);
+ return 1;
+}
+
+/* here's the real work.
+ -- we need to put stuff in f.buffer, update f.left and f.bufp,
+ then return the first byte (or BUFFILEEOF).
+ -- to do this, we need to get stuff into avail_in, and next_in,
+ and call inflate appropriately.
+ -- we may also need to add CRC maintenance - if inflate tells us
+ Z_STREAM_END, we then have 4bytes CRC and 4bytes length...
+ gzio.c:gzread shows most of the mechanism.
+ */
+static int
+BufZipFileFill (BufFilePtr f)
+{
+ xzip_buf *x = (xzip_buf *)f->private;
+
+ /* we only get called when left == 0... */
+ /* but just in case, deal */
+ if (f->left >= 0) {
+ f->left--;
+ return *(f->bufp++);
+ }
+ /* did we run out last time? */
+ switch (x->zstat) {
+ case Z_OK:
+ break;
+ case Z_STREAM_END:
+ case Z_DATA_ERROR:
+ case Z_ERRNO:
+ f->left = 0;
+ return BUFFILEEOF;
+ default:
+ return BUFFILEEOF;
+ }
+ /* now we work to consume what we can */
+ /* let zlib know what we can handle */
+ x->z.next_out = x->b;
+ x->z.avail_out = BUFFILESIZE;
+
+ /* and try to consume all of it */
+ while (x->z.avail_out > 0) {
+ /* if we don't have anything to work from... */
+ if (x->z.avail_in == 0) {
+ /* ... fill the z buf from underlying file */
+ int i, c;
+ for (i = 0; i < sizeof(x->b_in); i++) {
+ c = BufFileGet(x->f);
+ if (c == BUFFILEEOF) break;
+ x->b_in[i] = c;
+ }
+ x->z.avail_in += i;
+ x->z.next_in = x->b_in;
+ }
+ /* so now we have some output space and some input data */
+ x->zstat = inflate(&(x->z), Z_NO_FLUSH);
+ /* the inflation output happens in the f buffer directly... */
+ if (x->zstat == Z_STREAM_END) {
+ /* deal with EOF, crc */
+ break;
+ }
+ if (x->zstat != Z_OK) {
+ break;
+ }
+ }
+ f->bufp = x->b;
+ f->left = BUFFILESIZE - x->z.avail_out;
+
+ if (f->left >= 0) {
+ f->left--;
+ return *(f->bufp++);
+ } else {
+ return BUFFILEEOF;
+ }
+}
+
+/* there should be a BufCommonSkip... */
+static int
+BufZipFileSkip (BufFilePtr f, int c)
+{
+ /* BufFileRawSkip returns the count unchanged.
+ BufCompressedSkip returns 0.
+ That means it probably never gets called... */
+ int retval = c;
+ while(c--) {
+ int get = BufFileGet(f);
+ if (get == BUFFILEEOF) return get;
+ }
+ return retval;
+}
+
+/* now we need to duplicate check_header */
+/* contents:
+ 0x1f, 0x8b -- magic number
+ 1 byte -- method (Z_DEFLATED)
+ 1 byte -- flags (mask with RESERVED -> fail)
+ 4 byte -- time (discard)
+ 1 byte -- xflags (discard)
+ 1 byte -- "os" code (discard)
+ [if flags & EXTRA_FIELD:
+ 2 bytes -- LSBfirst length n
+ n bytes -- extra data (discard)]
+ [if flags & ORIG_NAME:
+ n bytes -- null terminated name (discard)]
+ [if flags & COMMENT:
+ n bytes -- null terminated comment (discard)]
+ [if flags & HEAD_CRC:
+ 2 bytes -- crc of headers? (discard)]
+ */
+
+/* gzip flag byte -- from gzio.c */
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define RESERVED 0xE0 /* bits 5..7: reserved */
+
+#define GET(f) do {c = BufFileGet(f); if (c == BUFFILEEOF) return c;} while(0)
+static int
+BufCheckZipHeader(BufFilePtr f)
+{
+ int c, flags;
+ GET(f); if (c != 0x1f) return 1; /* magic 1 */
+ GET(f); if (c != 0x8b) return 2; /* magic 2 */
+ GET(f); if (c != Z_DEFLATED) return 3; /* method */
+ GET(f); if (c & RESERVED) return 4; /* reserved flags */
+ flags = c;
+ GET(f); GET(f); GET(f); GET(f); /* time */
+ GET(f); /* xflags */
+ GET(f); /* os code */
+ if (flags & EXTRA_FIELD) {
+ int len;
+ GET(f); len = c;
+ GET(f); len += (c<<8);
+ while (len-- >= 0) {
+ GET(f);
+ }
+ }
+ if (flags & ORIG_NAME) {
+ do { GET(f); } while (c != 0);
+ }
+ if (flags & COMMENT) {
+ do { GET(f); } while (c != 0);
+ }
+ if (flags & HEAD_CRC) {
+ GET(f); GET(f); /* header crc */
+ }
+ return 0;
+}
diff --git a/libXfont/src/fontfile/makefile b/libXfont/src/fontfile/makefile new file mode 100644 index 000000000..6468ff9b5 --- /dev/null +++ b/libXfont/src/fontfile/makefile @@ -0,0 +1,26 @@ + +LIBRARY = libfontfile + +INCLUDES += $(MHMAKECONF)\zlib\src\zlib-1.2.3 + +DEFINES += X_GZIP_FONT_COMPRESSION + +CSRCS = bitsource.c \ + bufio.c \ + decompress.c \ + defaults.c \ + dirfile.c \ + fileio.c \ + filewr.c \ + fontdir.c \ + fontencc.c \ + fontfile.c \ + fontscale.c \ + gunzip.c \ + register.c \ + renderers.c \ + catalogue.c + +INCLUDES := ../.. $(INCLUDES) + + diff --git a/libXfont/src/fontfile/renderers.c b/libXfont/src/fontfile/renderers.c index a9e4bef53..8adb05e1c 100644 --- a/libXfont/src/fontfile/renderers.c +++ b/libXfont/src/fontfile/renderers.c @@ -1,114 +1,115 @@ -/* - -Copyright 1991, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fntfilst.h> -extern void ErrorF(const char *f, ...); - -static FontRenderersRec renderers; - -/* - * XXX Maybe should allow unregistering renders. For now, just clear the - * list at each new generation. - */ -extern unsigned long serverGeneration; -static unsigned long rendererGeneration = 0; - -Bool -FontFileRegisterRenderer (FontRendererPtr renderer) -{ - return FontFilePriorityRegisterRenderer(renderer, 0); -} - -Bool -FontFilePriorityRegisterRenderer (FontRendererPtr renderer, int priority) -{ - int i; - struct _FontRenderersElement *new; - - if (rendererGeneration != serverGeneration) { - rendererGeneration = serverGeneration; - renderers.number = 0; - if (renderers.renderers) - free(renderers.renderers); - renderers.renderers = NULL; - } - - for (i = 0; i < renderers.number; i++) { - if (!strcasecmp (renderers.renderers[i].renderer->fileSuffix, - renderer->fileSuffix)) { - if(renderers.renderers[i].priority >= priority) { - if(renderers.renderers[i].priority == priority) { - if (rendererGeneration == 1) - ErrorF("Warning: font renderer for \"%s\" " - "already registered at priority %d\n", - renderer->fileSuffix, priority); - } - return TRUE; - } else { - break; - } - } - } - - if(i >= renderers.number) { - new = realloc (renderers.renderers, sizeof(*new) * (i + 1)); - if (!new) - return FALSE; - renderers.renderers = new; - renderers.number = i + 1; - } - renderer->number = i; - renderers.renderers[i].renderer = renderer; - renderers.renderers[i].priority = priority; - return TRUE; -} - -FontRendererPtr -FontFileMatchRenderer (char *fileName) -{ - int i; - int fileLen; - FontRendererPtr r; - - fileLen = strlen (fileName); - for (i = 0; i < renderers.number; i++) - { - r = renderers.renderers[i].renderer; - if (fileLen >= r->fileSuffixLen && - !strcasecmp (fileName + fileLen - r->fileSuffixLen, r->fileSuffix)) - { - return r; - } - } - return 0; -} +/*
+
+Copyright 1991, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fntfilst.h>
+#include <unistd.h>
+extern void ErrorF(const char *f, ...);
+
+static FontRenderersRec renderers;
+
+/*
+ * XXX Maybe should allow unregistering renders. For now, just clear the
+ * list at each new generation.
+ */
+extern unsigned long serverGeneration;
+static unsigned long rendererGeneration = 0;
+
+Bool
+FontFileRegisterRenderer (FontRendererPtr renderer)
+{
+ return FontFilePriorityRegisterRenderer(renderer, 0);
+}
+
+Bool
+FontFilePriorityRegisterRenderer (FontRendererPtr renderer, int priority)
+{
+ int i;
+ struct _FontRenderersElement *new;
+
+ if (rendererGeneration != serverGeneration) {
+ rendererGeneration = serverGeneration;
+ renderers.number = 0;
+ if (renderers.renderers)
+ free(renderers.renderers);
+ renderers.renderers = NULL;
+ }
+
+ for (i = 0; i < renderers.number; i++) {
+ if (!strcasecmp (renderers.renderers[i].renderer->fileSuffix,
+ renderer->fileSuffix)) {
+ if(renderers.renderers[i].priority >= priority) {
+ if(renderers.renderers[i].priority == priority) {
+ if (rendererGeneration == 1)
+ ErrorF("Warning: font renderer for \"%s\" "
+ "already registered at priority %d\n",
+ renderer->fileSuffix, priority);
+ }
+ return TRUE;
+ } else {
+ break;
+ }
+ }
+ }
+
+ if(i >= renderers.number) {
+ new = realloc (renderers.renderers, sizeof(*new) * (i + 1));
+ if (!new)
+ return FALSE;
+ renderers.renderers = new;
+ renderers.number = i + 1;
+ }
+ renderer->number = i;
+ renderers.renderers[i].renderer = renderer;
+ renderers.renderers[i].priority = priority;
+ return TRUE;
+}
+
+FontRendererPtr
+FontFileMatchRenderer (char *fileName)
+{
+ int i;
+ int fileLen;
+ FontRendererPtr r;
+
+ fileLen = strlen (fileName);
+ for (i = 0; i < renderers.number; i++)
+ {
+ r = renderers.renderers[i].renderer;
+ if (fileLen >= r->fileSuffixLen &&
+ !strcasecmp (fileName + fileLen - r->fileSuffixLen, r->fileSuffix))
+ {
+ return r;
+ }
+ }
+ return 0;
+}
diff --git a/libXfont/src/stubs/makefile b/libXfont/src/stubs/makefile new file mode 100644 index 000000000..e028dd5db --- /dev/null +++ b/libXfont/src/stubs/makefile @@ -0,0 +1,26 @@ +LIBRARY = libstubs + +CSRCS = \ + cauthgen.c \ + csignal.c \ + delfntcid.c \ + errorf.c \ + fatalerror.c \ + findoldfnt.c \ + getcres.c \ + getdefptsize.c \ + getnewfntcid.c \ + gettime.c \ + initfshdl.c \ + regfpefunc.c \ + rmfshdl.c \ + servclient.c \ + setfntauth.c \ + stfntcfnt.c \ + stubs.h + +CSRCS:=$(filter-out %.h,$(CSRCS)) + +INCLUDES := ../.. $(INCLUDES) + + diff --git a/libXfont/src/stubs/stubs.h b/libXfont/src/stubs/stubs.h index 7f0eef298..ce3aeb158 100644 --- a/libXfont/src/stubs/stubs.h +++ b/libXfont/src/stubs/stubs.h @@ -1,41 +1,41 @@ -#include <stdio.h> -#include <X11/fonts/fntfilst.h> -#include <X11/fonts/font.h> - -#ifndef True -#define True (-1) -#endif -#ifndef False -#define False (0) -#endif - -/* this probably works for Mach-O too, but probably not for PE */ -#if (defined(__APPLE__) || defined(__ELF__)) && defined(__GNUC__) && (__GNUC__ >= 3) -#define weak __attribute__((weak)) -#else -#define weak -#ifndef __SUNPRO_C /* Sun compilers use #pragma weak in .c files instead */ -#define NO_WEAK_SYMBOLS -#endif -#endif - -/* This is really just a hack for now... __APPLE__ really should be using - * the weak symbols route above, but it's causing an as-yet unresolved issue, - * so we're instead building with flat_namespace. - */ -#ifdef __APPLE__ -#undef weak -#define weak -#endif - -extern FontPtr find_old_font ( FSID id ); -extern int set_font_authorizations ( char **authorizations, - int *authlen, - ClientPtr client ); - -extern unsigned long GetTimeInMillis (void); - -extern void ErrorF(const char *format, ...); -extern void FatalError(const char *format, ...); - -/* end of file */ +#include <stdio.h>
+#include <X11/fonts/fntfilst.h>
+#include <X11/fonts/font.h>
+
+#ifndef True
+#define True (-1)
+#endif
+#ifndef False
+#define False (0)
+#endif
+
+/* this probably works for Mach-O too, but probably not for PE */
+#if (defined(__APPLE__) || defined(__ELF__)) && defined(__GNUC__) && (__GNUC__ >= 3)
+#define weak __attribute__((weak))
+#else
+#define weak
+#ifndef __SUNPRO_C /* Sun compilers use #pragma weak in .c files instead */
+#define NO_WEAK_SYMBOLS
+#endif
+#endif
+
+/* This is really just a hack for now... __APPLE__ really should be using
+ * the weak symbols route above, but it's causing an as-yet unresolved issue,
+ * so we're instead building with flat_namespace.
+ */
+#ifdef __APPLE__
+#undef weak
+#define weak
+#endif
+
+extern FontPtr find_old_font ( FSID id );
+extern int set_font_authorizations ( char **authorizations,
+ int *authlen,
+ ClientPtr client );
+
+extern unsigned long GetTimeInMillis (void);
+
+extern void ErrorF(const char *format, ...);
+extern void FatalError(const char *format, ...);
+
+/* end of file */
diff --git a/libXfont/src/util/atom.c b/libXfont/src/util/atom.c index f15e3d8de..d2d628ece 100644 --- a/libXfont/src/util/atom.c +++ b/libXfont/src/util/atom.c @@ -1,242 +1,242 @@ -/* - -Copyright 1990, 1994, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -/* lame atom replacement routines for font applications */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fontmisc.h> -#include "stubs.h" - -typedef struct _AtomList { - char *name; - int len; - int hash; - Atom atom; -} AtomListRec, *AtomListPtr; - -static AtomListPtr *hashTable; - -static int hashSize, hashUsed; -static int hashMask; -static int rehash; - -static AtomListPtr *reverseMap; -static int reverseMapSize; -static Atom lastAtom; - -static int -Hash(char *string, int len) -{ - int h; - - h = 0; - while (len--) - h = (h << 3) ^ *string++; - if (h < 0) - return -h; - return h; -} - -static int -ResizeHashTable (void) -{ - int newHashSize; - int newHashMask; - AtomListPtr *newHashTable; - int i; - int h; - int newRehash; - int r; - - if (hashSize == 0) - newHashSize = 1024; - else - newHashSize = hashSize * 2; - newHashTable = calloc (newHashSize, sizeof (AtomListPtr)); - if (!newHashTable) { - fprintf(stderr, "ResizeHashTable(): Error: Couldn't allocate" - " newHashTable (%ld)\n", - newHashSize * (unsigned long)sizeof (AtomListPtr)); - return FALSE; - } - newHashMask = newHashSize - 1; - newRehash = (newHashMask - 2); - for (i = 0; i < hashSize; i++) - { - if (hashTable[i]) - { - h = (hashTable[i]->hash) & newHashMask; - if (newHashTable[h]) - { - r = hashTable[i]->hash % newRehash | 1; - do { - h += r; - if (h >= newHashSize) - h -= newHashSize; - } while (newHashTable[h]); - } - newHashTable[h] = hashTable[i]; - } - } - free (hashTable); - hashTable = newHashTable; - hashSize = newHashSize; - hashMask = newHashMask; - rehash = newRehash; - return TRUE; -} - -static int -ResizeReverseMap (void) -{ - int ret = TRUE; - if (reverseMapSize == 0) - reverseMapSize = 1000; - else - reverseMapSize *= 2; - reverseMap = realloc (reverseMap, reverseMapSize * sizeof (AtomListPtr)); - if (!reverseMap) { - fprintf(stderr, "ResizeReverseMap(): Error: Couldn't reallocate" - " reverseMap (%ld)\n", - reverseMapSize * (unsigned long)sizeof(AtomListPtr)); - ret = FALSE; - } - return ret; -} - -static int -NameEqual (const char *a, const char *b, int l) -{ - while (l--) - if (*a++ != *b++) - return FALSE; - return TRUE; -} - -#ifdef __SUNPRO_C -#pragma weak MakeAtom -#endif - -weak Atom -MakeAtom(char *string, unsigned len, int makeit) -{ - AtomListPtr a; - int hash; - int h = 0; - int r; - - hash = Hash (string, len); - if (hashTable) - { - h = hash & hashMask; - if (hashTable[h]) - { - if (hashTable[h]->hash == hash && hashTable[h]->len == len && - NameEqual (hashTable[h]->name, string, len)) - { - return hashTable[h]->atom; - } - r = (hash % rehash) | 1; - for (;;) - { - h += r; - if (h >= hashSize) - h -= hashSize; - if (!hashTable[h]) - break; - if (hashTable[h]->hash == hash && hashTable[h]->len == len && - NameEqual (hashTable[h]->name, string, len)) - { - return hashTable[h]->atom; - } - } - } - } - if (!makeit) - return None; - a = malloc (sizeof (AtomListRec) + len + 1); - if (a == NULL) { - fprintf(stderr, "MakeAtom(): Error: Couldn't allocate AtomListRec" - " (%ld)\n", (unsigned long)sizeof (AtomListRec) + len + 1); - return None; - } - a->name = (char *) (a + 1); - a->len = len; - strncpy (a->name, string, len); - a->name[len] = '\0'; - a->atom = ++lastAtom; - a->hash = hash; - if (hashUsed >= hashSize / 2) - { - ResizeHashTable (); - h = hash & hashMask; - if (hashTable[h]) - { - r = (hash % rehash) | 1; - do { - h += r; - if (h >= hashSize) - h -= hashSize; - } while (hashTable[h]); - } - } - hashTable[h] = a; - hashUsed++; - if (reverseMapSize <= a->atom) { - if (!ResizeReverseMap()) - return None; - } - reverseMap[a->atom] = a; - return a->atom; -} - -#ifdef __SUNPRO_C -#pragma weak ValidAtom -#endif - -weak int -ValidAtom(Atom atom) -{ - return (atom != None) && (atom <= lastAtom); -} - -#ifdef __SUNPRO_C -#pragma weak NameForAtom -#endif - -weak char * -NameForAtom(Atom atom) -{ - if (atom != None && atom <= lastAtom) - return reverseMap[atom]->name; - return NULL; -} +/*
+
+Copyright 1990, 1994, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+/* lame atom replacement routines for font applications */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fontmisc.h>
+#include "stubs.h"
+
+typedef struct _AtomList {
+ char *name;
+ int len;
+ int hash;
+ Atom atom;
+} AtomListRec, *AtomListPtr;
+
+static AtomListPtr *hashTable;
+
+static int hashSize, hashUsed;
+static int hashMask;
+static int rehash;
+
+static AtomListPtr *reverseMap;
+static int reverseMapSize;
+static Atom lastAtom;
+
+static int
+Hash(char *string, int len)
+{
+ int h;
+
+ h = 0;
+ while (len--)
+ h = (h << 3) ^ *string++;
+ if (h < 0)
+ return -h;
+ return h;
+}
+
+static int
+ResizeHashTable (void)
+{
+ int newHashSize;
+ int newHashMask;
+ AtomListPtr *newHashTable;
+ int i;
+ int h;
+ int newRehash;
+ int r;
+
+ if (hashSize == 0)
+ newHashSize = 1024;
+ else
+ newHashSize = hashSize * 2;
+ newHashTable = calloc (newHashSize, sizeof (AtomListPtr));
+ if (!newHashTable) {
+ fprintf(stderr, "ResizeHashTable(): Error: Couldn't allocate"
+ " newHashTable (%ld)\n",
+ newHashSize * (unsigned long)sizeof (AtomListPtr));
+ return FALSE;
+ }
+ newHashMask = newHashSize - 1;
+ newRehash = (newHashMask - 2);
+ for (i = 0; i < hashSize; i++)
+ {
+ if (hashTable[i])
+ {
+ h = (hashTable[i]->hash) & newHashMask;
+ if (newHashTable[h])
+ {
+ r = hashTable[i]->hash % newRehash | 1;
+ do {
+ h += r;
+ if (h >= newHashSize)
+ h -= newHashSize;
+ } while (newHashTable[h]);
+ }
+ newHashTable[h] = hashTable[i];
+ }
+ }
+ free (hashTable);
+ hashTable = newHashTable;
+ hashSize = newHashSize;
+ hashMask = newHashMask;
+ rehash = newRehash;
+ return TRUE;
+}
+
+static int
+ResizeReverseMap (void)
+{
+ int ret = TRUE;
+ if (reverseMapSize == 0)
+ reverseMapSize = 1000;
+ else
+ reverseMapSize *= 2;
+ reverseMap = realloc (reverseMap, reverseMapSize * sizeof (AtomListPtr));
+ if (!reverseMap) {
+ fprintf(stderr, "ResizeReverseMap(): Error: Couldn't reallocate"
+ " reverseMap (%ld)\n",
+ reverseMapSize * (unsigned long)sizeof(AtomListPtr));
+ ret = FALSE;
+ }
+ return ret;
+}
+
+static int
+NameEqual (const char *a, const char *b, int l)
+{
+ while (l--)
+ if (*a++ != *b++)
+ return FALSE;
+ return TRUE;
+}
+
+#ifdef __SUNPRO_C
+#pragma weak MakeAtom
+#endif
+
+weak Atom
+MakeAtom(char *string, unsigned len, int makeit)
+{
+ AtomListPtr a;
+ int hash;
+ int h = 0;
+ int r;
+
+ hash = Hash (string, len);
+ if (hashTable)
+ {
+ h = hash & hashMask;
+ if (hashTable[h])
+ {
+ if (hashTable[h]->hash == hash && hashTable[h]->len == len &&
+ NameEqual (hashTable[h]->name, string, len))
+ {
+ return hashTable[h]->atom;
+ }
+ r = (hash % rehash) | 1;
+ for (;;)
+ {
+ h += r;
+ if (h >= hashSize)
+ h -= hashSize;
+ if (!hashTable[h])
+ break;
+ if (hashTable[h]->hash == hash && hashTable[h]->len == len &&
+ NameEqual (hashTable[h]->name, string, len))
+ {
+ return hashTable[h]->atom;
+ }
+ }
+ }
+ }
+ if (!makeit)
+ return None;
+ a = malloc (sizeof (AtomListRec) + len + 1);
+ if (a == NULL) {
+ fprintf(stderr, "MakeAtom(): Error: Couldn't allocate AtomListRec"
+ " (%ld)\n", (unsigned long)sizeof (AtomListRec) + len + 1);
+ return None;
+ }
+ a->name = (char *) (a + 1);
+ a->len = len;
+ strncpy (a->name, string, len);
+ a->name[len] = '\0';
+ a->atom = ++lastAtom;
+ a->hash = hash;
+ if (hashUsed >= hashSize / 2)
+ {
+ ResizeHashTable ();
+ h = hash & hashMask;
+ if (hashTable[h])
+ {
+ r = (hash % rehash) | 1;
+ do {
+ h += r;
+ if (h >= hashSize)
+ h -= hashSize;
+ } while (hashTable[h]);
+ }
+ }
+ hashTable[h] = a;
+ hashUsed++;
+ if (reverseMapSize <= a->atom) {
+ if (!ResizeReverseMap())
+ return None;
+ }
+ reverseMap[a->atom] = a;
+ return a->atom;
+}
+
+#ifdef __SUNPRO_C
+#pragma weak ValidAtom
+#endif
+
+weak int
+ValidAtom(Atom atom)
+{
+ return (atom != None) && (atom <= lastAtom);
+}
+
+#ifdef __SUNPRO_C
+#pragma weak NameForAtom
+#endif
+
+weak char *
+NameForAtom(Atom atom)
+{
+ if (atom != None && atom <= lastAtom)
+ return reverseMap[atom]->name;
+ return NULL;
+}
diff --git a/libXfont/src/util/fontaccel.c b/libXfont/src/util/fontaccel.c index c5915dba9..4848aac75 100644 --- a/libXfont/src/util/fontaccel.c +++ b/libXfont/src/util/fontaccel.c @@ -1,104 +1,104 @@ -/* - -Copyright 1990, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fontmisc.h> -#include <X11/fonts/fontstruct.h> -#include <X11/fonts/fontutil.h> - -void -FontComputeInfoAccelerators(FontInfoPtr pFontInfo) -{ - pFontInfo->noOverlap = FALSE; - if (pFontInfo->maxOverlap <= pFontInfo->minbounds.leftSideBearing) - pFontInfo->noOverlap = TRUE; - - if ((pFontInfo->minbounds.ascent == pFontInfo->maxbounds.ascent) && - (pFontInfo->minbounds.descent == pFontInfo->maxbounds.descent) && - (pFontInfo->minbounds.leftSideBearing == - pFontInfo->maxbounds.leftSideBearing) && - (pFontInfo->minbounds.rightSideBearing == - pFontInfo->maxbounds.rightSideBearing) && - (pFontInfo->minbounds.characterWidth == - pFontInfo->maxbounds.characterWidth) && - (pFontInfo->minbounds.attributes == pFontInfo->maxbounds.attributes)) { - pFontInfo->constantMetrics = TRUE; - if ((pFontInfo->maxbounds.leftSideBearing == 0) && - (pFontInfo->maxbounds.rightSideBearing == - pFontInfo->maxbounds.characterWidth) && - (pFontInfo->maxbounds.ascent == pFontInfo->fontAscent) && - (pFontInfo->maxbounds.descent == pFontInfo->fontDescent)) - pFontInfo->terminalFont = TRUE; - else - pFontInfo->terminalFont = FALSE; - } else { - pFontInfo->constantMetrics = FALSE; - pFontInfo->terminalFont = FALSE; - } - if (pFontInfo->minbounds.characterWidth == pFontInfo->maxbounds.characterWidth) - pFontInfo->constantWidth = TRUE; - else - pFontInfo->constantWidth = FALSE; - - if ((pFontInfo->minbounds.leftSideBearing >= 0) && - (pFontInfo->maxOverlap <= 0) && - (pFontInfo->minbounds.ascent >= -pFontInfo->fontDescent) && - (pFontInfo->maxbounds.ascent <= pFontInfo->fontAscent) && - (-pFontInfo->minbounds.descent <= pFontInfo->fontAscent) && - (pFontInfo->maxbounds.descent <= pFontInfo->fontDescent)) - pFontInfo->inkInside = TRUE; - else - pFontInfo->inkInside = FALSE; -} - -int -FontCouldBeTerminal(FontInfoPtr pFontInfo) -{ - if ((pFontInfo->minbounds.leftSideBearing >= 0) && - (pFontInfo->maxbounds.rightSideBearing <= pFontInfo->maxbounds.characterWidth) && - (pFontInfo->minbounds.characterWidth == pFontInfo->maxbounds.characterWidth) && - (pFontInfo->maxbounds.ascent <= pFontInfo->fontAscent) && - (pFontInfo->maxbounds.descent <= pFontInfo->fontDescent) && - (pFontInfo->maxbounds.leftSideBearing != 0 || - pFontInfo->minbounds.rightSideBearing != pFontInfo->minbounds.characterWidth || - pFontInfo->minbounds.ascent != pFontInfo->fontAscent || - pFontInfo->minbounds.descent != pFontInfo->fontDescent)) { - /* blow off font with nothing but a SPACE */ - if (pFontInfo->maxbounds.ascent == 0 && - pFontInfo->maxbounds.descent == 0) - return FALSE; - return TRUE; - } - return FALSE; -} +/*
+
+Copyright 1990, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fontmisc.h>
+#include <X11/fonts/fontstruct.h>
+#include <X11/fonts/fontutil.h>
+
+void
+FontComputeInfoAccelerators(FontInfoPtr pFontInfo)
+{
+ pFontInfo->noOverlap = FALSE;
+ if (pFontInfo->maxOverlap <= pFontInfo->minbounds.leftSideBearing)
+ pFontInfo->noOverlap = TRUE;
+
+ if ((pFontInfo->minbounds.ascent == pFontInfo->maxbounds.ascent) &&
+ (pFontInfo->minbounds.descent == pFontInfo->maxbounds.descent) &&
+ (pFontInfo->minbounds.leftSideBearing ==
+ pFontInfo->maxbounds.leftSideBearing) &&
+ (pFontInfo->minbounds.rightSideBearing ==
+ pFontInfo->maxbounds.rightSideBearing) &&
+ (pFontInfo->minbounds.characterWidth ==
+ pFontInfo->maxbounds.characterWidth) &&
+ (pFontInfo->minbounds.attributes == pFontInfo->maxbounds.attributes)) {
+ pFontInfo->constantMetrics = TRUE;
+ if ((pFontInfo->maxbounds.leftSideBearing == 0) &&
+ (pFontInfo->maxbounds.rightSideBearing ==
+ pFontInfo->maxbounds.characterWidth) &&
+ (pFontInfo->maxbounds.ascent == pFontInfo->fontAscent) &&
+ (pFontInfo->maxbounds.descent == pFontInfo->fontDescent))
+ pFontInfo->terminalFont = TRUE;
+ else
+ pFontInfo->terminalFont = FALSE;
+ } else {
+ pFontInfo->constantMetrics = FALSE;
+ pFontInfo->terminalFont = FALSE;
+ }
+ if (pFontInfo->minbounds.characterWidth == pFontInfo->maxbounds.characterWidth)
+ pFontInfo->constantWidth = TRUE;
+ else
+ pFontInfo->constantWidth = FALSE;
+
+ if ((pFontInfo->minbounds.leftSideBearing >= 0) &&
+ (pFontInfo->maxOverlap <= 0) &&
+ (pFontInfo->minbounds.ascent >= -pFontInfo->fontDescent) &&
+ (pFontInfo->maxbounds.ascent <= pFontInfo->fontAscent) &&
+ (-pFontInfo->minbounds.descent <= pFontInfo->fontAscent) &&
+ (pFontInfo->maxbounds.descent <= pFontInfo->fontDescent))
+ pFontInfo->inkInside = TRUE;
+ else
+ pFontInfo->inkInside = FALSE;
+}
+
+int
+FontCouldBeTerminal(FontInfoPtr pFontInfo)
+{
+ if ((pFontInfo->minbounds.leftSideBearing >= 0) &&
+ (pFontInfo->maxbounds.rightSideBearing <= pFontInfo->maxbounds.characterWidth) &&
+ (pFontInfo->minbounds.characterWidth == pFontInfo->maxbounds.characterWidth) &&
+ (pFontInfo->maxbounds.ascent <= pFontInfo->fontAscent) &&
+ (pFontInfo->maxbounds.descent <= pFontInfo->fontDescent) &&
+ (pFontInfo->maxbounds.leftSideBearing != 0 ||
+ pFontInfo->minbounds.rightSideBearing != pFontInfo->minbounds.characterWidth ||
+ pFontInfo->minbounds.ascent != pFontInfo->fontAscent ||
+ pFontInfo->minbounds.descent != pFontInfo->fontDescent)) {
+ /* blow off font with nothing but a SPACE */
+ if (pFontInfo->maxbounds.ascent == 0 &&
+ pFontInfo->maxbounds.descent == 0)
+ return FALSE;
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/libXfont/src/util/fontnames.c b/libXfont/src/util/fontnames.c index ceafce593..3beaf0fd5 100644 --- a/libXfont/src/util/fontnames.c +++ b/libXfont/src/util/fontnames.c @@ -1,119 +1,119 @@ -/* - -Copyright 1991, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fontmisc.h> -#include <X11/fonts/fontstruct.h> - -void -FreeFontNames(FontNamesPtr pFN) -{ - int i; - - if (!pFN) - return; - for (i = 0; i < pFN->nnames; i++) { - free(pFN->names[i]); - } - free(pFN->names); - free(pFN->length); - free(pFN); -} - -FontNamesPtr -MakeFontNamesRecord(unsigned int size) -{ - FontNamesPtr pFN; - - pFN = malloc(sizeof(FontNamesRec)); - if (pFN) { - pFN->nnames = 0; - pFN->size = size; - if (size) - { - pFN->length = malloc(size * sizeof(int)); - pFN->names = malloc(size * sizeof(char *)); - if (!pFN->length || !pFN->names) { - free(pFN->length); - free(pFN->names); - free(pFN); - pFN = (FontNamesPtr) 0; - } - } - else - { - pFN->length = 0; - pFN->names = 0; - } - } - return pFN; -} - -int -AddFontNamesName(FontNamesPtr names, char *name, int length) -{ - int index = names->nnames; - char *nelt; - - nelt = malloc(length + 1); - if (!nelt) - return AllocError; - if (index >= names->size) { - int size = names->size << 1; - int *nlength; - char **nnames; - - if (size == 0) - size = 8; - nlength = realloc(names->length, size * sizeof(int)); - nnames = realloc(names->names, size * sizeof(char *)); - if (nlength && nnames) { - names->size = size; - names->length = nlength; - names->names = nnames; - } else { - free(nelt); - free(nlength); - free(nnames); - return AllocError; - } - } - names->length[index] = length; - names->names[index] = nelt; - strncpy(nelt, name, length); - nelt[length] = '\0'; - names->nnames++; - return Successful; -} +/*
+
+Copyright 1991, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fontmisc.h>
+#include <X11/fonts/fontstruct.h>
+
+void
+FreeFontNames(FontNamesPtr pFN)
+{
+ int i;
+
+ if (!pFN)
+ return;
+ for (i = 0; i < pFN->nnames; i++) {
+ free(pFN->names[i]);
+ }
+ free(pFN->names);
+ free(pFN->length);
+ free(pFN);
+}
+
+FontNamesPtr
+MakeFontNamesRecord(unsigned int size)
+{
+ FontNamesPtr pFN;
+
+ pFN = malloc(sizeof(FontNamesRec));
+ if (pFN) {
+ pFN->nnames = 0;
+ pFN->size = size;
+ if (size)
+ {
+ pFN->length = malloc(size * sizeof(int));
+ pFN->names = malloc(size * sizeof(char *));
+ if (!pFN->length || !pFN->names) {
+ free(pFN->length);
+ free(pFN->names);
+ free(pFN);
+ pFN = (FontNamesPtr) 0;
+ }
+ }
+ else
+ {
+ pFN->length = 0;
+ pFN->names = 0;
+ }
+ }
+ return pFN;
+}
+
+int
+AddFontNamesName(FontNamesPtr names, char *name, int length)
+{
+ int index = names->nnames;
+ char *nelt;
+
+ nelt = malloc(length + 1);
+ if (!nelt)
+ return AllocError;
+ if (index >= names->size) {
+ int size = names->size << 1;
+ int *nlength;
+ char **nnames;
+
+ if (size == 0)
+ size = 8;
+ nlength = realloc(names->length, size * sizeof(int));
+ nnames = realloc(names->names, size * sizeof(char *));
+ if (nlength && nnames) {
+ names->size = size;
+ names->length = nlength;
+ names->names = nnames;
+ } else {
+ free(nelt);
+ free(nlength);
+ free(nnames);
+ return AllocError;
+ }
+ }
+ names->length[index] = length;
+ names->names[index] = nelt;
+ strncpy(nelt, name, length);
+ nelt[length] = '\0';
+ names->nnames++;
+ return Successful;
+}
diff --git a/libXfont/src/util/fontutil.c b/libXfont/src/util/fontutil.c index 22f6119ae..552a1e3df 100644 --- a/libXfont/src/util/fontutil.c +++ b/libXfont/src/util/fontutil.c @@ -1,410 +1,410 @@ -/* - -Copyright 1991, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fontmisc.h> -#include <X11/fonts/fontstruct.h> -#include <X11/fonts/FSproto.h> -#include <X11/fonts/fontutil.h> - -/* Define global here... doesn't hurt the servers, and avoids - unresolved references in font clients. */ - -static int defaultGlyphCachingMode = DEFAULT_GLYPH_CACHING_MODE; -int glyphCachingMode = DEFAULT_GLYPH_CACHING_MODE; - -void -GetGlyphs(FontPtr font, - unsigned long count, - unsigned char *chars, - FontEncoding fontEncoding, - unsigned long *glyphcount, /* RETURN */ - CharInfoPtr *glyphs) /* RETURN */ -{ - (*font->get_glyphs) (font, count, chars, fontEncoding, glyphcount, glyphs); -} - -#define MIN(a,b) ((a)<(b)?(a):(b)) -#define MAX(a,b) ((a)>(b)?(a):(b)) - -void -QueryGlyphExtents(FontPtr pFont, - CharInfoPtr *charinfo, - unsigned long count, - ExtentInfoRec *info) -{ - register unsigned long i; - xCharInfo *pCI; - - info->drawDirection = pFont->info.drawDirection; - - info->fontAscent = pFont->info.fontAscent; - info->fontDescent = pFont->info.fontDescent; - - if (count != 0) { - - pCI = &((*charinfo)->metrics); charinfo++; - /* ignore nonexisting characters when calculating text extents */ - if ( !((pCI->characterWidth == 0) - && (pCI->rightSideBearing == 0) - && (pCI->leftSideBearing == 0) - && (pCI->ascent == 0) - && (pCI->descent == 0)) ) { - info->overallAscent = pCI->ascent; - info->overallDescent = pCI->descent; - info->overallLeft = pCI->leftSideBearing; - info->overallRight = pCI->rightSideBearing; - info->overallWidth = pCI->characterWidth; - } - - if (pFont->info.constantMetrics && pFont->info.noOverlap) { - info->overallWidth *= count; - info->overallRight += (info->overallWidth - - pCI->characterWidth); - } else { - for (i = 1; i < count; i++) { - pCI = &((*charinfo)->metrics); charinfo++; - /* ignore nonexisting characters when calculating extents */ - if ( !((pCI->characterWidth == 0) - && (pCI->rightSideBearing == 0) - && (pCI->leftSideBearing == 0) - && (pCI->ascent == 0) - && (pCI->descent == 0)) ) { - info->overallAscent = MAX( - info->overallAscent, - pCI->ascent); - info->overallDescent = MAX( - info->overallDescent, - pCI->descent); - info->overallLeft = MIN( - info->overallLeft, - info->overallWidth + pCI->leftSideBearing); - info->overallRight = MAX( - info->overallRight, - info->overallWidth + pCI->rightSideBearing); - /* - * yes, this order is correct; overallWidth IS incremented - * last - */ - info->overallWidth += pCI->characterWidth; - } - } - } - } else { - info->overallAscent = 0; - info->overallDescent = 0; - info->overallWidth = 0; - info->overallLeft = 0; - info->overallRight = 0; - } -} - -Bool -QueryTextExtents(FontPtr pFont, - unsigned long count, - unsigned char *chars, - ExtentInfoRec *info) -{ - xCharInfo **charinfo; - unsigned long n; - FontEncoding encoding; - int cm; - int i; - unsigned long t; - xCharInfo *defaultChar = 0; - unsigned char defc[2]; - int firstReal; - - charinfo = malloc(count * sizeof(xCharInfo *)); - if (!charinfo) - return FALSE; - encoding = TwoD16Bit; - if (pFont->info.lastRow == 0) - encoding = Linear16Bit; - (*pFont->get_metrics) (pFont, count, chars, encoding, &n, charinfo); - - /* Do default character substitution as get_metrics doesn't */ - -#define IsNonExistentChar(ci) (!(ci) || \ - ((ci)->ascent == 0 && \ - (ci)->descent == 0 && \ - (ci)->leftSideBearing == 0 && \ - (ci)->rightSideBearing == 0 && \ - (ci)->characterWidth == 0)) - - firstReal = n; - defc[0] = pFont->info.defaultCh >> 8; - defc[1] = pFont->info.defaultCh; - (*pFont->get_metrics) (pFont, 1, defc, encoding, &t, &defaultChar); - if ((IsNonExistentChar (defaultChar))) - defaultChar = 0; - for (i = 0; i < n; i++) - { - if ((IsNonExistentChar (charinfo[i]))) - { - if (!defaultChar) - continue; - charinfo[i] = defaultChar; - } - if (firstReal == n) - firstReal = i; - } - cm = pFont->info.constantMetrics; - pFont->info.constantMetrics = FALSE; - QueryGlyphExtents(pFont, (CharInfoPtr*) charinfo + firstReal, - n - firstReal, info); - pFont->info.constantMetrics = cm; - free(charinfo); - return TRUE; -} - -Bool -ParseGlyphCachingMode(char *str) -{ - if (!strcmp(str, "none")) defaultGlyphCachingMode = CACHING_OFF; - else if (!strcmp(str, "all")) defaultGlyphCachingMode = CACHE_ALL_GLYPHS; - else if (!strcmp(str, "16")) defaultGlyphCachingMode = CACHE_16_BIT_GLYPHS; - else return FALSE; - return TRUE; -} - -void -InitGlyphCaching(void) -{ - /* Set glyphCachingMode to the mode the server hopes to - support. DDX drivers that do not support the requested level - of glyph caching can call SetGlyphCachingMode to lower the - level of support. - */ - - glyphCachingMode = defaultGlyphCachingMode; -} - -/* ddxen can call SetGlyphCachingMode to inform us of what level of glyph - * caching they can support. - */ -void -SetGlyphCachingMode(int newmode) -{ - if ( (glyphCachingMode > newmode) && (newmode >= 0) ) - glyphCachingMode = newmode; -} - -#define range_alloc_granularity 16 -#define mincharp(p) ((p)->min_char_low + ((p)->min_char_high << 8)) -#define maxcharp(p) ((p)->max_char_low + ((p)->max_char_high << 8)) - -/* add_range(): Add range to a list of ranges, with coalescence */ -int -add_range(fsRange *newrange, - int *nranges, - fsRange **range, - Bool charset_subset) -{ - int first, last, middle; - unsigned long keymin, keymax; - unsigned long ptrmin = 0, ptrmax = 0; - fsRange *ptr = NULL, *ptr1, *ptr2, *endptr; - - /* There are two different ways to treat ranges: - - 1) Charset subsetting (support of the HP XLFD enhancements), in - which a range of 0x1234,0x3456 means all numbers between - 0x1234 and 0x3456, and in which min and max might be swapped. - - 2) Row/column ranges, in which a range of 0x1234,0x3456 means the - ranges 0x1234-0x1256, 0x1334-0x1356, ... , 0x3434-0x3456. - This is for support of glyph caching. - - The choice of treatment is selected with the "charset_subset" - flag */ - - /* If newrange covers multiple rows; break up the rows */ - if (!charset_subset && newrange->min_char_high != newrange->max_char_high) - { - int i, err = 0; - fsRange temprange; - for (i = newrange->min_char_high; - i <= newrange->max_char_high; - i++) - { - temprange.min_char_low = newrange->min_char_low; - temprange.max_char_low = newrange->max_char_low; - temprange.min_char_high = temprange.max_char_high = i; - err = add_range(&temprange, nranges, range, charset_subset); - if (err != Successful) break; - } - return err; - } - - keymin = mincharp(newrange); - keymax = maxcharp(newrange); - - if (charset_subset && keymin > keymax) - { - unsigned long temp = keymin; - keymin = keymax; - keymax = temp; - } - - /* add_range() maintains a sorted list; this makes possible coalescence - and binary searches */ - - /* Binary search for a range with which the new range can merge */ - - first = middle = 0; - last = *nranges - 1; - while (last >= first) - { - middle = (first + last) / 2; - ptr = (*range) + middle; - ptrmin = mincharp(ptr); - ptrmax = maxcharp(ptr); - - if (ptrmin > 0 && keymax < ptrmin - 1) last = middle - 1; - else if (keymin > ptrmax + 1) first = middle + 1; - else if (!charset_subset) - { - /* We might have a range with which to merge... IF the - result doesn't cross rows */ - if (newrange->min_char_high != ptr->min_char_high) - last = first - 1; /* Force adding a new range */ - break; - } - else break; /* We have at least one range with which we can merge */ - } - - if (last < first) - { - /* Search failed; we need to add a new range to the list. */ - - /* Grow the list if necessary */ - if (*nranges == 0 || *range == (fsRange *)0) - { - *range = malloc(range_alloc_granularity * SIZEOF(fsRange)); - *nranges = 0; - } - else if (!(*nranges % range_alloc_granularity)) - { - *range = realloc(*range, (*nranges + range_alloc_granularity) * - SIZEOF(fsRange)); - } - - /* If alloc failed, just return a null list */ - if (*range == (fsRange *)0) - { - *nranges = 0; - return AllocError; - } - - /* Should new entry go *at* or *after* ptr? */ - ptr = (*range) + middle; - if (middle < *nranges && keymin > ptrmin) ptr++; /* after */ - - /* Open up a space for our new range */ - memmove((char *)(ptr + 1), - (char *)ptr, - (char *)(*range + *nranges) - (char *)ptr); - - /* Insert the new range */ - ptr->min_char_low = keymin & 0xff; - ptr->min_char_high = keymin >> 8; - ptr->max_char_low = keymax & 0xff; - ptr->max_char_high = keymax >> 8; - - /* Update range count */ - (*nranges)++; - - /* Done */ - return Successful; - } - - /* Join our new range to that pointed to by "ptr" */ - if (keymin < ptrmin) - { - ptr->min_char_low = keymin & 0xff; - ptr->min_char_high = keymin >> 8; - } - if (keymax > ptrmax) - { - ptr->max_char_low = keymax & 0xff; - ptr->max_char_high = keymax >> 8; - } - - ptrmin = mincharp(ptr); - ptrmax = maxcharp(ptr); - - endptr = *range + *nranges; - - for (ptr1 = ptr; ptr1 >= *range; ptr1--) - { - if (ptrmin <= maxcharp(ptr1) + 1) - { - if (!charset_subset && ptr->min_char_high != ptr1->min_char_high) - break; - if (ptrmin >= mincharp(ptr1)) - ptrmin = mincharp(ptr1); - } - else break; - } - for (ptr2 = ptr; ptr2 < endptr; ptr2++) - { - if ((ptr2->min_char_low == 0 && ptr2->min_char_high == 0) || - ptrmax >= mincharp(ptr2) - 1) - { - if (!charset_subset && ptr->min_char_high != ptr2->min_char_high) - break; - if (ptrmax <= maxcharp(ptr2)) - ptrmax = maxcharp(ptr2); - } - else break; - } - - /* We need to coalesce ranges between ptr1 and ptr2 exclusive */ - ptr1++; - ptr2--; - if (ptr1 != ptr2) - { - memmove(ptr1, ptr2, (char *)endptr - (char *)ptr2); - *nranges -= (ptr2 - ptr1); - } - - /* Write the new range into the range list */ - ptr1->min_char_low = ptrmin & 0xff; - ptr1->min_char_high = ptrmin >> 8; - ptr1->max_char_low = ptrmax & 0xff; - ptr1->max_char_high = ptrmax >> 8; - - return Successful; -} +/*
+
+Copyright 1991, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fontmisc.h>
+#include <X11/fonts/fontstruct.h>
+#include <X11/fonts/FSproto.h>
+#include <X11/fonts/fontutil.h>
+
+/* Define global here... doesn't hurt the servers, and avoids
+ unresolved references in font clients. */
+
+static int defaultGlyphCachingMode = DEFAULT_GLYPH_CACHING_MODE;
+int glyphCachingMode = DEFAULT_GLYPH_CACHING_MODE;
+
+void
+GetGlyphs(FontPtr font,
+ unsigned long count,
+ unsigned char *chars,
+ FontEncoding fontEncoding,
+ unsigned long *glyphcount, /* RETURN */
+ CharInfoPtr *glyphs) /* RETURN */
+{
+ (*font->get_glyphs) (font, count, chars, fontEncoding, glyphcount, glyphs);
+}
+
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
+void
+QueryGlyphExtents(FontPtr pFont,
+ CharInfoPtr *charinfo,
+ unsigned long count,
+ ExtentInfoRec *info)
+{
+ register unsigned long i;
+ xCharInfo *pCI;
+
+ info->drawDirection = pFont->info.drawDirection;
+
+ info->fontAscent = pFont->info.fontAscent;
+ info->fontDescent = pFont->info.fontDescent;
+
+ if (count != 0) {
+
+ pCI = &((*charinfo)->metrics); charinfo++;
+ /* ignore nonexisting characters when calculating text extents */
+ if ( !((pCI->characterWidth == 0)
+ && (pCI->rightSideBearing == 0)
+ && (pCI->leftSideBearing == 0)
+ && (pCI->ascent == 0)
+ && (pCI->descent == 0)) ) {
+ info->overallAscent = pCI->ascent;
+ info->overallDescent = pCI->descent;
+ info->overallLeft = pCI->leftSideBearing;
+ info->overallRight = pCI->rightSideBearing;
+ info->overallWidth = pCI->characterWidth;
+ }
+
+ if (pFont->info.constantMetrics && pFont->info.noOverlap) {
+ info->overallWidth *= count;
+ info->overallRight += (info->overallWidth -
+ pCI->characterWidth);
+ } else {
+ for (i = 1; i < count; i++) {
+ pCI = &((*charinfo)->metrics); charinfo++;
+ /* ignore nonexisting characters when calculating extents */
+ if ( !((pCI->characterWidth == 0)
+ && (pCI->rightSideBearing == 0)
+ && (pCI->leftSideBearing == 0)
+ && (pCI->ascent == 0)
+ && (pCI->descent == 0)) ) {
+ info->overallAscent = MAX(
+ info->overallAscent,
+ pCI->ascent);
+ info->overallDescent = MAX(
+ info->overallDescent,
+ pCI->descent);
+ info->overallLeft = MIN(
+ info->overallLeft,
+ info->overallWidth + pCI->leftSideBearing);
+ info->overallRight = MAX(
+ info->overallRight,
+ info->overallWidth + pCI->rightSideBearing);
+ /*
+ * yes, this order is correct; overallWidth IS incremented
+ * last
+ */
+ info->overallWidth += pCI->characterWidth;
+ }
+ }
+ }
+ } else {
+ info->overallAscent = 0;
+ info->overallDescent = 0;
+ info->overallWidth = 0;
+ info->overallLeft = 0;
+ info->overallRight = 0;
+ }
+}
+
+Bool
+QueryTextExtents(FontPtr pFont,
+ unsigned long count,
+ unsigned char *chars,
+ ExtentInfoRec *info)
+{
+ xCharInfo **charinfo;
+ unsigned long n;
+ FontEncoding encoding;
+ int cm;
+ int i;
+ unsigned long t;
+ xCharInfo *defaultChar = 0;
+ unsigned char defc[2];
+ int firstReal;
+
+ charinfo = malloc(count * sizeof(xCharInfo *));
+ if (!charinfo)
+ return FALSE;
+ encoding = TwoD16Bit;
+ if (pFont->info.lastRow == 0)
+ encoding = Linear16Bit;
+ (*pFont->get_metrics) (pFont, count, chars, encoding, &n, charinfo);
+
+ /* Do default character substitution as get_metrics doesn't */
+
+#define IsNonExistentChar(ci) (!(ci) || \
+ ((ci)->ascent == 0 && \
+ (ci)->descent == 0 && \
+ (ci)->leftSideBearing == 0 && \
+ (ci)->rightSideBearing == 0 && \
+ (ci)->characterWidth == 0))
+
+ firstReal = n;
+ defc[0] = pFont->info.defaultCh >> 8;
+ defc[1] = pFont->info.defaultCh;
+ (*pFont->get_metrics) (pFont, 1, defc, encoding, &t, &defaultChar);
+ if ((IsNonExistentChar (defaultChar)))
+ defaultChar = 0;
+ for (i = 0; i < n; i++)
+ {
+ if ((IsNonExistentChar (charinfo[i])))
+ {
+ if (!defaultChar)
+ continue;
+ charinfo[i] = defaultChar;
+ }
+ if (firstReal == n)
+ firstReal = i;
+ }
+ cm = pFont->info.constantMetrics;
+ pFont->info.constantMetrics = FALSE;
+ QueryGlyphExtents(pFont, (CharInfoPtr*) charinfo + firstReal,
+ n - firstReal, info);
+ pFont->info.constantMetrics = cm;
+ free(charinfo);
+ return TRUE;
+}
+
+Bool
+ParseGlyphCachingMode(char *str)
+{
+ if (!strcmp(str, "none")) defaultGlyphCachingMode = CACHING_OFF;
+ else if (!strcmp(str, "all")) defaultGlyphCachingMode = CACHE_ALL_GLYPHS;
+ else if (!strcmp(str, "16")) defaultGlyphCachingMode = CACHE_16_BIT_GLYPHS;
+ else return FALSE;
+ return TRUE;
+}
+
+void
+InitGlyphCaching(void)
+{
+ /* Set glyphCachingMode to the mode the server hopes to
+ support. DDX drivers that do not support the requested level
+ of glyph caching can call SetGlyphCachingMode to lower the
+ level of support.
+ */
+
+ glyphCachingMode = defaultGlyphCachingMode;
+}
+
+/* ddxen can call SetGlyphCachingMode to inform us of what level of glyph
+ * caching they can support.
+ */
+void
+SetGlyphCachingMode(int newmode)
+{
+ if ( (glyphCachingMode > newmode) && (newmode >= 0) )
+ glyphCachingMode = newmode;
+}
+
+#define range_alloc_granularity 16
+#define mincharp(p) ((p)->min_char_low + ((p)->min_char_high << 8))
+#define maxcharp(p) ((p)->max_char_low + ((p)->max_char_high << 8))
+
+/* add_range(): Add range to a list of ranges, with coalescence */
+int
+add_range(fsRange *newrange,
+ int *nranges,
+ fsRange **range,
+ Bool charset_subset)
+{
+ int first, last, middle;
+ unsigned long keymin, keymax;
+ unsigned long ptrmin = 0, ptrmax = 0;
+ fsRange *ptr = NULL, *ptr1, *ptr2, *endptr;
+
+ /* There are two different ways to treat ranges:
+
+ 1) Charset subsetting (support of the HP XLFD enhancements), in
+ which a range of 0x1234,0x3456 means all numbers between
+ 0x1234 and 0x3456, and in which min and max might be swapped.
+
+ 2) Row/column ranges, in which a range of 0x1234,0x3456 means the
+ ranges 0x1234-0x1256, 0x1334-0x1356, ... , 0x3434-0x3456.
+ This is for support of glyph caching.
+
+ The choice of treatment is selected with the "charset_subset"
+ flag */
+
+ /* If newrange covers multiple rows; break up the rows */
+ if (!charset_subset && newrange->min_char_high != newrange->max_char_high)
+ {
+ int i, err = 0;
+ fsRange temprange;
+ for (i = newrange->min_char_high;
+ i <= newrange->max_char_high;
+ i++)
+ {
+ temprange.min_char_low = newrange->min_char_low;
+ temprange.max_char_low = newrange->max_char_low;
+ temprange.min_char_high = temprange.max_char_high = i;
+ err = add_range(&temprange, nranges, range, charset_subset);
+ if (err != Successful) break;
+ }
+ return err;
+ }
+
+ keymin = mincharp(newrange);
+ keymax = maxcharp(newrange);
+
+ if (charset_subset && keymin > keymax)
+ {
+ unsigned long temp = keymin;
+ keymin = keymax;
+ keymax = temp;
+ }
+
+ /* add_range() maintains a sorted list; this makes possible coalescence
+ and binary searches */
+
+ /* Binary search for a range with which the new range can merge */
+
+ first = middle = 0;
+ last = *nranges - 1;
+ while (last >= first)
+ {
+ middle = (first + last) / 2;
+ ptr = (*range) + middle;
+ ptrmin = mincharp(ptr);
+ ptrmax = maxcharp(ptr);
+
+ if (ptrmin > 0 && keymax < ptrmin - 1) last = middle - 1;
+ else if (keymin > ptrmax + 1) first = middle + 1;
+ else if (!charset_subset)
+ {
+ /* We might have a range with which to merge... IF the
+ result doesn't cross rows */
+ if (newrange->min_char_high != ptr->min_char_high)
+ last = first - 1; /* Force adding a new range */
+ break;
+ }
+ else break; /* We have at least one range with which we can merge */
+ }
+
+ if (last < first)
+ {
+ /* Search failed; we need to add a new range to the list. */
+
+ /* Grow the list if necessary */
+ if (*nranges == 0 || *range == (fsRange *)0)
+ {
+ *range = malloc(range_alloc_granularity * SIZEOF(fsRange));
+ *nranges = 0;
+ }
+ else if (!(*nranges % range_alloc_granularity))
+ {
+ *range = realloc(*range, (*nranges + range_alloc_granularity) *
+ SIZEOF(fsRange));
+ }
+
+ /* If alloc failed, just return a null list */
+ if (*range == (fsRange *)0)
+ {
+ *nranges = 0;
+ return AllocError;
+ }
+
+ /* Should new entry go *at* or *after* ptr? */
+ ptr = (*range) + middle;
+ if (middle < *nranges && keymin > ptrmin) ptr++; /* after */
+
+ /* Open up a space for our new range */
+ memmove((char *)(ptr + 1),
+ (char *)ptr,
+ (char *)(*range + *nranges) - (char *)ptr);
+
+ /* Insert the new range */
+ ptr->min_char_low = keymin & 0xff;
+ ptr->min_char_high = keymin >> 8;
+ ptr->max_char_low = keymax & 0xff;
+ ptr->max_char_high = keymax >> 8;
+
+ /* Update range count */
+ (*nranges)++;
+
+ /* Done */
+ return Successful;
+ }
+
+ /* Join our new range to that pointed to by "ptr" */
+ if (keymin < ptrmin)
+ {
+ ptr->min_char_low = keymin & 0xff;
+ ptr->min_char_high = keymin >> 8;
+ }
+ if (keymax > ptrmax)
+ {
+ ptr->max_char_low = keymax & 0xff;
+ ptr->max_char_high = keymax >> 8;
+ }
+
+ ptrmin = mincharp(ptr);
+ ptrmax = maxcharp(ptr);
+
+ endptr = *range + *nranges;
+
+ for (ptr1 = ptr; ptr1 >= *range; ptr1--)
+ {
+ if (ptrmin <= maxcharp(ptr1) + 1)
+ {
+ if (!charset_subset && ptr->min_char_high != ptr1->min_char_high)
+ break;
+ if (ptrmin >= mincharp(ptr1))
+ ptrmin = mincharp(ptr1);
+ }
+ else break;
+ }
+ for (ptr2 = ptr; ptr2 < endptr; ptr2++)
+ {
+ if ((ptr2->min_char_low == 0 && ptr2->min_char_high == 0) ||
+ ptrmax >= mincharp(ptr2) - 1)
+ {
+ if (!charset_subset && ptr->min_char_high != ptr2->min_char_high)
+ break;
+ if (ptrmax <= maxcharp(ptr2))
+ ptrmax = maxcharp(ptr2);
+ }
+ else break;
+ }
+
+ /* We need to coalesce ranges between ptr1 and ptr2 exclusive */
+ ptr1++;
+ ptr2--;
+ if (ptr1 != ptr2)
+ {
+ memmove(ptr1, ptr2, (char *)endptr - (char *)ptr2);
+ *nranges -= (ptr2 - ptr1);
+ }
+
+ /* Write the new range into the range list */
+ ptr1->min_char_low = ptrmin & 0xff;
+ ptr1->min_char_high = ptrmin >> 8;
+ ptr1->max_char_low = ptrmax & 0xff;
+ ptr1->max_char_high = ptrmax >> 8;
+
+ return Successful;
+}
diff --git a/libXfont/src/util/fontxlfd.c b/libXfont/src/util/fontxlfd.c index 81240376f..26ef042e7 100644 --- a/libXfont/src/util/fontxlfd.c +++ b/libXfont/src/util/fontxlfd.c @@ -1,632 +1,632 @@ -/* - -Copyright 1990, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fontmisc.h> -#include <X11/fonts/fontstruct.h> -#include <X11/fonts/fontxlfd.h> -#include <X11/fonts/fontutil.h> -#include <X11/Xos.h> -#include <math.h> -#include <stdlib.h> -#if defined(sony) && !defined(SYSTYPE_SYSV) && !defined(_SYSTYPE_SYSV) -#define NO_LOCALE -#endif -#ifndef NO_LOCALE -#include <locale.h> -#endif -#include <ctype.h> -#include <stdio.h> /* for sprintf() */ - -static char * -GetInt(char *ptr, int *val) -{ - if (*ptr == '*') { - *val = -1; - ptr++; - } else - for (*val = 0; *ptr >= '0' && *ptr <= '9';) - *val = *val * 10 + *ptr++ - '0'; - if (*ptr == '-') - return ptr; - return (char *) 0; -} - -#define minchar(p) ((p).min_char_low + ((p).min_char_high << 8)) -#define maxchar(p) ((p).max_char_low + ((p).max_char_high << 8)) - - -#ifndef NO_LOCALE -static struct lconv *locale = 0; -#endif -static char *radix = ".", *plus = "+", *minus = "-"; - -static char * -readreal(char *ptr, double *result) -{ - char buffer[80], *p1, *p2; - -#ifndef NO_LOCALE - /* Figure out what symbols apply in this locale */ - - if (!locale) - { - locale = localeconv(); - if (locale->decimal_point && *locale->decimal_point) - radix = locale->decimal_point; - if (locale->positive_sign && *locale->positive_sign) - plus = locale->positive_sign; - if (locale->negative_sign && *locale->negative_sign) - minus = locale->negative_sign; - } -#endif - /* Copy the first 80 chars of ptr into our local buffer, changing - symbols as needed. */ - for (p1 = ptr, p2 = buffer; - *p1 && (p2 - buffer) < sizeof(buffer) - 1; - p1++, p2++) - { - switch(*p1) - { - case '~': *p2 = *minus; break; - case '+': *p2 = *plus; break; - case '.': *p2 = *radix; break; - default: *p2 = *p1; - } - } - *p2 = 0; - - /* Now we have something that strtod() can interpret... do it. */ - *result = strtod(buffer, &p1); - /* Return NULL if failure, pointer past number if success */ - return (p1 == buffer) ? (char *)0 : (ptr + (p1 - buffer)); -} - -static char * -xlfd_double_to_text(double value, char *buffer, int space_required) -{ - char formatbuf[40]; - register char *p1; - int ndigits, exponent; - -#ifndef NO_LOCALE - if (!locale) - { - locale = localeconv(); - if (locale->decimal_point && *locale->decimal_point) - radix = locale->decimal_point; - if (locale->positive_sign && *locale->positive_sign) - plus = locale->positive_sign; - if (locale->negative_sign && *locale->negative_sign) - minus = locale->negative_sign; - } -#endif - /* Compute a format to use to render the number */ - sprintf(formatbuf, "%%.%dle", XLFD_NDIGITS); - - if (space_required) - *buffer++ = ' '; - - /* Render the number using printf's idea of formatting */ - sprintf(buffer, formatbuf, value); - - /* Find and read the exponent value */ - for (p1 = buffer + strlen(buffer); - *p1-- != 'e' && p1[1] != 'E';); - exponent = atoi(p1 + 2); - if (value == 0.0) exponent = 0; - - /* Figure out how many digits are significant */ - while (p1 >= buffer && (!isdigit(*p1) || *p1 == '0')) p1--; - ndigits = 0; - while (p1 >= buffer) if (isdigit(*p1--)) ndigits++; - - /* Figure out notation to use */ - if (exponent >= XLFD_NDIGITS || ndigits - exponent > XLFD_NDIGITS + 1) - { - /* Scientific */ - sprintf(formatbuf, "%%.%dle", ndigits - 1); - sprintf(buffer, formatbuf, value); - } - else - { - /* Fixed */ - ndigits -= exponent + 1; - if (ndigits < 0) ndigits = 0; - sprintf(formatbuf, "%%.%dlf", ndigits); - sprintf(buffer, formatbuf, value); - if (exponent < 0) - { - p1 = buffer; - while (*p1 && *p1 != '0') p1++; - while (*p1++) p1[-1] = *p1; - } - } - - /* Last step, convert the locale-specific sign and radix characters - to our own. */ - for (p1 = buffer; *p1; p1++) - { - if (*p1 == *minus) *p1 = '~'; - else if (*p1 == *plus) *p1 = '+'; - else if (*p1 == *radix) *p1 = '.'; - } - - return buffer - space_required; -} - -double -xlfd_round_double(double x) -{ - /* Utility for XLFD users to round numbers to XLFD_NDIGITS - significant digits. How do you round to n significant digits on - a binary machine? */ - -#if defined(i386) || defined(__i386__) || \ - defined(ia64) || defined(__ia64__) || \ - defined(__alpha__) || defined(__alpha) || \ - defined(__hppa__) || \ - defined(__amd64__) || defined(__amd64) || \ - defined(sgi) -#include <float.h> - -/* if we have IEEE 754 fp, we can round to binary digits... */ - -#if (FLT_RADIX == 2) && (DBL_DIG == 15) && (DBL_MANT_DIG == 53) - -#ifndef M_LN2 -#define M_LN2 0.69314718055994530942 -#endif -#ifndef M_LN10 -#define M_LN10 2.30258509299404568402 -#endif - -/* convert # of decimal digits to # of binary digits */ -#define XLFD_NDIGITS_2 ((int)(XLFD_NDIGITS * M_LN10 / M_LN2 + 0.5)) - - union conv_d { - double d; - unsigned char b[8]; - } d; - int i,j,k,d_exp; - - if (x == 0) - return x; - - /* do minor sanity check for IEEE 754 fp and correct byte order */ - d.d = 1.0; - if (sizeof(double) == 8 && d.b[7] == 0x3f && d.b[6] == 0xf0) { - - /* - * this code will round IEEE 754 double to XLFD_NDIGITS_2 binary digits - */ - - d.d = x; - d_exp = (d.b[7] << 4) | (d.b[6] >> 4); - - i = (DBL_MANT_DIG-XLFD_NDIGITS_2) >> 3; - j = 1 << ((DBL_MANT_DIG-XLFD_NDIGITS_2) & 0x07); - for (; i<7; i++) { - k = d.b[i] + j; - d.b[i] = k; - if (k & 0x100) j = 1; - else break; - } - if ((i==7) && ((d.b[6] & 0xf0) != ((d_exp<<4) & 0xf0))) { - /* mantissa overflow: increment exponent */ - d_exp = (d_exp & 0x800 ) | ((d_exp & 0x7ff) + 1); - d.b[7] = d_exp >> 4; - d.b[6] = (d.b[6] & 0x0f) | (d_exp << 4); - } - - i = (DBL_MANT_DIG-XLFD_NDIGITS_2) >> 3; - j = 1 << ((DBL_MANT_DIG-XLFD_NDIGITS_2) & 0x07); - d.b[i] &= ~(j-1); - for (;--i>=0;) d.b[i] = 0; - - return d.d; - } - else -#endif -#endif /* i386 || __i386__ */ - { - /* - * If not IEEE 754: Let printf() do it for you. - */ - - char formatbuf[40], buffer[40]; - - sprintf(formatbuf, "%%.%dlg", XLFD_NDIGITS); - sprintf(buffer, formatbuf, x); - return atof(buffer); - } -} - -static char * -GetMatrix(char *ptr, FontScalablePtr vals, int which) -{ - double *matrix; - - if (which == PIXELSIZE_MASK) - matrix = vals->pixel_matrix; - else if (which == POINTSIZE_MASK) - matrix = vals->point_matrix; - else return (char *)0; - - while (isspace(*ptr)) ptr++; - if (*ptr == '[') - { - /* This is a matrix containing real numbers. It would be nice - to use strtod() or sscanf() to read the numbers, but those - don't handle '~' for minus and we cannot force them to use a - "." for the radix. We'll have to do the hard work ourselves - (in readreal()). */ - - if ((ptr = readreal(++ptr, matrix + 0)) && - (ptr = readreal(ptr, matrix + 1)) && - (ptr = readreal(ptr, matrix + 2)) && - (ptr = readreal(ptr, matrix + 3))) - { - while (isspace(*ptr)) ptr++; - if (*ptr != ']') - ptr = (char *)0; - else - { - ptr++; - while (isspace(*ptr)) ptr++; - if (*ptr == '-') - { - if (which == POINTSIZE_MASK) - vals->values_supplied |= POINTSIZE_ARRAY; - else - vals->values_supplied |= PIXELSIZE_ARRAY; - } - else ptr = (char *)0; - } - } - } - else - { - int value; - if ((ptr = GetInt(ptr, &value))) - { - vals->values_supplied &= ~which; - if (value > 0) - { - matrix[3] = (double)value; - if (which == POINTSIZE_MASK) - { - matrix[3] /= 10.0; - vals->values_supplied |= POINTSIZE_SCALAR; - } - else - vals->values_supplied |= PIXELSIZE_SCALAR; - /* If we're concocting the pixelsize array from a scalar, - we will need to normalize element 0 for the pixel shape. - This is done in FontFileCompleteXLFD(). */ - matrix[0] = matrix[3]; - matrix[1] = matrix[2] = 0.0; - } - else if (value < 0) - { - if (which == POINTSIZE_MASK) - vals->values_supplied |= POINTSIZE_WILDCARD; - else - vals->values_supplied |= PIXELSIZE_WILDCARD; - } - } - } - return ptr; -} - - -static void -append_ranges(char *fname, int nranges, fsRange *ranges) -{ - if (nranges) - { - int i; - - strcat(fname, "["); - for (i = 0; i < nranges && strlen(fname) < 1010; i++) - { - if (i) strcat(fname, " "); - sprintf(fname + strlen(fname), "%d", - minchar(ranges[i])); - if (ranges[i].min_char_low == - ranges[i].max_char_low && - ranges[i].min_char_high == - ranges[i].max_char_high) continue; - sprintf(fname + strlen(fname), "_%d", - maxchar(ranges[i])); - } - strcat(fname, "]"); - } -} - -Bool -FontParseXLFDName(char *fname, FontScalablePtr vals, int subst) -{ - register char *ptr; - register char *ptr1, - *ptr2, - *ptr3, - *ptr4; - register char *ptr5; - FontScalableRec tmpvals; - char replaceChar = '0'; - char tmpBuf[1024]; - int spacingLen; - int l; - char *p; - - bzero(&tmpvals, sizeof(tmpvals)); - if (subst != FONT_XLFD_REPLACE_VALUE) - *vals = tmpvals; - - if (!(*(ptr = fname) == '-' || (*ptr++ == '*' && *ptr == '-')) || /* fndry */ - !(ptr = strchr(ptr + 1, '-')) || /* family_name */ - !(ptr1 = ptr = strchr(ptr + 1, '-')) || /* weight_name */ - !(ptr = strchr(ptr + 1, '-')) || /* slant */ - !(ptr = strchr(ptr + 1, '-')) || /* setwidth_name */ - !(ptr = strchr(ptr + 1, '-')) || /* add_style_name */ - !(ptr = strchr(ptr + 1, '-')) || /* pixel_size */ - !(ptr = GetMatrix(ptr + 1, &tmpvals, PIXELSIZE_MASK)) || - !(ptr2 = ptr = GetMatrix(ptr + 1, &tmpvals, POINTSIZE_MASK)) || - !(ptr = GetInt(ptr + 1, &tmpvals.x)) || /* resolution_x */ - !(ptr3 = ptr = GetInt(ptr + 1, &tmpvals.y)) || /* resolution_y */ - !(ptr4 = ptr = strchr(ptr + 1, '-')) || /* spacing */ - !(ptr5 = ptr = GetInt(ptr + 1, &tmpvals.width)) || /* average_width */ - !(ptr = strchr(ptr + 1, '-')) || /* charset_registry */ - strchr(ptr + 1, '-'))/* charset_encoding */ - return FALSE; - - /* Lop off HP charset subsetting enhancement. Interpreting this - field requires allocating some space in which to return the - results. So, to prevent memory leaks, this procedure will simply - lop off and ignore charset subsetting, and initialize the - relevant vals fields to zero. It's up to the caller to make its - own call to FontParseRanges() if it's interested in the charset - subsetting. */ - - if (subst != FONT_XLFD_REPLACE_NONE && - (p = strchr(strrchr(fname, '-'), '['))) - { - tmpvals.values_supplied |= CHARSUBSET_SPECIFIED; - *p = '\0'; - } - - /* Fill in deprecated fields for the benefit of rasterizers that care - about them. */ - tmpvals.pixel = (tmpvals.pixel_matrix[3] >= 0) ? - (int)(tmpvals.pixel_matrix[3] + .5) : - (int)(tmpvals.pixel_matrix[3] - .5); - tmpvals.point = (tmpvals.point_matrix[3] >= 0) ? - (int)(tmpvals.point_matrix[3] * 10 + .5) : - (int)(tmpvals.point_matrix[3] * 10 - .5); - - spacingLen = ptr4 - ptr3 + 1; - - switch (subst) { - case FONT_XLFD_REPLACE_NONE: - *vals = tmpvals; - break; - case FONT_XLFD_REPLACE_STAR: - replaceChar = '*'; - case FONT_XLFD_REPLACE_ZERO: - strcpy(tmpBuf, ptr2); - ptr5 = tmpBuf + (ptr5 - ptr2); - ptr3 = tmpBuf + (ptr3 - ptr2); - ptr2 = tmpBuf; - ptr = ptr1 + 1; - - ptr = strchr(ptr, '-') + 1; /* skip weight */ - ptr = strchr(ptr, '-') + 1; /* skip slant */ - ptr = strchr(ptr, '-') + 1; /* skip setwidth_name */ - ptr = strchr(ptr, '-') + 1; /* skip add_style_name */ - - if ((ptr - fname) + spacingLen + strlen(ptr5) + 10 >= (unsigned)1024) - return FALSE; - *ptr++ = replaceChar; - *ptr++ = '-'; - *ptr++ = replaceChar; - *ptr++ = '-'; - *ptr++ = '*'; - *ptr++ = '-'; - *ptr++ = '*'; - if (spacingLen > 2) - { - memmove(ptr, ptr3, spacingLen); - ptr += spacingLen; - } - else - { - *ptr++ = '-'; - *ptr++ = '*'; - *ptr++ = '-'; - } - *ptr++ = replaceChar; - strcpy(ptr, ptr5); - *vals = tmpvals; - break; - case FONT_XLFD_REPLACE_VALUE: - if (vals->values_supplied & PIXELSIZE_MASK) - { - tmpvals.values_supplied = - (tmpvals.values_supplied & ~PIXELSIZE_MASK) | - (vals->values_supplied & PIXELSIZE_MASK); - tmpvals.pixel_matrix[0] = vals->pixel_matrix[0]; - tmpvals.pixel_matrix[1] = vals->pixel_matrix[1]; - tmpvals.pixel_matrix[2] = vals->pixel_matrix[2]; - tmpvals.pixel_matrix[3] = vals->pixel_matrix[3]; - } - if (vals->values_supplied & POINTSIZE_MASK) - { - tmpvals.values_supplied = - (tmpvals.values_supplied & ~POINTSIZE_MASK) | - (vals->values_supplied & POINTSIZE_MASK); - tmpvals.point_matrix[0] = vals->point_matrix[0]; - tmpvals.point_matrix[1] = vals->point_matrix[1]; - tmpvals.point_matrix[2] = vals->point_matrix[2]; - tmpvals.point_matrix[3] = vals->point_matrix[3]; - } - if (vals->x >= 0) - tmpvals.x = vals->x; - if (vals->y >= 0) - tmpvals.y = vals->y; - if (vals->width >= 0) - tmpvals.width = vals->width; - else if (vals->width < -1) /* overload: -1 means wildcard */ - tmpvals.width = -vals->width; - - - p = ptr1 + 1; /* weight field */ - l = strchr(p, '-') - p; - sprintf(tmpBuf, "%*.*s", l, l, p); - - p += l + 1; /* slant field */ - l = strchr(p, '-') - p; - sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p); - - p += l + 1; /* setwidth_name */ - l = strchr(p, '-') - p; - sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p); - - p += l + 1; /* add_style_name field */ - l = strchr(p, '-') - p; - sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p); - - strcat(tmpBuf, "-"); - if ((tmpvals.values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY) - { - char buffer[80]; - strcat(tmpBuf, "["); - strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[0], - buffer, 0)); - strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[1], - buffer, 1)); - strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[2], - buffer, 1)); - strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[3], - buffer, 1)); - strcat(tmpBuf, "]"); - } - else - { - sprintf(tmpBuf + strlen(tmpBuf), "%d", - (int)(tmpvals.pixel_matrix[3] + .5)); - } - strcat(tmpBuf, "-"); - if ((tmpvals.values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY) - { - char buffer[80]; - strcat(tmpBuf, "["); - strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[0], - buffer, 0)); - strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[1], - buffer, 1)); - strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[2], - buffer, 1)); - strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[3], - buffer, 1)); - strcat(tmpBuf, "]"); - } - else - { - sprintf(tmpBuf + strlen(tmpBuf), "%d", - (int)(tmpvals.point_matrix[3] * 10.0 + .5)); - } - sprintf(tmpBuf + strlen(tmpBuf), "-%d-%d%*.*s%d%s", - tmpvals.x, tmpvals.y, - spacingLen, spacingLen, ptr3, tmpvals.width, ptr5); - strcpy(ptr1 + 1, tmpBuf); - if ((vals->values_supplied & CHARSUBSET_SPECIFIED) && !vals->nranges) - strcat(fname, "[]"); - else - append_ranges(fname, vals->nranges, vals->ranges); - break; - } - return TRUE; -} - -fsRange *FontParseRanges(char *name, int *nranges) -{ - int n; - unsigned long l; - char *p1, *p2; - fsRange *result = (fsRange *)0; - - name = strchr(name, '-'); - for (n = 1; name && n < 14; n++) - name = strchr(name + 1, '-'); - - *nranges = 0; - if (!name || !(p1 = strchr(name, '['))) return (fsRange *)0; - p1++; - - while (*p1 && *p1 != ']') - { - fsRange thisrange; - - l = strtol(p1, &p2, 0); - if (p2 == p1 || l > 0xffff) break; - thisrange.max_char_low = thisrange.min_char_low = l & 0xff; - thisrange.max_char_high = thisrange.min_char_high = l >> 8; - - p1 = p2; - if (*p1 == ']' || *p1 == ' ') - { - while (*p1 == ' ') p1++; - if (add_range(&thisrange, nranges, &result, TRUE) != Successful) - break; - } - else if (*p1 == '_') - { - l = strtol(++p1, &p2, 0); - if (p2 == p1 || l > 0xffff) break; - thisrange.max_char_low = l & 0xff; - thisrange.max_char_high = l >> 8; - p1 = p2; - if (*p1 == ']' || *p1 == ' ') - { - while (*p1 == ' ') p1++; - if (add_range(&thisrange, nranges, &result, TRUE) != Successful) - break; - } - } - else break; - } - - return result; -} +/*
+
+Copyright 1990, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <float.h>
+#include <X11/fonts/fontmisc.h>
+#include <X11/fonts/fontstruct.h>
+#include <X11/fonts/fontxlfd.h>
+#include <X11/fonts/fontutil.h>
+#include <X11/Xos.h>
+#include <math.h>
+#include <stdlib.h>
+#if defined(sony) && !defined(SYSTYPE_SYSV) && !defined(_SYSTYPE_SYSV)
+#define NO_LOCALE
+#endif
+#ifndef NO_LOCALE
+#include <locale.h>
+#endif
+#include <ctype.h>
+#include <stdio.h> /* for sprintf() */
+
+static char *
+GetInt(char *ptr, int *val)
+{
+ if (*ptr == '*') {
+ *val = -1;
+ ptr++;
+ } else
+ for (*val = 0; *ptr >= '0' && *ptr <= '9';)
+ *val = *val * 10 + *ptr++ - '0';
+ if (*ptr == '-')
+ return ptr;
+ return (char *) 0;
+}
+
+#define minchar(p) ((p).min_char_low + ((p).min_char_high << 8))
+#define maxchar(p) ((p).max_char_low + ((p).max_char_high << 8))
+
+
+#ifndef NO_LOCALE
+static struct lconv *locale = 0;
+#endif
+static char *radix = ".", *plus = "+", *minus = "-";
+
+static char *
+readreal(char *ptr, double *result)
+{
+ char buffer[80], *p1, *p2;
+
+#ifndef NO_LOCALE
+ /* Figure out what symbols apply in this locale */
+
+ if (!locale)
+ {
+ locale = localeconv();
+ if (locale->decimal_point && *locale->decimal_point)
+ radix = locale->decimal_point;
+ if (locale->positive_sign && *locale->positive_sign)
+ plus = locale->positive_sign;
+ if (locale->negative_sign && *locale->negative_sign)
+ minus = locale->negative_sign;
+ }
+#endif
+ /* Copy the first 80 chars of ptr into our local buffer, changing
+ symbols as needed. */
+ for (p1 = ptr, p2 = buffer;
+ *p1 && (p2 - buffer) < sizeof(buffer) - 1;
+ p1++, p2++)
+ {
+ switch(*p1)
+ {
+ case '~': *p2 = *minus; break;
+ case '+': *p2 = *plus; break;
+ case '.': *p2 = *radix; break;
+ default: *p2 = *p1;
+ }
+ }
+ *p2 = 0;
+
+ /* Now we have something that strtod() can interpret... do it. */
+ *result = strtod(buffer, &p1);
+ /* Return NULL if failure, pointer past number if success */
+ return (p1 == buffer) ? (char *)0 : (ptr + (p1 - buffer));
+}
+
+static char *
+xlfd_double_to_text(double value, char *buffer, int space_required)
+{
+ char formatbuf[40];
+ register char *p1;
+ int ndigits, exponent;
+
+#ifndef NO_LOCALE
+ if (!locale)
+ {
+ locale = localeconv();
+ if (locale->decimal_point && *locale->decimal_point)
+ radix = locale->decimal_point;
+ if (locale->positive_sign && *locale->positive_sign)
+ plus = locale->positive_sign;
+ if (locale->negative_sign && *locale->negative_sign)
+ minus = locale->negative_sign;
+ }
+#endif
+ /* Compute a format to use to render the number */
+ sprintf(formatbuf, "%%.%dle", XLFD_NDIGITS);
+
+ if (space_required)
+ *buffer++ = ' ';
+
+ /* Render the number using printf's idea of formatting */
+ sprintf(buffer, formatbuf, value);
+
+ /* Find and read the exponent value */
+ for (p1 = buffer + strlen(buffer);
+ *p1-- != 'e' && p1[1] != 'E';);
+ exponent = atoi(p1 + 2);
+ if (value == 0.0) exponent = 0;
+
+ /* Figure out how many digits are significant */
+ while (p1 >= buffer && (!isdigit(*p1) || *p1 == '0')) p1--;
+ ndigits = 0;
+ while (p1 >= buffer) if (isdigit(*p1--)) ndigits++;
+
+ /* Figure out notation to use */
+ if (exponent >= XLFD_NDIGITS || ndigits - exponent > XLFD_NDIGITS + 1)
+ {
+ /* Scientific */
+ sprintf(formatbuf, "%%.%dle", ndigits - 1);
+ sprintf(buffer, formatbuf, value);
+ }
+ else
+ {
+ /* Fixed */
+ ndigits -= exponent + 1;
+ if (ndigits < 0) ndigits = 0;
+ sprintf(formatbuf, "%%.%dlf", ndigits);
+ sprintf(buffer, formatbuf, value);
+ if (exponent < 0)
+ {
+ p1 = buffer;
+ while (*p1 && *p1 != '0') p1++;
+ while (*p1++) p1[-1] = *p1;
+ }
+ }
+
+ /* Last step, convert the locale-specific sign and radix characters
+ to our own. */
+ for (p1 = buffer; *p1; p1++)
+ {
+ if (*p1 == *minus) *p1 = '~';
+ else if (*p1 == *plus) *p1 = '+';
+ else if (*p1 == *radix) *p1 = '.';
+ }
+
+ return buffer - space_required;
+}
+
+double
+xlfd_round_double(double x)
+{
+ /* Utility for XLFD users to round numbers to XLFD_NDIGITS
+ significant digits. How do you round to n significant digits on
+ a binary machine? */
+
+#if defined(i386) || defined(__i386__) || \
+ defined(ia64) || defined(__ia64__) || \
+ defined(__alpha__) || defined(__alpha) || \
+ defined(__hppa__) || \
+ defined(__amd64__) || defined(__amd64) || \
+ defined(sgi)
+
+/* if we have IEEE 754 fp, we can round to binary digits... */
+
+#if (FLT_RADIX == 2) && (DBL_DIG == 15) && (DBL_MANT_DIG == 53)
+
+#ifndef M_LN2
+#define M_LN2 0.69314718055994530942
+#endif
+#ifndef M_LN10
+#define M_LN10 2.30258509299404568402
+#endif
+
+/* convert # of decimal digits to # of binary digits */
+#define XLFD_NDIGITS_2 ((int)(XLFD_NDIGITS * M_LN10 / M_LN2 + 0.5))
+
+ union conv_d {
+ double d;
+ unsigned char b[8];
+ } d;
+ int i,j,k,d_exp;
+
+ if (x == 0)
+ return x;
+
+ /* do minor sanity check for IEEE 754 fp and correct byte order */
+ d.d = 1.0;
+ if (sizeof(double) == 8 && d.b[7] == 0x3f && d.b[6] == 0xf0) {
+
+ /*
+ * this code will round IEEE 754 double to XLFD_NDIGITS_2 binary digits
+ */
+
+ d.d = x;
+ d_exp = (d.b[7] << 4) | (d.b[6] >> 4);
+
+ i = (DBL_MANT_DIG-XLFD_NDIGITS_2) >> 3;
+ j = 1 << ((DBL_MANT_DIG-XLFD_NDIGITS_2) & 0x07);
+ for (; i<7; i++) {
+ k = d.b[i] + j;
+ d.b[i] = k&0xff;
+ if (k & 0x100) j = 1;
+ else break;
+ }
+ if ((i==7) && ((d.b[6] & 0xf0) != ((d_exp<<4) & 0xf0))) {
+ /* mantissa overflow: increment exponent */
+ d_exp = (d_exp & 0x800 ) | ((d_exp & 0x7ff) + 1);
+ d.b[7] = d_exp >> 4;
+ d.b[6] = (d.b[6] & 0x0f) | (d_exp << 4);
+ }
+
+ i = (DBL_MANT_DIG-XLFD_NDIGITS_2) >> 3;
+ j = 1 << ((DBL_MANT_DIG-XLFD_NDIGITS_2) & 0x07);
+ d.b[i] &= ~(j-1);
+ for (;--i>=0;) d.b[i] = 0;
+
+ return d.d;
+ }
+ else
+#endif
+#endif /* i386 || __i386__ */
+ {
+ /*
+ * If not IEEE 754: Let printf() do it for you.
+ */
+
+ char formatbuf[40], buffer[40];
+
+ sprintf(formatbuf, "%%.%dlg", XLFD_NDIGITS);
+ sprintf(buffer, formatbuf, x);
+ return atof(buffer);
+ }
+}
+
+static char *
+GetMatrix(char *ptr, FontScalablePtr vals, int which)
+{
+ double *matrix;
+
+ if (which == PIXELSIZE_MASK)
+ matrix = vals->pixel_matrix;
+ else if (which == POINTSIZE_MASK)
+ matrix = vals->point_matrix;
+ else return (char *)0;
+
+ while (isspace(*ptr)) ptr++;
+ if (*ptr == '[')
+ {
+ /* This is a matrix containing real numbers. It would be nice
+ to use strtod() or sscanf() to read the numbers, but those
+ don't handle '~' for minus and we cannot force them to use a
+ "." for the radix. We'll have to do the hard work ourselves
+ (in readreal()). */
+
+ if ((ptr = readreal(++ptr, matrix + 0)) &&
+ (ptr = readreal(ptr, matrix + 1)) &&
+ (ptr = readreal(ptr, matrix + 2)) &&
+ (ptr = readreal(ptr, matrix + 3)))
+ {
+ while (isspace(*ptr)) ptr++;
+ if (*ptr != ']')
+ ptr = (char *)0;
+ else
+ {
+ ptr++;
+ while (isspace(*ptr)) ptr++;
+ if (*ptr == '-')
+ {
+ if (which == POINTSIZE_MASK)
+ vals->values_supplied |= POINTSIZE_ARRAY;
+ else
+ vals->values_supplied |= PIXELSIZE_ARRAY;
+ }
+ else ptr = (char *)0;
+ }
+ }
+ }
+ else
+ {
+ int value;
+ if ((ptr = GetInt(ptr, &value)))
+ {
+ vals->values_supplied &= ~which;
+ if (value > 0)
+ {
+ matrix[3] = (double)value;
+ if (which == POINTSIZE_MASK)
+ {
+ matrix[3] /= 10.0;
+ vals->values_supplied |= POINTSIZE_SCALAR;
+ }
+ else
+ vals->values_supplied |= PIXELSIZE_SCALAR;
+ /* If we're concocting the pixelsize array from a scalar,
+ we will need to normalize element 0 for the pixel shape.
+ This is done in FontFileCompleteXLFD(). */
+ matrix[0] = matrix[3];
+ matrix[1] = matrix[2] = 0.0;
+ }
+ else if (value < 0)
+ {
+ if (which == POINTSIZE_MASK)
+ vals->values_supplied |= POINTSIZE_WILDCARD;
+ else
+ vals->values_supplied |= PIXELSIZE_WILDCARD;
+ }
+ }
+ }
+ return ptr;
+}
+
+
+static void
+append_ranges(char *fname, int nranges, fsRange *ranges)
+{
+ if (nranges)
+ {
+ int i;
+
+ strcat(fname, "[");
+ for (i = 0; i < nranges && strlen(fname) < 1010; i++)
+ {
+ if (i) strcat(fname, " ");
+ sprintf(fname + strlen(fname), "%d",
+ minchar(ranges[i]));
+ if (ranges[i].min_char_low ==
+ ranges[i].max_char_low &&
+ ranges[i].min_char_high ==
+ ranges[i].max_char_high) continue;
+ sprintf(fname + strlen(fname), "_%d",
+ maxchar(ranges[i]));
+ }
+ strcat(fname, "]");
+ }
+}
+
+Bool
+FontParseXLFDName(char *fname, FontScalablePtr vals, int subst)
+{
+ register char *ptr;
+ register char *ptr1,
+ *ptr2,
+ *ptr3,
+ *ptr4;
+ register char *ptr5;
+ FontScalableRec tmpvals;
+ char replaceChar = '0';
+ char tmpBuf[1024];
+ int spacingLen;
+ int l;
+ char *p;
+
+ bzero(&tmpvals, sizeof(tmpvals));
+ if (subst != FONT_XLFD_REPLACE_VALUE)
+ *vals = tmpvals;
+
+ if (!(*(ptr = fname) == '-' || (*ptr++ == '*' && *ptr == '-')) || /* fndry */
+ !(ptr = strchr(ptr + 1, '-')) || /* family_name */
+ !(ptr1 = ptr = strchr(ptr + 1, '-')) || /* weight_name */
+ !(ptr = strchr(ptr + 1, '-')) || /* slant */
+ !(ptr = strchr(ptr + 1, '-')) || /* setwidth_name */
+ !(ptr = strchr(ptr + 1, '-')) || /* add_style_name */
+ !(ptr = strchr(ptr + 1, '-')) || /* pixel_size */
+ !(ptr = GetMatrix(ptr + 1, &tmpvals, PIXELSIZE_MASK)) ||
+ !(ptr2 = ptr = GetMatrix(ptr + 1, &tmpvals, POINTSIZE_MASK)) ||
+ !(ptr = GetInt(ptr + 1, &tmpvals.x)) || /* resolution_x */
+ !(ptr3 = ptr = GetInt(ptr + 1, &tmpvals.y)) || /* resolution_y */
+ !(ptr4 = ptr = strchr(ptr + 1, '-')) || /* spacing */
+ !(ptr5 = ptr = GetInt(ptr + 1, &tmpvals.width)) || /* average_width */
+ !(ptr = strchr(ptr + 1, '-')) || /* charset_registry */
+ strchr(ptr + 1, '-'))/* charset_encoding */
+ return FALSE;
+
+ /* Lop off HP charset subsetting enhancement. Interpreting this
+ field requires allocating some space in which to return the
+ results. So, to prevent memory leaks, this procedure will simply
+ lop off and ignore charset subsetting, and initialize the
+ relevant vals fields to zero. It's up to the caller to make its
+ own call to FontParseRanges() if it's interested in the charset
+ subsetting. */
+
+ if (subst != FONT_XLFD_REPLACE_NONE &&
+ (p = strchr(strrchr(fname, '-'), '[')))
+ {
+ tmpvals.values_supplied |= CHARSUBSET_SPECIFIED;
+ *p = '\0';
+ }
+
+ /* Fill in deprecated fields for the benefit of rasterizers that care
+ about them. */
+ tmpvals.pixel = (tmpvals.pixel_matrix[3] >= 0) ?
+ (int)(tmpvals.pixel_matrix[3] + .5) :
+ (int)(tmpvals.pixel_matrix[3] - .5);
+ tmpvals.point = (tmpvals.point_matrix[3] >= 0) ?
+ (int)(tmpvals.point_matrix[3] * 10 + .5) :
+ (int)(tmpvals.point_matrix[3] * 10 - .5);
+
+ spacingLen = ptr4 - ptr3 + 1;
+
+ switch (subst) {
+ case FONT_XLFD_REPLACE_NONE:
+ *vals = tmpvals;
+ break;
+ case FONT_XLFD_REPLACE_STAR:
+ replaceChar = '*';
+ case FONT_XLFD_REPLACE_ZERO:
+ strcpy(tmpBuf, ptr2);
+ ptr5 = tmpBuf + (ptr5 - ptr2);
+ ptr3 = tmpBuf + (ptr3 - ptr2);
+ ptr2 = tmpBuf;
+ ptr = ptr1 + 1;
+
+ ptr = strchr(ptr, '-') + 1; /* skip weight */
+ ptr = strchr(ptr, '-') + 1; /* skip slant */
+ ptr = strchr(ptr, '-') + 1; /* skip setwidth_name */
+ ptr = strchr(ptr, '-') + 1; /* skip add_style_name */
+
+ if ((ptr - fname) + spacingLen + strlen(ptr5) + 10 >= (unsigned)1024)
+ return FALSE;
+ *ptr++ = replaceChar;
+ *ptr++ = '-';
+ *ptr++ = replaceChar;
+ *ptr++ = '-';
+ *ptr++ = '*';
+ *ptr++ = '-';
+ *ptr++ = '*';
+ if (spacingLen > 2)
+ {
+ memmove(ptr, ptr3, spacingLen);
+ ptr += spacingLen;
+ }
+ else
+ {
+ *ptr++ = '-';
+ *ptr++ = '*';
+ *ptr++ = '-';
+ }
+ *ptr++ = replaceChar;
+ strcpy(ptr, ptr5);
+ *vals = tmpvals;
+ break;
+ case FONT_XLFD_REPLACE_VALUE:
+ if (vals->values_supplied & PIXELSIZE_MASK)
+ {
+ tmpvals.values_supplied =
+ (tmpvals.values_supplied & ~PIXELSIZE_MASK) |
+ (vals->values_supplied & PIXELSIZE_MASK);
+ tmpvals.pixel_matrix[0] = vals->pixel_matrix[0];
+ tmpvals.pixel_matrix[1] = vals->pixel_matrix[1];
+ tmpvals.pixel_matrix[2] = vals->pixel_matrix[2];
+ tmpvals.pixel_matrix[3] = vals->pixel_matrix[3];
+ }
+ if (vals->values_supplied & POINTSIZE_MASK)
+ {
+ tmpvals.values_supplied =
+ (tmpvals.values_supplied & ~POINTSIZE_MASK) |
+ (vals->values_supplied & POINTSIZE_MASK);
+ tmpvals.point_matrix[0] = vals->point_matrix[0];
+ tmpvals.point_matrix[1] = vals->point_matrix[1];
+ tmpvals.point_matrix[2] = vals->point_matrix[2];
+ tmpvals.point_matrix[3] = vals->point_matrix[3];
+ }
+ if (vals->x >= 0)
+ tmpvals.x = vals->x;
+ if (vals->y >= 0)
+ tmpvals.y = vals->y;
+ if (vals->width >= 0)
+ tmpvals.width = vals->width;
+ else if (vals->width < -1) /* overload: -1 means wildcard */
+ tmpvals.width = -vals->width;
+
+
+ p = ptr1 + 1; /* weight field */
+ l = strchr(p, '-') - p;
+ sprintf(tmpBuf, "%*.*s", l, l, p);
+
+ p += l + 1; /* slant field */
+ l = strchr(p, '-') - p;
+ sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p);
+
+ p += l + 1; /* setwidth_name */
+ l = strchr(p, '-') - p;
+ sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p);
+
+ p += l + 1; /* add_style_name field */
+ l = strchr(p, '-') - p;
+ sprintf(tmpBuf + strlen(tmpBuf), "-%*.*s", l, l, p);
+
+ strcat(tmpBuf, "-");
+ if ((tmpvals.values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY)
+ {
+ char buffer[80];
+ strcat(tmpBuf, "[");
+ strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[0],
+ buffer, 0));
+ strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[1],
+ buffer, 1));
+ strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[2],
+ buffer, 1));
+ strcat(tmpBuf, xlfd_double_to_text(tmpvals.pixel_matrix[3],
+ buffer, 1));
+ strcat(tmpBuf, "]");
+ }
+ else
+ {
+ sprintf(tmpBuf + strlen(tmpBuf), "%d",
+ (int)(tmpvals.pixel_matrix[3] + .5));
+ }
+ strcat(tmpBuf, "-");
+ if ((tmpvals.values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY)
+ {
+ char buffer[80];
+ strcat(tmpBuf, "[");
+ strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[0],
+ buffer, 0));
+ strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[1],
+ buffer, 1));
+ strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[2],
+ buffer, 1));
+ strcat(tmpBuf, xlfd_double_to_text(tmpvals.point_matrix[3],
+ buffer, 1));
+ strcat(tmpBuf, "]");
+ }
+ else
+ {
+ sprintf(tmpBuf + strlen(tmpBuf), "%d",
+ (int)(tmpvals.point_matrix[3] * 10.0 + .5));
+ }
+ sprintf(tmpBuf + strlen(tmpBuf), "-%d-%d%*.*s%d%s",
+ tmpvals.x, tmpvals.y,
+ spacingLen, spacingLen, ptr3, tmpvals.width, ptr5);
+ strcpy(ptr1 + 1, tmpBuf);
+ if ((vals->values_supplied & CHARSUBSET_SPECIFIED) && !vals->nranges)
+ strcat(fname, "[]");
+ else
+ append_ranges(fname, vals->nranges, vals->ranges);
+ break;
+ }
+ return TRUE;
+}
+
+fsRange *FontParseRanges(char *name, int *nranges)
+{
+ int n;
+ unsigned long l;
+ char *p1, *p2;
+ fsRange *result = (fsRange *)0;
+
+ name = strchr(name, '-');
+ for (n = 1; name && n < 14; n++)
+ name = strchr(name + 1, '-');
+
+ *nranges = 0;
+ if (!name || !(p1 = strchr(name, '['))) return (fsRange *)0;
+ p1++;
+
+ while (*p1 && *p1 != ']')
+ {
+ fsRange thisrange;
+
+ l = strtol(p1, &p2, 0);
+ if (p2 == p1 || l > 0xffff) break;
+ thisrange.max_char_low = thisrange.min_char_low = l & 0xff;
+ thisrange.max_char_high = thisrange.min_char_high = l >> 8;
+
+ p1 = p2;
+ if (*p1 == ']' || *p1 == ' ')
+ {
+ while (*p1 == ' ') p1++;
+ if (add_range(&thisrange, nranges, &result, TRUE) != Successful)
+ break;
+ }
+ else if (*p1 == '_')
+ {
+ l = strtol(++p1, &p2, 0);
+ if (p2 == p1 || l > 0xffff) break;
+ thisrange.max_char_low = l & 0xff;
+ thisrange.max_char_high = l >> 8;
+ p1 = p2;
+ if (*p1 == ']' || *p1 == ' ')
+ {
+ while (*p1 == ' ') p1++;
+ if (add_range(&thisrange, nranges, &result, TRUE) != Successful)
+ break;
+ }
+ }
+ else break;
+ }
+
+ return result;
+}
diff --git a/libXfont/src/util/format.c b/libXfont/src/util/format.c index f5424fe41..60afac9b8 100644 --- a/libXfont/src/util/format.c +++ b/libXfont/src/util/format.c @@ -1,124 +1,124 @@ -/* - * Copyright 1990, 1991 Network Computing Devices; - * Portions Copyright 1987 by Digital Equipment Corporation - * - * 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, and that the names of Network Computing Devices or Digital - * not be used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. Network Computing - * Devices and Digital make no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES OR DIGITAL BE - * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - -Copyright 1987, 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. - -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/FSproto.h> -#include <X11/fonts/font.h> -#include <X11/fonts/fontstruct.h> -#include <X11/fonts/fontutil.h> - -int -CheckFSFormat(fsBitmapFormat format, - fsBitmapFormatMask fmask, - int *bit_order, - int *byte_order, - int *scan, - int *glyph, - int *image) -{ - /* convert format to what the low levels want */ - if (fmask & BitmapFormatMaskBit) { - *bit_order = format & BitmapFormatBitOrderMask; - *bit_order = (*bit_order == BitmapFormatBitOrderMSB) - ? MSBFirst : LSBFirst; - } - if (fmask & BitmapFormatMaskByte) { - *byte_order = format & BitmapFormatByteOrderMask; - *byte_order = (*byte_order == BitmapFormatByteOrderMSB) - ? MSBFirst : LSBFirst; - } - if (fmask & BitmapFormatMaskScanLineUnit) { - *scan = format & BitmapFormatScanlineUnitMask; - /* convert byte paddings into byte counts */ - switch (*scan) { - case BitmapFormatScanlineUnit8: - *scan = 1; - break; - case BitmapFormatScanlineUnit16: - *scan = 2; - break; - case BitmapFormatScanlineUnit32: - *scan = 4; - break; - default: - return BadFontFormat; - } - } - if (fmask & BitmapFormatMaskScanLinePad) { - *glyph = format & BitmapFormatScanlinePadMask; - /* convert byte paddings into byte counts */ - switch (*glyph) { - case BitmapFormatScanlinePad8: - *glyph = 1; - break; - case BitmapFormatScanlinePad16: - *glyph = 2; - break; - case BitmapFormatScanlinePad32: - *glyph = 4; - break; - default: - return BadFontFormat; - } - } - if (fmask & BitmapFormatMaskImageRectangle) { - *image = format & BitmapFormatImageRectMask; - - if (*image != BitmapFormatImageRectMin && - *image != BitmapFormatImageRectMaxWidth && - *image != BitmapFormatImageRectMax) - return BadFontFormat; - } - return Successful; -} +/*
+ * Copyright 1990, 1991 Network Computing Devices;
+ * Portions Copyright 1987 by Digital Equipment Corporation
+ *
+ * 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, and that the names of Network Computing Devices or Digital
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. Network Computing
+ * Devices and Digital make no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES OR DIGITAL BE
+ * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+
+Copyright 1987, 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.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/FSproto.h>
+#include <X11/fonts/font.h>
+#include <X11/fonts/fontstruct.h>
+#include <X11/fonts/fontutil.h>
+
+int
+CheckFSFormat(fsBitmapFormat format,
+ fsBitmapFormatMask fmask,
+ int *bit_order,
+ int *byte_order,
+ int *scan,
+ int *glyph,
+ int *image)
+{
+ /* convert format to what the low levels want */
+ if (fmask & BitmapFormatMaskBit) {
+ *bit_order = format & BitmapFormatBitOrderMask;
+ *bit_order = (*bit_order == BitmapFormatBitOrderMSB)
+ ? MSBFirst : LSBFirst;
+ }
+ if (fmask & BitmapFormatMaskByte) {
+ *byte_order = format & BitmapFormatByteOrderMask;
+ *byte_order = (*byte_order == BitmapFormatByteOrderMSB)
+ ? MSBFirst : LSBFirst;
+ }
+ if (fmask & BitmapFormatMaskScanLineUnit) {
+ *scan = format & BitmapFormatScanlineUnitMask;
+ /* convert byte paddings into byte counts */
+ switch (*scan) {
+ case BitmapFormatScanlineUnit8:
+ *scan = 1;
+ break;
+ case BitmapFormatScanlineUnit16:
+ *scan = 2;
+ break;
+ case BitmapFormatScanlineUnit32:
+ *scan = 4;
+ break;
+ default:
+ return BadFontFormat;
+ }
+ }
+ if (fmask & BitmapFormatMaskScanLinePad) {
+ *glyph = format & BitmapFormatScanlinePadMask;
+ /* convert byte paddings into byte counts */
+ switch (*glyph) {
+ case BitmapFormatScanlinePad8:
+ *glyph = 1;
+ break;
+ case BitmapFormatScanlinePad16:
+ *glyph = 2;
+ break;
+ case BitmapFormatScanlinePad32:
+ *glyph = 4;
+ break;
+ default:
+ return BadFontFormat;
+ }
+ }
+ if (fmask & BitmapFormatMaskImageRectangle) {
+ *image = format & BitmapFormatImageRectMask;
+
+ if (*image != BitmapFormatImageRectMin &&
+ *image != BitmapFormatImageRectMaxWidth &&
+ *image != BitmapFormatImageRectMax)
+ return BadFontFormat;
+ }
+ return Successful;
+}
diff --git a/libXfont/src/util/makefile b/libXfont/src/util/makefile new file mode 100644 index 000000000..53b5560a3 --- /dev/null +++ b/libXfont/src/util/makefile @@ -0,0 +1,17 @@ +LIBRARY = libutil + +INCLUDES += ../stubs + +INCLUDES := ../.. $(INCLUDES) + +CSRCS = \ + atom.c \ + fontaccel.c \ + fontnames.c \ + fontutil.c \ + fontxlfd.c \ + format.c \ + miscutil.c \ + patcache.c \ + private.c \ + utilbitmap.c diff --git a/libXfont/src/util/miscutil.c b/libXfont/src/util/miscutil.c index 7173d3640..9e6cc3ffa 100644 --- a/libXfont/src/util/miscutil.c +++ b/libXfont/src/util/miscutil.c @@ -1,61 +1,61 @@ -/* - -Copyright 1991, 1994, 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. - -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/Xosdefs.h> -#include <stdlib.h> -#include <X11/fonts/fontmisc.h> -#include "stubs.h" - -#define XK_LATIN1 -#include <X11/keysymdef.h> - - -#ifdef __SUNPRO_C -#pragma weak serverGeneration -#pragma weak register_fpe_functions -#endif - -extern void BuiltinRegisterFpeFunctions(void); - -#ifndef NO_WEAK_SYMBOLS -/* make sure everything initializes themselves at least once */ -weak long serverGeneration = 1; -#endif - -weak void -register_fpe_functions (void) -{ - BuiltinRegisterFpeFunctions(); - FontFileRegisterFpeFunctions(); -#ifdef XFONT_FC - fs_register_fpe_functions(); -#endif -} +/*
+
+Copyright 1991, 1994, 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.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/Xosdefs.h>
+#include <stdlib.h>
+#include <X11/fonts/fontmisc.h>
+#include "stubs.h"
+
+#define XK_LATIN1
+#include <X11/keysymdef.h>
+
+
+#ifdef __SUNPRO_C
+#pragma weak serverGeneration
+#pragma weak register_fpe_functions
+#endif
+
+extern void BuiltinRegisterFpeFunctions(void);
+
+#ifndef NO_WEAK_SYMBOLS
+/* make sure everything initializes themselves at least once */
+weak long serverGeneration = 1;
+#endif
+
+weak void
+register_fpe_functions (void)
+{
+ BuiltinRegisterFpeFunctions();
+ FontFileRegisterFpeFunctions();
+#ifdef XFONT_FC
+ fs_register_fpe_functions();
+#endif
+}
diff --git a/libXfont/src/util/patcache.c b/libXfont/src/util/patcache.c index 548105a00..f1a203683 100644 --- a/libXfont/src/util/patcache.c +++ b/libXfont/src/util/patcache.c @@ -1,218 +1,218 @@ -/* - -Copyright 1991, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fontmisc.h> -#include <X11/fonts/fontstruct.h> - -/* - * Static sized hash table for looking up font name patterns - * - * LRU entries, reusing old entries - */ - -#define NBUCKETS 16 -#define NENTRIES 64 - -#define UNSET (NENTRIES+1) - -typedef unsigned char EntryPtr; - -typedef struct _FontPatternCacheEntry { - struct _FontPatternCacheEntry *next, **prev; - short patlen; - char *pattern; - int hash; - FontPtr pFont; /* associated font */ -} FontPatternCacheEntryRec, *FontPatternCacheEntryPtr; - -typedef struct _FontPatternCache { - FontPatternCacheEntryPtr buckets[NBUCKETS]; - FontPatternCacheEntryRec entries[NENTRIES]; - FontPatternCacheEntryPtr free; -} FontPatternCacheRec; - -/* Empty cache (for rehash) */ -void -EmptyFontPatternCache (FontPatternCachePtr cache) -{ - int i; - - for (i = 0; i < NBUCKETS; i++) - cache->buckets[i] = 0; - for (i = 0; i < NENTRIES; i++) - { - cache->entries[i].next = &cache->entries[i+1]; - cache->entries[i].prev = 0; - cache->entries[i].pFont = 0; - free (cache->entries[i].pattern); - cache->entries[i].pattern = 0; - cache->entries[i].patlen = 0; - } - cache->free = &cache->entries[0]; - cache->entries[NENTRIES - 1].next = 0; -} - -/* Create and initialize cache */ -FontPatternCachePtr -MakeFontPatternCache (void) -{ - FontPatternCachePtr cache; - int i; - cache = malloc (sizeof *cache); - if (!cache) - return 0; - for (i = 0; i < NENTRIES; i++) { - cache->entries[i].patlen = 0; - cache->entries[i].pattern = 0; - cache->entries[i].pFont = 0; - } - EmptyFontPatternCache (cache); - return cache; -} - -/* toss cache */ -void -FreeFontPatternCache (FontPatternCachePtr cache) -{ - int i; - - for (i = 0; i < NENTRIES; i++) - free (cache->entries[i].pattern); - free (cache); -} - -/* compute id for string */ -static int -Hash (const char *string, int len) -{ - int hash; - - hash = 0; - while (len--) - hash = (hash << 1) ^ *string++; - if (hash < 0) - hash = -hash; - return hash; -} - -/* add entry */ -void -CacheFontPattern (FontPatternCachePtr cache, - char *pattern, - int patlen, - FontPtr pFont) -{ - FontPatternCacheEntryPtr e; - char *newpat; - int i; - - newpat = malloc (patlen); - if (!newpat) - return; - if (cache->free) - { - e = cache->free; - cache->free = e->next; - } - else - { - i = rand (); - if (i < 0) - i = -i; - i %= NENTRIES; - e = &cache->entries[i]; - if (e->next) - e->next->prev = e->prev; - *e->prev = e->next; - free (e->pattern); - } - /* set pattern */ - memcpy (newpat, pattern, patlen); - e->pattern = newpat; - e->patlen = patlen; - /* link to new hash chain */ - e->hash = Hash (pattern, patlen); - i = e->hash % NBUCKETS; - e->next = cache->buckets[i]; - if (e->next) - e->next->prev = &(e->next); - cache->buckets[i] = e; - e->prev = &(cache->buckets[i]); - e->pFont = pFont; -} - -/* find matching entry */ -FontPtr -FindCachedFontPattern (FontPatternCachePtr cache, - char *pattern, - int patlen) -{ - int hash; - int i; - FontPatternCacheEntryPtr e; - - hash = Hash (pattern, patlen); - i = hash % NBUCKETS; - for (e = cache->buckets[i]; e; e = e->next) - { - if (e->patlen == patlen && e->hash == hash && - !memcmp (e->pattern, pattern, patlen)) - { - return e->pFont; - } - } - return 0; -} - -void -RemoveCachedFontPattern (FontPatternCachePtr cache, - FontPtr pFont) -{ - FontPatternCacheEntryPtr e; - int i; - - for (i = 0; i < NENTRIES; i++) - { - if ((e = &cache->entries[i])->pFont == pFont) - { - e->pFont = 0; - if (e->next) - e->next->prev = e->prev; - *e->prev = e->next; - e->next = cache->free; - cache->free = e; - free (e->pattern); - e->pattern = 0; - } - } -} +/*
+
+Copyright 1991, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fontmisc.h>
+#include <X11/fonts/fontstruct.h>
+
+/*
+ * Static sized hash table for looking up font name patterns
+ *
+ * LRU entries, reusing old entries
+ */
+
+#define NBUCKETS 16
+#define NENTRIES 64
+
+#define UNSET (NENTRIES+1)
+
+typedef unsigned char EntryPtr;
+
+typedef struct _FontPatternCacheEntry {
+ struct _FontPatternCacheEntry *next, **prev;
+ short patlen;
+ char *pattern;
+ int hash;
+ FontPtr pFont; /* associated font */
+} FontPatternCacheEntryRec, *FontPatternCacheEntryPtr;
+
+typedef struct _FontPatternCache {
+ FontPatternCacheEntryPtr buckets[NBUCKETS];
+ FontPatternCacheEntryRec entries[NENTRIES];
+ FontPatternCacheEntryPtr free;
+} FontPatternCacheRec;
+
+/* Empty cache (for rehash) */
+void
+EmptyFontPatternCache (FontPatternCachePtr cache)
+{
+ int i;
+
+ for (i = 0; i < NBUCKETS; i++)
+ cache->buckets[i] = 0;
+ for (i = 0; i < NENTRIES; i++)
+ {
+ cache->entries[i].next = &cache->entries[i+1];
+ cache->entries[i].prev = 0;
+ cache->entries[i].pFont = 0;
+ free (cache->entries[i].pattern);
+ cache->entries[i].pattern = 0;
+ cache->entries[i].patlen = 0;
+ }
+ cache->free = &cache->entries[0];
+ cache->entries[NENTRIES - 1].next = 0;
+}
+
+/* Create and initialize cache */
+FontPatternCachePtr
+MakeFontPatternCache (void)
+{
+ FontPatternCachePtr cache;
+ int i;
+ cache = malloc (sizeof *cache);
+ if (!cache)
+ return 0;
+ for (i = 0; i < NENTRIES; i++) {
+ cache->entries[i].patlen = 0;
+ cache->entries[i].pattern = 0;
+ cache->entries[i].pFont = 0;
+ }
+ EmptyFontPatternCache (cache);
+ return cache;
+}
+
+/* toss cache */
+void
+FreeFontPatternCache (FontPatternCachePtr cache)
+{
+ int i;
+
+ for (i = 0; i < NENTRIES; i++)
+ free (cache->entries[i].pattern);
+ free (cache);
+}
+
+/* compute id for string */
+static int
+Hash (const char *string, int len)
+{
+ int hash;
+
+ hash = 0;
+ while (len--)
+ hash = (hash << 1) ^ *string++;
+ if (hash < 0)
+ hash = -hash;
+ return hash;
+}
+
+/* add entry */
+void
+CacheFontPattern (FontPatternCachePtr cache,
+ char *pattern,
+ int patlen,
+ FontPtr pFont)
+{
+ FontPatternCacheEntryPtr e;
+ char *newpat;
+ int i;
+
+ newpat = malloc (patlen);
+ if (!newpat)
+ return;
+ if (cache->free)
+ {
+ e = cache->free;
+ cache->free = e->next;
+ }
+ else
+ {
+ i = rand ();
+ if (i < 0)
+ i = -i;
+ i %= NENTRIES;
+ e = &cache->entries[i];
+ if (e->next)
+ e->next->prev = e->prev;
+ *e->prev = e->next;
+ free (e->pattern);
+ }
+ /* set pattern */
+ memcpy (newpat, pattern, patlen);
+ e->pattern = newpat;
+ e->patlen = patlen;
+ /* link to new hash chain */
+ e->hash = Hash (pattern, patlen);
+ i = e->hash % NBUCKETS;
+ e->next = cache->buckets[i];
+ if (e->next)
+ e->next->prev = &(e->next);
+ cache->buckets[i] = e;
+ e->prev = &(cache->buckets[i]);
+ e->pFont = pFont;
+}
+
+/* find matching entry */
+FontPtr
+FindCachedFontPattern (FontPatternCachePtr cache,
+ char *pattern,
+ int patlen)
+{
+ int hash;
+ int i;
+ FontPatternCacheEntryPtr e;
+
+ hash = Hash (pattern, patlen);
+ i = hash % NBUCKETS;
+ for (e = cache->buckets[i]; e; e = e->next)
+ {
+ if (e->patlen == patlen && e->hash == hash &&
+ !memcmp (e->pattern, pattern, patlen))
+ {
+ return e->pFont;
+ }
+ }
+ return 0;
+}
+
+void
+RemoveCachedFontPattern (FontPatternCachePtr cache,
+ FontPtr pFont)
+{
+ FontPatternCacheEntryPtr e;
+ int i;
+
+ for (i = 0; i < NENTRIES; i++)
+ {
+ if ((e = &cache->entries[i])->pFont == pFont)
+ {
+ e->pFont = 0;
+ if (e->next)
+ e->next->prev = e->prev;
+ *e->prev = e->next;
+ e->next = cache->free;
+ cache->free = e;
+ free (e->pattern);
+ e->pattern = 0;
+ }
+ }
+}
diff --git a/libXfont/src/util/private.c b/libXfont/src/util/private.c index 36715b1fa..f28ec6ab5 100644 --- a/libXfont/src/util/private.c +++ b/libXfont/src/util/private.c @@ -1,105 +1,105 @@ -/* - -Copyright 1991, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fontmisc.h> -#include <X11/fonts/fontstruct.h> - -static int _FontPrivateAllocateIndex = 0; - -int -AllocateFontPrivateIndex (void) -{ - return _FontPrivateAllocateIndex++; -} - -FontPtr -CreateFontRec (void) -{ - FontPtr pFont; - int size; - - size = sizeof(FontRec) + (sizeof(pointer) * _FontPrivateAllocateIndex); - - pFont = malloc(size); - - if(pFont) { - bzero((char*)pFont, size); - pFont->maxPrivate = _FontPrivateAllocateIndex - 1; - if(_FontPrivateAllocateIndex) - pFont->devPrivates = (pointer)(&pFont[1]); - } - - return pFont; -} - -void -DestroyFontRec (FontPtr pFont) -{ - if (pFont->devPrivates && pFont->devPrivates != (pointer)(&pFont[1])) - free(pFont->devPrivates); - free(pFont); -} - -void -ResetFontPrivateIndex (void) -{ - _FontPrivateAllocateIndex = 0; -} - -Bool -_FontSetNewPrivate (FontPtr pFont, int n, pointer ptr) -{ - pointer *new; - - if (n > pFont->maxPrivate) { - if (pFont->devPrivates && pFont->devPrivates != (pointer)(&pFont[1])) { - new = realloc (pFont->devPrivates, (n + 1) * sizeof (pointer)); - if (!new) - return FALSE; - } else { - /* omg realloc */ - new = malloc ((n + 1) * sizeof (pointer)); - if (!new) - return FALSE; - if (pFont->devPrivates) - memcpy (new, pFont->devPrivates, (pFont->maxPrivate + 1) * sizeof (pointer)); - } - pFont->devPrivates = new; - /* zero out new, uninitialized privates */ - while(++pFont->maxPrivate < n) - pFont->devPrivates[pFont->maxPrivate] = (pointer)0; - } - pFont->devPrivates[n] = ptr; - return TRUE; -} - +/*
+
+Copyright 1991, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fontmisc.h>
+#include <X11/fonts/fontstruct.h>
+
+static int _FontPrivateAllocateIndex = 0;
+
+int
+AllocateFontPrivateIndex (void)
+{
+ return _FontPrivateAllocateIndex++;
+}
+
+FontPtr
+CreateFontRec (void)
+{
+ FontPtr pFont;
+ int size;
+
+ size = sizeof(FontRec) + (sizeof(pointer) * _FontPrivateAllocateIndex);
+
+ pFont = malloc(size);
+
+ if(pFont) {
+ bzero((char*)pFont, size);
+ pFont->maxPrivate = _FontPrivateAllocateIndex - 1;
+ if(_FontPrivateAllocateIndex)
+ pFont->devPrivates = (pointer)(&pFont[1]);
+ }
+
+ return pFont;
+}
+
+void
+DestroyFontRec (FontPtr pFont)
+{
+ if (pFont->devPrivates && pFont->devPrivates != (pointer)(&pFont[1]))
+ free(pFont->devPrivates);
+ free(pFont);
+}
+
+void
+ResetFontPrivateIndex (void)
+{
+ _FontPrivateAllocateIndex = 0;
+}
+
+Bool
+_FontSetNewPrivate (FontPtr pFont, int n, pointer ptr)
+{
+ pointer *new;
+
+ if (n > pFont->maxPrivate) {
+ if (pFont->devPrivates && pFont->devPrivates != (pointer)(&pFont[1])) {
+ new = realloc (pFont->devPrivates, (n + 1) * sizeof (pointer));
+ if (!new)
+ return FALSE;
+ } else {
+ /* omg realloc */
+ new = malloc ((n + 1) * sizeof (pointer));
+ if (!new)
+ return FALSE;
+ if (pFont->devPrivates)
+ memcpy (new, pFont->devPrivates, (pFont->maxPrivate + 1) * sizeof (pointer));
+ }
+ pFont->devPrivates = new;
+ /* zero out new, uninitialized privates */
+ while(++pFont->maxPrivate < n)
+ pFont->devPrivates[pFont->maxPrivate] = (pointer)0;
+ }
+ pFont->devPrivates[n] = ptr;
+ return TRUE;
+}
+
diff --git a/libXfont/src/util/utilbitmap.c b/libXfont/src/util/utilbitmap.c index 5feb2d133..070cd5801 100644 --- a/libXfont/src/util/utilbitmap.c +++ b/libXfont/src/util/utilbitmap.c @@ -1,185 +1,185 @@ -/* - -Copyright 1990, 1994, 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. - -*/ - -/* - * Author: Keith Packard, MIT X Consortium - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <X11/fonts/fontmisc.h> - -/* Utility functions for reformating font bitmaps */ - -static const unsigned char _reverse_byte[0x100] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff -}; - -/* - * Invert bit order within each BYTE of an array. - */ -void -BitOrderInvert(unsigned char *buf, int nbytes) -{ - const unsigned char *rev = _reverse_byte; - - for (; --nbytes >= 0; buf++) - *buf = rev[*buf]; -} - -/* - * Invert byte order within each 16-bits of an array. - */ -void -TwoByteSwap(unsigned char *buf, int nbytes) -{ - unsigned char c; - - for (; nbytes > 0; nbytes -= 2, buf += 2) - { - c = buf[0]; - buf[0] = buf[1]; - buf[1] = c; - } -} - -/* - * Invert byte order within each 32-bits of an array. - */ -void -FourByteSwap(unsigned char *buf, int nbytes) -{ - unsigned char c; - - for (; nbytes > 0; nbytes -= 4, buf += 4) - { - c = buf[0]; - buf[0] = buf[3]; - buf[3] = c; - c = buf[1]; - buf[1] = buf[2]; - buf[2] = c; - } -} - -/* - * Repad a bitmap - */ - -int -RepadBitmap (char *pSrc, char *pDst, - unsigned int srcPad, unsigned int dstPad, - int width, int height) -{ - int srcWidthBytes,dstWidthBytes; - int row,col; - char *pTmpSrc,*pTmpDst; - - switch (srcPad) { - case 1: - srcWidthBytes = (width+7)>>3; - break; - case 2: - srcWidthBytes = ((width+15)>>4)<<1; - break; - case 4: - srcWidthBytes = ((width+31)>>5)<<2; - break; - case 8: - srcWidthBytes = ((width+63)>>6)<<3; - break; - default: - return 0; - } - switch (dstPad) { - case 1: - dstWidthBytes = (width+7)>>3; - break; - case 2: - dstWidthBytes = ((width+15)>>4)<<1; - break; - case 4: - dstWidthBytes = ((width+31)>>5)<<2; - break; - case 8: - dstWidthBytes = ((width+63)>>6)<<3; - break; - default: - return 0; - } - - width = srcWidthBytes; - if (width > dstWidthBytes) - width = dstWidthBytes; - pTmpSrc= pSrc; - pTmpDst= pDst; - for (row = 0; row < height; row++) - { - for (col = 0; col < width; col++) - *pTmpDst++ = *pTmpSrc++; - while (col < dstWidthBytes) - { - *pTmpDst++ = '\0'; - col++; - } - pTmpSrc += srcWidthBytes - width; - } - return dstWidthBytes * height; -} - - +/*
+
+Copyright 1990, 1994, 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.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fontmisc.h>
+
+/* Utility functions for reformating font bitmaps */
+
+static const unsigned char _reverse_byte[0x100] = {
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+};
+
+/*
+ * Invert bit order within each BYTE of an array.
+ */
+void
+BitOrderInvert(unsigned char *buf, int nbytes)
+{
+ const unsigned char *rev = _reverse_byte;
+
+ for (; --nbytes >= 0; buf++)
+ *buf = rev[*buf];
+}
+
+/*
+ * Invert byte order within each 16-bits of an array.
+ */
+void
+TwoByteSwap(unsigned char *buf, int nbytes)
+{
+ unsigned char c;
+
+ for (; nbytes > 0; nbytes -= 2, buf += 2)
+ {
+ c = buf[0];
+ buf[0] = buf[1];
+ buf[1] = c;
+ }
+}
+
+/*
+ * Invert byte order within each 32-bits of an array.
+ */
+void
+FourByteSwap(unsigned char *buf, int nbytes)
+{
+ unsigned char c;
+
+ for (; nbytes > 0; nbytes -= 4, buf += 4)
+ {
+ c = buf[0];
+ buf[0] = buf[3];
+ buf[3] = c;
+ c = buf[1];
+ buf[1] = buf[2];
+ buf[2] = c;
+ }
+}
+
+/*
+ * Repad a bitmap
+ */
+
+int
+RepadBitmap (char *pSrc, char *pDst,
+ unsigned int srcPad, unsigned int dstPad,
+ int width, int height)
+{
+ int srcWidthBytes,dstWidthBytes;
+ int row,col;
+ char *pTmpSrc,*pTmpDst;
+
+ switch (srcPad) {
+ case 1:
+ srcWidthBytes = (width+7)>>3;
+ break;
+ case 2:
+ srcWidthBytes = ((width+15)>>4)<<1;
+ break;
+ case 4:
+ srcWidthBytes = ((width+31)>>5)<<2;
+ break;
+ case 8:
+ srcWidthBytes = ((width+63)>>6)<<3;
+ break;
+ default:
+ return 0;
+ }
+ switch (dstPad) {
+ case 1:
+ dstWidthBytes = (width+7)>>3;
+ break;
+ case 2:
+ dstWidthBytes = ((width+15)>>4)<<1;
+ break;
+ case 4:
+ dstWidthBytes = ((width+31)>>5)<<2;
+ break;
+ case 8:
+ dstWidthBytes = ((width+63)>>6)<<3;
+ break;
+ default:
+ return 0;
+ }
+
+ width = srcWidthBytes;
+ if (width > dstWidthBytes)
+ width = dstWidthBytes;
+ pTmpSrc= pSrc;
+ pTmpDst= pDst;
+ for (row = 0; row < height; row++)
+ {
+ for (col = 0; col < width; col++)
+ *pTmpDst++ = *pTmpSrc++;
+ while (col < dstWidthBytes)
+ {
+ *pTmpDst++ = '\0';
+ col++;
+ }
+ pTmpSrc += srcWidthBytes - width;
+ }
+ return dstWidthBytes * height;
+}
+
+
|