/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ /* fonts.c --- managing fonts for layout. Created: Jamie Zawinski , 23-Jun-94. Re-written: Erik van der Poel , 15-Oct-95. */ /* Currently, we allow the user to select the size of the font used, and the family/foundry. Within that, the document author specifies a size from 1-7, a face (normal, bold, italic, bold-italic) and whether the font is fixed or variable width. Meaning 7*4*2 = 56 possible fonts (but we load lazily). */ #include "mozilla.h" #include "xfe.h" #include "fonts.h" #include "libi18n.h" #include "prprf.h" #include "prmem.h" #include #include "xupfonts.h" #ifndef NO_WEB_FONTS #include "nf.h" #include "Mnfrc.h" /* before Mnffbc to stop warnings about nfrc */ #include "Mnffmi.h" /* before Mnffbc to stop warnings about nffmi */ #include "Mnff.h" /* before Mnfdoer to stop warnings about nff */ #include "Mnfdoer.h" /* before Mnffbc to stop warnings about nfdoer */ #include "Mnfrf.h" /* before Mnffbc to stop warnings about nfrf */ #include "Mnffp.h" #include "Mnffbc.h" /* font consumer interface definitions */ #include "Mnffbu.h" /* font utility interface definitions */ #include "Mnffbp.h" /* font producer interface definitions */ #endif #include "xp_qsort.h" /* for XP_GetString() */ extern int XFE_OTHER_LANGUAGE; extern int XFE_USER_DEFINED; /* for debugging */ /* #define FE_PRINT_FONTS 1 */ #ifndef NO_WEB_FONTS /* This is defined in mozilla.c */ extern void fe_GetProgramDirectory(char *path, int len); #endif /* NO_WEB_FONTS */ #define fe_FONT_PITCH_MONO 0x1 #define fe_FONT_PITCH_PROPORTIONAL 0x2 #define fe_FONT_PITCH_BOTH 0x3 #define fe_TryFont(context, familyName, points, sizeNum, fontmask, charset, pitch, faceNum, dpy) \ (*fe_CharSetFuncsArray[fe_CharSetInfoArray[charset].info].loadFont) \ (context, familyName, points, sizeNum, fontmask, charset, pitch, faceNum, dpy) #define FE_MAYBE_FREE(p) do { if (p) { free(p); (p) = NULL; } } while (0) #define FE_MALLOC_ZAP(type) ((type *) calloc(1, sizeof(type))) #define FE_FONT_MASK_TO_PITCH(fontmask) (((fontmask) & LO_FONT_FIXED) ? 1 : 0) #define FE_FONT_MASK_TOGGLE_PITCH(fontmask) ((fontmask) ^ LO_FONT_FIXED) #define FE_NORMALIZE_SIZE(sizeNum) \ do { (sizeNum) &= 0x7; if ((sizeNum) < 1) { (sizeNum) = 1; } } while (0) #define FE_OPPOSITE_PITCH(p) ((p)==0 ? 1 : 0) #define FE_OPPOSITE_WEIGHT_FACE(f) ((f)^1) #define FE_OPPOSITE_SLANT_FACE(f) ((f)^2) #define FE_FONT_MASK_TO_FACE(fontmask) \ ((((fontmask) & LO_FONT_BOLD) && \ ((fontmask) & LO_FONT_ITALIC)) ? 3 : \ ((fontmask) & LO_FONT_ITALIC) ? 2 : \ ((fontmask) & LO_FONT_BOLD) ? 1 : 0); #define FE_FONT_SELECTED_FAMILY(charset, pitch) \ fe_FontFindSelectedFamily(&fe_FontCharSets[charset].pitches[pitch]) typedef struct fe_StringProcessTable { unsigned char fontIndex; unsigned char skip; unsigned char len; } fe_StringProcessTable; typedef struct fe_FontGroupFont { unsigned char mask1; unsigned char mask2; XFontStruct *xFont; } fe_FontGroupFont; typedef struct fe_FontSetListEntry fe_FontSetListEntry; struct fe_FontSetListEntry { fe_FontSetListEntry *next; char *list; XFontSet fontSet; }; typedef int (*fe_XDrawStringFunc)(Display *dpy, Drawable d, GC gc, int x, int y, char *string, int len); static fe_Font fe_FixedFont = NULL; #define FE_DEFAULT_FONT_SIZE_INCREMENT 0.2 static double fe_FontSizeIncrement = FE_DEFAULT_FONT_SIZE_INCREMENT; /* Allowing an arbitrarily large point sizes enables a condition * where viewing a web page which requests fonts in large point sizes * could cause the X server to run out of memory and crash. * Choose a reasonable maximum point size and normalize requests. */ #define FE_DEFAULT_FONT_MAXIMUM_POINTS 200 static int fe_FontMaximumPoints = FE_DEFAULT_FONT_MAXIMUM_POINTS; static fe_FontFace *fe_FontFaceList = NULL; static fe_FontSize *fe_FontSizeList = NULL; static fe_FontSetListEntry *fe_FontSetList = NULL; #ifndef NO_WEB_FONTS static struct nffbc * fe_FontBroker = NULL; struct nffbu * fe_FontUtility = NULL; #endif fe_FontCharSet fe_FontCharSets[INTL_CHAR_SET_MAX]; unsigned char fe_SortedFontCharSets[INTL_CHAR_SET_MAX]; typedef struct GenericFontFamily { char * class_name; char * generic_name; char * family_name; } GenericFontFamily; static GenericFontFamily fe_generics[] = { {"Serif", "serif", "times"}, {"Sans-Serif", "sans-serif", "helvetica"}, {"Cursive", "cursive", "itc zapf chancery"}, {"Fantasy", "fantasy", "new century schoolbook"}, {"Monospace", "monospace", "courier"} }; #define fe_GenericFamilyCount (sizeof(fe_generics) / sizeof(GenericFontFamily)) static XP_Bool fe_AreNormalFontsAvail(int16 win_csid); static XmFontList fe_GetFontListNormal(int16 charset, fe_Font font, int numOfFont); static XmString fe_ToXmStringNormal(int16 charset, fe_Font font, char * string, int len); static fe_Font fe_LoadNormalFont(MWContext *context, char *familyName, int points, int sizeNum, int fontmask, int charset, int pitch, int faceNum, Display *dpy); static fe_Font fe_LoadFont(MWContext *context, int16 *charset, char *familyName, int points, int size, int fontmask); static fe_Font fe_LoadFontWithoutSubstitution(MWContext *context, int16 *charset, char *familyName, int points, int sizeNum, int fontmask); static fe_Font WrapPlatformFont(fe_Font platform_font, unsigned char font_type); #ifndef NO_WEB_FONTS static fe_Font fe_LoadRenderableFont(MWContext *context, LO_TextAttr *attr, int16 *charset, char *family); static double fe_ConvertHTMLSizeToPointSize(LO_TextAttr *attr, int16 charset); #endif static fe_FontSize * fe_FindFontPointSize(fe_FontFamily *family, double decipoints, XP_Bool search_for_fit, XP_Bool scale_to_fit); static char * fe_FindGenericFamily(int charsetID, char *familyName); static XP_Bool fe_AreEUCCNFontsAvail(int16 /* win_csid */); static XmFontList fe_FontGroupGetFontList(int16 charset, fe_Font font, int numOfFonts); static XmString fe_EUCToXmString(int16 charset, fe_Font fontGroup, char * string, int len, fe_StringProcessTable *table); static fe_Font fe_LoadEUCCNFont(MWContext *context, char *familyName, int points, int sizeNum, int fontmask, int charset, int pitch, int faceNum, Display *dpy); static void fe_EUCCNTextExtents(fe_Font font, char *string, int len, int *direction, int *fontAscent, int *fontDescent, XCharStruct *overall); static void fe_DrawEUCCNString(Display *dpy, Drawable d, fe_Font font, GC gc, int x, int y, char *string, int len); static void fe_DrawEUCCNImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2, int x, int y, char *string, int len); static XmString fe_EUCCNToXmString(int16 charset, fe_Font fontGroup, char * string, int len); static XP_Bool fe_AreEUCJPFontsAvail(int16 /* win_csid */); static fe_Font fe_LoadEUCJPFont(MWContext *context, char *familyName, int points, int sizeNum, int fontmask, int charset, int pitch, int faceNum, Display *dpy); static void fe_EUCJPTextExtents(fe_Font font, char *string, int len, int *direction, int *fontAscent, int *fontDescent, XCharStruct *overall); static void fe_DrawEUCJPString(Display *dpy, Drawable d, fe_Font font, GC gc, int x, int y, char *string, int len); static void fe_DrawEUCJPImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2, int x, int y, char *string, int len); static XmString fe_EUCJPToXmString(int16 charset, fe_Font fontGroup, char * string, int len); static XP_Bool fe_AreEUCKRFontsAvail(int16 /* win_csid */); static fe_Font fe_LoadEUCKRFont(MWContext *context, char *familyName, int points, int sizeNum, int fontmask, int charset, int pitch, int faceNum, Display *dpy); static void fe_EUCKRTextExtents(fe_Font font, char *string, int len, int *direction, int *fontAscent, int *fontDescent, XCharStruct *overall); static void fe_DrawEUCKRString(Display *dpy, Drawable d, fe_Font font, GC gc, int x, int y, char *string, int len); static void fe_DrawEUCKRImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2, int x, int y, char *string, int len); static XmString fe_EUCKRToXmString(int16 charset, fe_Font fontGroup, char * string, int len); static XP_Bool fe_AreEUCTWFontsAvail(int16 /* win_csid */); static fe_Font fe_LoadEUCTWFont(MWContext *context, char *familyName, int points, int sizeNum, int fontmask, int charset, int pitch, int faceNum, Display *dpy); static void fe_EUCTWTextExtents(fe_Font font, char *string, int len, int *direction, int *fontAscent, int *fontDescent, XCharStruct *overall); static void fe_DrawEUCTWString(Display *dpy, Drawable d, fe_Font font, GC gc, int x, int y, char *string, int len); static void fe_DrawEUCTWImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2, int x, int y, char *string, int len); static XmString fe_EUCTWToXmString(int16 charset, fe_Font fontGroup, char * string, int len); static XP_Bool fe_AreBIG5FontsAvail(int16 /* win_csid */); static fe_Font fe_LoadBIG5Font(MWContext *context, char *familyName, int points, int sizeNum, int fontmask, int charset, int pitch, int faceNum, Display *dpy); static void fe_BIG5TextExtents(fe_Font font, char *string, int len, int *direction, int *fontAscent, int *fontDescent, XCharStruct *overall); static void fe_DrawBIG5String(Display *dpy, Drawable d, fe_Font font, GC gc, int x, int y, char *string, int len); static void fe_DrawBIG5ImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2, int x, int y, char *string, int len); static XmString fe_BIG5ToXmString(int16 charset, fe_Font fontGroup, char * string, int len); /* Unicode support */ static XP_Bool fe_AreUnicodeFontsAvail(int16 /* win_csid */); static void fe_DrawUTF8StringImage(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2, int x, int y, char *string, int len); static XFontStruct * fe_UnicodeInitXfont(fe_UnicodePseudoFont *ufont, uint16 encoding); static int16 *INTL_GetXCharSetIDs(Display *dpy); static XmFontList fe_UTF8GetFontList(int16 charset, fe_Font font, int numOfFont); static XmString fe_UTF8ToXmString(int16 charset, fe_Font fontGroup, char * string, int len); static XP_Bool fe_NoneAreFontsAvail(int16 /* win_csid */); static fe_Font fe_NoneLoadFont(void *not_used, char *familyName, int points, int sizeNum, int fontmask, int charset, int pitch, int faceNum, Display *dpy); static void fe_NoneTextExtents(fe_Font font, char *string, int len, int *direction, int *fontAscent, int *fontDescent, XCharStruct *overall); static void fe_NoneDrawString(Display *dpy, Drawable d, fe_Font font, GC gc, int x, int y, char *string, int len); static void fe_NoneDrawImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2, int x, int y, char *string, int len); static XmFontList fe_NoneGetFontList(int16 charset, fe_Font font, int numOfFonts); static XmString fe_NoneToXmString(int16 charset, fe_Font fontGroup, char * string, int len); enum { FE_FONT_INFO_X8 = 0, FE_FONT_INFO_X16, FE_FONT_INFO_EUCCN, FE_FONT_INFO_EUCJP, FE_FONT_INFO_EUCKR, FE_FONT_INFO_EUCTW, FE_FONT_INFO_BIG5, FE_FONT_INFO_UNICODE, FE_FONT_INFO_NONE, }; fe_CharSetFuncs fe_CharSetFuncsArray[] = { { 1, (fe_AreFontsAvailFunc) fe_AreNormalFontsAvail, (fe_LoadFontFunc) fe_LoadNormalFont, (fe_TextExtentsFunc) XTextExtents, (fe_DrawStringFunc) XDrawString, (fe_DrawImageStringFunc) XDrawImageString, (fe_GetFontList) fe_GetFontListNormal, (fe_ToXmString) fe_ToXmStringNormal }, { 1, (fe_AreFontsAvailFunc) fe_AreNormalFontsAvail, (fe_LoadFontFunc) fe_LoadNormalFont, (fe_TextExtentsFunc) XTextExtents16, (fe_DrawStringFunc) XDrawString16, (fe_DrawImageStringFunc) XDrawImageString16, (fe_GetFontList) fe_GetFontListNormal, (fe_ToXmString) fe_ToXmStringNormal }, { 2, (fe_AreFontsAvailFunc) fe_AreEUCCNFontsAvail, (fe_LoadFontFunc) fe_LoadEUCCNFont, (fe_TextExtentsFunc) fe_EUCCNTextExtents, (fe_DrawStringFunc) fe_DrawEUCCNString, (fe_DrawImageStringFunc) fe_DrawEUCCNImageString, (fe_GetFontList) fe_FontGroupGetFontList, (fe_ToXmString) fe_EUCCNToXmString }, { 4, (fe_AreFontsAvailFunc) fe_AreEUCJPFontsAvail, (fe_LoadFontFunc) fe_LoadEUCJPFont, (fe_TextExtentsFunc) fe_EUCJPTextExtents, (fe_DrawStringFunc) fe_DrawEUCJPString, (fe_DrawImageStringFunc) fe_DrawEUCJPImageString, (fe_GetFontList) fe_FontGroupGetFontList, (fe_ToXmString) fe_EUCJPToXmString }, { 2, (fe_AreFontsAvailFunc) fe_AreEUCKRFontsAvail, (fe_LoadFontFunc) fe_LoadEUCKRFont, (fe_TextExtentsFunc) fe_EUCKRTextExtents, (fe_DrawStringFunc) fe_DrawEUCKRString, (fe_DrawImageStringFunc) fe_DrawEUCKRImageString, (fe_GetFontList) fe_FontGroupGetFontList, (fe_ToXmString) fe_EUCKRToXmString }, { 3, (fe_AreFontsAvailFunc) fe_AreEUCTWFontsAvail, (fe_LoadFontFunc) fe_LoadEUCTWFont, (fe_TextExtentsFunc) fe_EUCTWTextExtents, (fe_DrawStringFunc) fe_DrawEUCTWString, (fe_DrawImageStringFunc) fe_DrawEUCTWImageString, (fe_GetFontList) fe_FontGroupGetFontList, (fe_ToXmString) fe_EUCTWToXmString }, { 2, (fe_AreFontsAvailFunc) fe_AreBIG5FontsAvail, (fe_LoadFontFunc) fe_LoadBIG5Font, (fe_TextExtentsFunc) fe_BIG5TextExtents, (fe_DrawStringFunc) fe_DrawBIG5String, (fe_DrawImageStringFunc) fe_DrawBIG5ImageString, (fe_GetFontList) fe_FontGroupGetFontList, (fe_ToXmString) fe_BIG5ToXmString }, { 4, (fe_AreFontsAvailFunc) fe_AreUnicodeFontsAvail, (fe_LoadFontFunc) fe_LoadUnicodeFont, (fe_TextExtentsFunc) fe_UTF8TextExtents, (fe_DrawStringFunc) fe_DrawUTF8String, (fe_DrawImageStringFunc) fe_DrawUTF8StringImage, (fe_GetFontList) fe_UTF8GetFontList, (fe_ToXmString) fe_UTF8ToXmString }, { 0, (fe_AreFontsAvailFunc) fe_NoneAreFontsAvail, (fe_LoadFontFunc) fe_NoneLoadFont, (fe_TextExtentsFunc) fe_NoneTextExtents, (fe_DrawStringFunc) fe_NoneDrawString, (fe_DrawImageStringFunc) fe_NoneDrawImageString, (fe_GetFontList) fe_NoneGetFontList, (fe_ToXmString) fe_NoneToXmString }, }; fe_CharSetInfo fe_CharSetInfoArray[] = { { CS_DEFAULT , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_ASCII , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_LATIN1 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_JIS , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_SJIS , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_EUCJP , FE_FONT_TYPE_GROUP , FE_FONT_INFO_EUCJP }, { CS_MAC_ROMAN , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_BIG5 , FE_FONT_TYPE_GROUP , FE_FONT_INFO_BIG5 }, { CS_GB_8BIT , FE_FONT_TYPE_GROUP , FE_FONT_INFO_EUCCN }, { CS_CNS_8BIT , FE_FONT_TYPE_GROUP , FE_FONT_INFO_EUCTW }, { CS_LATIN2 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_MAC_CE , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_KSC_8BIT , FE_FONT_TYPE_GROUP , FE_FONT_INFO_EUCKR }, { CS_2022_KR , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_8859_3 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_8859_4 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_8859_5 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_8859_6 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_8859_7 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_8859_8 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_8859_9 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_SYMBOL , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_DINGBATS , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_DECTECH , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_CNS11643_1 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_CNS11643_2 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_JISX0208 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_JISX0201 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_KSC5601 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_TIS620 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_JISX0212 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_GB2312 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_UCS2 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_UCS4 , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_UTF8 , FE_FONT_TYPE_GROUP , FE_FONT_INFO_UNICODE }, { CS_UTF7 , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_NPC , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_X_BIG5 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_USRDEF2 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_KOI8_R , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_MAC_CYRILLIC , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_CP_1251 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_MAC_GREEK , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_CP_1253 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_CP_1250 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_CP_1254 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_MAC_TURKISH , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_GB2312_11 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_JISX0208_11 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_KSC5601_11 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_CNS11643_1110, FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_UCS2_SWAP , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_IMAP4_UTF7 , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_CP_850 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_CP_852 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_CP_855 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_CP_857 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_CP_862 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_CP_864 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_CP_866 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_CP_874 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_CP_1257 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_CP_1258 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_ARMSCII8 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_HZ , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_ISO_2022_CN , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_GB13000 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_BIG5_PLUS , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_UHC , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_CNS11643_3 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_CNS11643_4 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_CNS11643_5 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_CNS11643_6 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_CNS11643_7 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_CNS11643_8 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_CNS11643_9 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_CNS11643_10 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_CNS11643_11 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_CNS11643_12 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_CNS11643_13 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_CNS11643_14 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_CNS11643_15 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_CNS11643_16 , FE_FONT_TYPE_X16 , FE_FONT_INFO_X16 }, { CS_VIET_VISCII , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_VIET_VIQR , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_KOI8_U , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_ISO_IR_111 , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_8859_6_I , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_8859_6_E , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_8859_8_I , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_8859_8_E , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_JOHAB , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, { CS_JOHABFONT , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, /* put this as NONE untill we have real johab font support */ { CS_VIET_VPS , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_VIET_TCVN , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_VIET_VNI , FE_FONT_TYPE_X8 , FE_FONT_INFO_X8 }, { CS_T61 , FE_FONT_TYPE_NONE , FE_FONT_INFO_NONE }, }; static unsigned char *fe_LocaleCharSets = NULL; static int32 smallestFontFoundSize = 12; XP_Bool fe_IsCharSetSupported(int16 doc_csid) { /* need to deal with webfonts */ #if 1 return TRUE; #else int16 win_csid; win_csid = INTL_DocToWinCharSetID(doc_csid); return(fe_AreFontsAvail(win_csid)); #endif } static XP_Bool fe_NoneAreFontsAvail(int16 win_csid ) { XP_ASSERT(0); /* this call should never been called */ return FALSE; /* to make the compiler won't complain */ } static fe_Font fe_NoneLoadFont(void *not_used, char *familyName, int points, int sizeNum, int fontmask, int charset, int pitch, int faceNum, Display *dpy) { XP_ASSERT(0); /* this call should never been called */ return (fe_Font) NULL; /* to make the compiler won't complain */ } static void fe_NoneTextExtents(fe_Font font, char *string, int len, int *direction, int *fontAscent, int *fontDescent, XCharStruct *overall) { XP_ASSERT(0); /* this call should never been called */ } static void fe_NoneDrawString(Display *dpy, Drawable d, fe_Font font, GC gc, int x, int y, char *string, int len) { XP_ASSERT(0); /* this call should never been called */ } static void fe_NoneDrawImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2, int x, int y, char *string, int len) { XP_ASSERT(0); /* this call should never been called */ } static XmFontList fe_NoneGetFontList(int16 charset, fe_Font font, int numOfFonts) { XP_ASSERT(0); /* this call should never been called */ return (XmFontList) NULL; /* to make the compiler won't complain */ } static XmString fe_NoneToXmString(int16 charset, fe_Font fontGroup, char * string, int len) { XP_ASSERT(0); /* this call should never been called */ return (XmString) NULL; /* to make the compiler won't complain */ } XP_Bool fe_AreFontsAvail(int16 win_csid) { int result; result = (*fe_CharSetFuncsArray[fe_CharSetInfoArray[(win_csid) & 0xff].info ].areFontsAvail)(win_csid); return result; } static void fe_GetLocaleCharSets(Display *dpy) { char *charset; int16 charsetID; char clas[512]; XrmDatabase db; char *def; XFontSet fontSet; int i; int j; char *mimeCharSet; int missCount; char **missing; char name[512]; char *p; char *type; XrmValue value; if (fe_LocaleCharSets) { return; } #if defined(SCO) || defined(UNIXWARE) && (XlibSpecificationRelease == 5) /* ** XCreateFontSet is very slow in old Xlibs, fixed in X11R6 ** If locale == C, just punt */ { char *locale; locale = setlocale(LC_CTYPE, NULL); if (*locale == 'C') /* SCO is C_C.C */ { return; } } #endif missing = NULL; missCount = 0; def = NULL; fontSet = XCreateFontSet(dpy, "*-iso8859-1", &missing, &missCount, &def); if ((!fontSet) || (missCount < 1) || (!missing)) { goto get_locale_char_sets_fail; } fe_LocaleCharSets = malloc(missCount + 2); if (!fe_LocaleCharSets) { goto get_locale_char_sets_fail; } j = 0; fe_LocaleCharSets[j++] = ((unsigned char) (CS_LATIN1 & 0xff)); charset = NULL; db = XtDatabase(dpy); for (i = 0; i < missCount; i++) { FE_MAYBE_FREE(charset); if (!missing[i]) { continue; } /* (void) fprintf(real_stderr, "locale font %d: \"%s\"\n", i + 1, missing[i]); */ charset = strdup(missing[i]); if (!charset) { goto get_locale_char_sets_fail; } p = charset; while (*p) { (*p) = XP_TO_LOWER(*p); p++; } (void) PR_snprintf(clas, sizeof(clas), "%s.DocumentFonts.CharSet.Name", fe_progclass); (void) PR_snprintf(name, sizeof(name), "%s.documentFonts.charset.%s", fe_progclass, charset); if (XrmGetResource(db, name, clas, &type, &value)) { mimeCharSet = (char *) value.addr; } else { #ifdef DEBUG (void) fprintf(real_stderr, "fontset charset %s\n", charset); #endif /* DEBUG */ continue; } charsetID = INTL_CharSetNameToID(mimeCharSet); if ((charsetID == CS_UNKNOWN) && strcmp(charset, "x-ignore")) { #ifdef DEBUG (void) fprintf(real_stderr, "fontset internal %s %s\n", charset, mimeCharSet); #endif /* DEBUG */ continue; } if (!strcmp(charset, "x-ignore")) { continue; } charsetID &= 0xff; if (charsetID >= INTL_CHAR_SET_MAX) { continue; } fe_LocaleCharSets[j++] = (unsigned char) charsetID; } FE_MAYBE_FREE(charset); fe_LocaleCharSets[j] = 0; XFreeStringList(missing); XFreeFontSet(dpy, fontSet); return; get_locale_char_sets_fail: if (fontSet) { XFreeFontSet(dpy, fontSet); } if (missing) { XFreeStringList(missing); } if (fe_LocaleCharSets) { free(fe_LocaleCharSets); fe_LocaleCharSets = NULL; } } fe_FontFamily * fe_FontFindSelectedFamily(fe_FontPitch *pitch) { fe_FontFamily *family; int i; if (!pitch) return(NULL); if (pitch->selectedFamily) return(pitch->selectedFamily); family = NULL; for (i = 0; i < pitch->numberOfFamilies; i++) { if (pitch->families[i].selected) { family = &pitch->families[i]; break; } } if (!family) { family = FE_MALLOC_ZAP(fe_FontFamily); } pitch->selectedFamily = family; return (family); } static fe_FontFamily * fe_GetFontFamily(uint16 charset, int pitch) { fe_FontFamily *family; family = FE_FONT_SELECTED_FAMILY((charset&0xFF), pitch); if (family == NULL) { return NULL; } if (!family->htmlSizesComputed) { fe_ComputeFontSizeTable(family); } return family; } fe_FontFamily * fe_FontFindFamily(int charsetID, int pitchID, char *familyName) { fe_FontFamily *family; fe_FontPitch *pitch; int i; char * genericFamily; if (!familyName || !*familyName) return(NULL); family = NULL; pitch = &fe_FontCharSets[charsetID&0xFF].pitches[pitchID]; for (i = 0; i < pitch->numberOfFamilies; i++) { if (!XP_STRCASECMP(pitch->families[i].family, familyName)) { family = &pitch->families[i]; if (!family->htmlSizesComputed) { fe_ComputeFontSizeTable(family); } break; } } if (family) return family; genericFamily = fe_FindGenericFamily(charsetID, familyName); if (!genericFamily) return family; for (i = 0; i < pitch->numberOfFamilies; i++) { if (!XP_STRCASECMP(pitch->families[i].family, genericFamily)) { family = &pitch->families[i]; if (!family->htmlSizesComputed) { fe_ComputeFontSizeTable(family); } break; } } return (family); } static char * fe_FindGenericFamily(int charsetID, char *familyName) { char * genericFamily; int i; /* This is the "default font displayer's" mapping of the * generic font names, as described by CSS1, into common X fonts. */ if (!familyName || !*familyName) return(NULL); /* Generic font names are mapped only for the Latin-1 charset */ if (CS_LATIN1 != charsetID) return NULL; genericFamily = NULL; for (i = 0; i < fe_GenericFamilyCount; i++) { if (!XP_STRCASECMP(fe_generics[i].generic_name, familyName)) { genericFamily = fe_generics[i].family_name; break; } } return genericFamily; } XtPointer fe_GetFont(MWContext *context, int sizeNum, int fontmask) { XmFontListEntry flentry; XtPointer fontOrFontSet; XmFontType type; XmFontList fontList; fontOrFontSet = fe_GetFontOrFontSet(context, NULL, sizeNum, fontmask, &type); if (!fontOrFontSet) { return NULL; } flentry = XmFontListEntryCreate(XmFONTLIST_DEFAULT_TAG, type, fontOrFontSet); if (!flentry) { return NULL; } fontList = XmFontListAppendEntry(NULL, flentry); if (!fontList) { return NULL; } XmFontListEntryFree(&flentry); return fontList; } XtPointer fe_GetFontOrFontSet(MWContext *context, char *familyName, int sizeNum, int fontmask, XmFontType *type) { unsigned char charset; int16 cs; char *def; Display *dpy; fe_FontSetListEntry *f; fe_FontFace *face; int faceNum; XtPointer fontOrFontSet; char *list; int missCount; char **missing; char *newList; unsigned char *p; int pitch; fe_FontSize *size; fe_FontFamily *family; def = NULL; dpy = XtDisplay(CONTEXT_WIDGET(context)); faceNum = FE_FONT_MASK_TO_FACE(fontmask); list = NULL; missCount = 0; missing = NULL; pitch = FE_FONT_MASK_TO_PITCH(fontmask); FE_NORMALIZE_SIZE(sizeNum); if (fe_LocaleCharSets) { p = fe_LocaleCharSets; while (*p) { charset = *p++; family = NULL; if (familyName && *familyName) { family = fe_FontFindFamily(charset, pitch, familyName); if (!family) return NULL; } if (!family) { family = fe_GetFontFamily(charset, pitch); if (!family) { return NULL; } } size = family->htmlSizes[sizeNum-1]; if (!size) { continue; } face = size->faces[faceNum]; if (!face) { continue; } if (!face->longXLFDFontName) { continue; } if (list) { newList = PR_smprintf("%s,%s", list, face->longXLFDFontName); free(list); list = newList; } else { list = strdup(face->longXLFDFontName); } if (!list) { return NULL; } } f = fe_FontSetList; while (f) { if (!strcmp(f->list, list)) { break; } f = f->next; } if (f) { free(list); fontOrFontSet = f->fontSet; *type = XmFONT_IS_FONTSET; } else { fontOrFontSet = XCreateFontSet(dpy, list, &missing, &missCount, &def); if (fontOrFontSet) { /* (void) fprintf(real_stderr, "font set \"%s\" succeeded\n", list); */ f = XP_NEW_ZAP(fe_FontSetListEntry); if (!f) { return NULL; } f->next = fe_FontSetList; fe_FontSetList = f; f->list = list; f->fontSet = fontOrFontSet; *type = XmFONT_IS_FONTSET; } else { /* (void) fprintf(real_stderr, "font set \"%s\" failed\n", list); */ return NULL; } } } else { cs = CS_LATIN1; fontOrFontSet = fe_LoadFont(context, &cs, familyName, 0 /* no pointsize */, sizeNum, fontmask); *type = XmFONT_IS_FONT; } return fontOrFontSet; } static int fe_PitchAndFaceToFontMask(int pitch, int face) { int fontmask; if (pitch) { fontmask = LO_FONT_FIXED; } else { fontmask = 0; } switch (face) { case 1: fontmask |= LO_FONT_BOLD; break; case 2: fontmask |= LO_FONT_ITALIC; break; case 3: fontmask |= (LO_FONT_BOLD | LO_FONT_ITALIC); break; default: break; } return fontmask; } static fe_Font fe_LoadFontGroup(MWContext *context, char *familyName, int points, int sizeNum, int fontmask, int16 charsetID, int pitch, int faceNum, Display *dpy) { fe_FontFace *face; fe_Font font; int i; fe_FontSize *size; fe_FontFamily *family; size = FE_MALLOC_ZAP(fe_FontSize); if (!size) { return NULL; } for (i = 0; i < 4; i++) { face = FE_MALLOC_ZAP(fe_FontFace); if (!face) { return NULL; } size->faces[i] = face; /* * @@@ ignore familyName for now * need to modify all the loadFont funcs too */ font = (*fe_CharSetFuncsArray[fe_CharSetInfoArray[charsetID]. info].loadFont)(context, NULL, points, sizeNum, fe_PitchAndFaceToFontMask(pitch, i), charsetID, pitch, i, dpy); if (!font) { return NULL; } face->font = font; } family = FE_FONT_SELECTED_FAMILY(charsetID, pitch); if (!family) { XP_FREE(size); return NULL; } /* XXX what is going on here for pointsizes? -converse */ if (!points) { family->htmlSizes[sizeNum-1] = size; } return size->faces[faceNum]->font; } static fe_Font fe_LoadFont(MWContext *context, int16 *charset, char *familyName, int points, int sizeNum, int fontmask) { int16 charsetID; Display *dpy; fe_FontFace *face; int faceNum; fe_Font font; int pitch; fe_FontSize *size; int trySize; fe_FontFamily *family; double decipoints; /* * paranoia, robustness */ charsetID = 0; if (charset) { charsetID = *charset; } else { charset = &charsetID; } if (!charsetID) { charsetID = INTL_DefaultTextAttributeCharSetID(context); if (!charsetID) { charsetID = CS_LATIN1; } *charset = charsetID; } charsetID &= 0xff; if (charsetID >= INTL_CHAR_SET_MAX) { charsetID = (CS_LATIN1 & 0xff); *charset = CS_LATIN1; } pitch = FE_FONT_MASK_TO_PITCH(fontmask); faceNum = FE_FONT_MASK_TO_FACE(fontmask); dpy = XtDisplay(CONTEXT_WIDGET(context)); family = NULL; if (familyName && *familyName) { family = fe_FontFindFamily(charsetID, pitch, familyName); if ((!family) && (fe_CharSetInfoArray[charsetID].type != FE_FONT_TYPE_GROUP)) { return NULL; } } if (!family) { /* We blew the font lookup, falling back to default. */ family = fe_GetFontFamily(*charset, pitch); /* Invalidate the point size, I can't read it. */ points = 0; if (!family) { if (*charset == CS_LATIN1) { return fe_FixedFont; } else { *charset = CS_LATIN1; return fe_LoadFont(context, charset, familyName, points, sizeNum, fontmask); } } } if (! points) size = family->htmlSizes[sizeNum-1]; else { decipoints = (double) (points * 10); size = fe_FindFontPointSize(family, decipoints, False, True); } if (!size) { if (fe_CharSetInfoArray[charsetID].type == FE_FONT_TYPE_GROUP) { font = fe_LoadFontGroup(context, familyName, points, sizeNum, fontmask, charsetID, pitch, faceNum, dpy); if (font) { return font; } } /* * this charset is not available * use Latin-1 font to display the bytes */ if (*charset == CS_LATIN1) { return fe_FixedFont; } else { *charset = CS_LATIN1; return fe_LoadFont(context, charset, familyName, points, sizeNum, fontmask); } } face = size->faces[faceNum]; if (!face) { /* * this shouldn't happen * if it does, we will display these bytes in a Latin-1 font */ if (*charset == CS_LATIN1) { return fe_FixedFont; } else { *charset = CS_LATIN1; return fe_LoadFont(context, charset, familyName, points, sizeNum, fontmask); } } font = face->font; if (!font) { font = fe_TryFont(context, familyName, points, sizeNum, fontmask, charsetID, pitch, faceNum, dpy); if (font) { face->font = font; } else { for (trySize = sizeNum - 1; trySize > 0; trySize--) { font = fe_TryFont(context, familyName, points, trySize, fontmask, charsetID, pitch, faceNum, dpy); if (font) { return font; } } for (trySize = sizeNum + 1; trySize < 8; trySize++) { font = fe_TryFont(context, familyName, points, trySize, fontmask, charsetID, pitch, faceNum, dpy); if (font) { return font; } } *charset = CS_LATIN1; font = fe_FixedFont; face->font = font; return font; /* @@@ need to change this */ /* (void) fprintf(real_stderr, "could not load\n%s\n", face->longXLFDFontName); */ /* XP_GetString(XFE_COULD_NOT_LOAD_FONT) */ /* XP_GetString(XFE_USING_FALLBACK_FONT) */ /* XP_GetString(XFE_NO_FALLBACK_FONT) */ /* FE_Alert(context, msg); */ } } return font; } static fe_Font fe_LoadFontWithoutSubstitution(MWContext *context, int16 *charset, char *familyName, int points, int sizeNum, int fontmask) { int16 charsetID; Display *dpy; fe_FontFace *face; int faceNum; fe_Font font; int pitch; fe_FontSize *size; int trySize; fe_FontFamily *family; double decipoints; /* * paranoia, robustness */ charsetID = 0; if (charset) { charsetID = *charset; } else { charset = &charsetID; } if (!charsetID) { charsetID = INTL_DefaultTextAttributeCharSetID(context); if (!charsetID) { charsetID = CS_LATIN1; } *charset = charsetID; } charsetID &= 0xff; if (charsetID >= INTL_CHAR_SET_MAX) { charsetID = (CS_LATIN1 & 0xff); *charset = CS_LATIN1; } pitch = FE_FONT_MASK_TO_PITCH(fontmask); faceNum = FE_FONT_MASK_TO_FACE(fontmask); dpy = XtDisplay(CONTEXT_WIDGET(context)); family = NULL; if (familyName && *familyName) { family = fe_FontFindFamily(charsetID, pitch, familyName); if (!family) { return NULL; } } else { return NULL; } if (! points) size = family->htmlSizes[sizeNum-1]; else { decipoints = (double) (points * 10); size = fe_FindFontPointSize(family, decipoints, False, True); } if (!size) { return NULL; } face = size->faces[faceNum]; if (!face) { return NULL; } font = face->font; if (!font) { font = fe_TryFont(context, familyName, points, sizeNum, fontmask, charsetID, pitch, faceNum, dpy); if (font) { face->font = font; } else if (points == 0) { for (trySize = sizeNum - 1; trySize > 0; trySize--) { font = fe_TryFont(context, familyName, points, trySize, fontmask, charsetID, pitch, faceNum, dpy); if (font) { return font; } } for (trySize = sizeNum + 1; trySize < 8; trySize++) { font = fe_TryFont(context, familyName, points, trySize, fontmask, charsetID, pitch, faceNum, dpy); if (font) { return font; } } } } return font; } static char * NameFromList(char * namelist) { static char * list; static int next; static int len; int start; int end; char final = '\0'; if (namelist) { list = namelist; len = strlen(namelist); next = 0; } start = next; if (! list || list[start] == '\0') return (char *) NULL; /* skip over leading whitespace and commas to find the start of the name */ while (list[start] != '\0' && (list[start] == ',' || isspace(list[start]))) start++; /* find the end of the name */ next = start; while(list[next] != '\0' && list[next] != ',') { if (list[next] == '"' || list[next] == '\'') { final = list[next]; /* find the matching quote */ next++; while (list[next] != '\0' && list[next] != final) next++; /* if list[next] is null, there was no matching quote, so bail */ if (list[next] == '\0') break; } next++; } end = next - 1; if (list[next] != '\0' && next < len) next++; /* strip off trailing whitespace */ while (end >= start && isspace(list[end])) end--; /* if it's quoted, strip off the quotes */ if ((list[start] == '"' || list[start] == '\'') && list[end] == list[start]) { start++; end--; } end++; list[end] = '\0'; return &(list[start]); } fe_Font fe_LoadFontFromFace(MWContext *context, LO_TextAttr *attr, int16 *charset, char *net_font_face, int size, int fontmask) { fe_Font font = 0; char *local_net_font_face = NULL; char *familyname = NULL; char *last_familyname = NULL; unsigned char font_type = 0; int16 charsetID; int16 saved_charset; int points = 0; if (attr) { font = (fe_Font) attr->FE_Data; if (font) return(font); points = (int) attr->point_size; if (points < 1) points = 0; if (points > fe_FontMaximumPoints) points = fe_FontMaximumPoints; if (attr->font_weight > 0) { if (attr->font_weight <= 500) fontmask &= ~LO_FONT_BOLD; else fontmask |= LO_FONT_BOLD; } } charsetID = 0; if (charset) { charsetID = *charset; } else { charset = &charsetID; } if (!charsetID) { charsetID = INTL_DefaultTextAttributeCharSetID(context); if (!charsetID) { charsetID = CS_LATIN1; } *charset = charsetID; } charsetID &= 0xff; if (charsetID >= INTL_CHAR_SET_MAX) { charsetID = (CS_LATIN1 & 0xff); *charset = CS_LATIN1; } saved_charset = *charset; FE_NORMALIZE_SIZE(size); if (net_font_face && *net_font_face) { local_net_font_face = strdup(net_font_face); if (!local_net_font_face) return (0); familyname = NameFromList(local_net_font_face); while (familyname) { #if !defined(NO_WEB_FONTS) && !defined(NO_BROKERED_WEB_FONTS) /* Prefer fonts from the broker. */ font = fe_LoadRenderableFont(context, attr, charset, familyname); if (font) font_type = FE_FONT_TYPE_RENDERABLE; #endif if (! font) { /* First, determine whether any font is available * in this charset; if not, the charset will be * reassigned to CS_LATIN1. */ (void) fe_LoadFont(context, charset, NULL, 0, 3, 0); font = fe_LoadFontWithoutSubstitution(context, charset, familyname, points, size, fontmask); if (!font) /* Try the other pitch */ font = fe_LoadFontWithoutSubstitution(context, charset, familyname, points, size, FE_FONT_MASK_TOGGLE_PITCH(fontmask)); } if (font) break; last_familyname = familyname; familyname = NameFromList((char *) NULL); } if (!font && last_familyname) { font = fe_LoadFont(context, charset, last_familyname, points, size, fontmask); if (!font) { /* Try the other pitch */ font = fe_LoadFont(context, charset, familyname, points, size, FE_FONT_MASK_TOGGLE_PITCH(fontmask)); } } XP_FREE(local_net_font_face); } /* If we didn't get a font from the face, default to no font_face */ if (!font) { font = fe_LoadFont(context, charset, NULL, points, size, fontmask); } if (font) { fe_Font platform_font = font; if (FE_FONT_TYPE_RENDERABLE != font_type) font_type = fe_CharSetInfoArray[(*charset) & 0xff].type; font = WrapPlatformFont(platform_font, font_type); if (attr) { attr->FE_Data = (void *) font; } } /* Preserve the document charset. Web fonts may be used to * render glyphs in character sets which are not represented * in the platform-specific font catalog. */ *charset = saved_charset; return(font); } static fe_Font WrapPlatformFont(fe_Font platform_font, unsigned char font_type) { fe_FontWrap *fw; fw = XP_NEW(fe_FontWrap); if (!fw) return NULL; fw->platform_font = platform_font; fw->distinguisher = font_type; return (fe_Font) fw; } /* Delete the wrapper but do not free the font. */ void fe_DoneWithFont(fe_Font font) { XP_DELETE(font); } static void FreePlatformFont(Display *dpy, XFontStruct *xfs, LO_TextAttr *attr) { XFontProp *prop; int n; fe_FontSize *size = 0; fe_FontSize **prev = 0; fe_FontFace *face = 0; fe_FontFamily *family; XP_Bool in_use; XP_Bool found; char * familyName; int pitch; Atom atom; /* Do not free fonts which fulfill requests for HTML sizes */ if (attr->point_size < 1) return; /* Take the family name from the FAMILY_NAME property of the font */ familyName = NULL; for (n = xfs->n_properties, prop=xfs->properties; --n >= 0; prop++) { if (XA_FAMILY_NAME == prop->name) { atom = prop->card32; familyName = XGetAtomName(dpy, atom); break; } } if (! familyName) return; /* Use the font family name, the requested charset and the * requested pitch to find the family record. */ pitch = FE_FONT_MASK_TO_PITCH(attr->fontmask); family = fe_FontFindFamily(attr->charset, pitch, familyName); if (! family) { pitch = FE_OPPOSITE_PITCH(pitch); family = fe_FontFindFamily(attr->charset, pitch, familyName); } if (! family && CS_LATIN1 != attr->charset) { pitch = FE_FONT_MASK_TO_PITCH(attr->fontmask); family = fe_FontFindFamily(CS_LATIN1, pitch, familyName); if (! family) { pitch = FE_OPPOSITE_PITCH(pitch); family = fe_FontFindFamily(CS_LATIN1, pitch, familyName); } } XFree(familyName); /* Search through the family pool for a match on this xfs */ found = False; if (family) { prev = &(family->pool); for (size = family->pool; size; prev = &(size->next), size = size->next) { for (n=0; n <= 3; n++) { face = size->faces[n]; if (face && face->font == xfs) { found = True; break; } } if (found) break; } } /* Free the font and set the font field to NULL */ if (found && size) { XFreeFont(dpy, xfs); face->font = NULL; /* If all the faces are not loaded, free the faces * and free the size record which points to them. */ in_use = False; for (n=0; n < 4; n++) { if (size->faces[n]->font != NULL) in_use = True; } if ((! in_use) && prev) { *prev = size->next; for (n=0; n < 4; n++) { face = size->faces[n]; if (face->longXLFDFontName) free(face->longXLFDFontName); free(face); } free(size); } } } void FE_ReleaseTextAttrFeData(MWContext *context, LO_TextAttr *attr) { fe_FontWrap *fw; struct nfrf *rf; XFontStruct *xfs; Display *dpy; if (!context || !attr) return; fw = (fe_FontWrap *) attr->FE_Data; if (! fw) return; switch (fw->distinguisher) { case FE_FONT_TYPE_X8: case FE_FONT_TYPE_X16: dpy = XtDisplay(CONTEXT_WIDGET(context)); xfs = (XFontStruct *) fw->platform_font; FreePlatformFont(dpy, xfs, attr); break; case FE_FONT_TYPE_GROUP: default: break; case FE_FONT_TYPE_RENDERABLE: rf = (struct nfrf *) fw->platform_font; nfrf_release(rf, NULL); break; } XP_DELETE(fw); attr->FE_Data = NULL; } #ifndef NO_WEB_FONTS static fe_Font fe_LoadRenderableFont(MWContext *context, LO_TextAttr *attr, int16 *charset, char *family) { int weight; int escapement; int style; int underline; int strikeout; int charsetID; struct nfrc * rc; struct nffmi * fmi; struct nff * unsized_font = NULL; struct nfrf * renderable_font = NULL; void * rcbuf[4]; double pointsize; char mime_name[128]; if (!context || !attr || !charset) return (fe_Font) NULL; /* Create a rendering context */ rcbuf[0] = XtDisplay(CONTEXT_WIDGET(context)); rcbuf[1] = rcbuf[2] = NULL; rc = nffbu_CreateRenderingContext(fe_FontUtility, NF_RC_DIRECT, 0, rcbuf, 3, NULL); if (!rc) return (fe_Font) NULL; /* Create a font match information object */ charsetID = *charset; if (charsetID < 0 || (charsetID & 0xff) >= INTL_CHAR_SET_MAX) return (fe_Font) NULL; INTL_CharSetIDToName(charsetID, mime_name); weight = attr->font_weight; if (0 == weight) weight = (LO_FONT_BOLD & attr->attrmask) ? 700 : 400; style = (LO_FONT_ITALIC & attr->attrmask) ? nfStyleItalic : nfStyleNormal; underline = (LO_ATTR_UNDERLINE & attr->attrmask) ? nfUnderlineYes : nfUnderlineNo; strikeout = (LO_ATTR_STRIKEOUT & attr->attrmask) ? nfStrikeOutYes : nfStrikeOutNo; escapement = (LO_FONT_FIXED & attr->attrmask) ? nfSpacingMonospaced : nfSpacingProportional; fmi = nffbu_CreateFontMatchInfo(fe_FontUtility, family, NULL, mime_name, weight, escapement, style, underline, strikeout, nfResolutionDontCare, nfResolutionDontCare, NULL /* exception */); /* Create the font, cleanup, and return the font */ if (fmi) { /* Find the url that is loading this font */ History_entry *he = SHIST_GetCurrent(&context->hist); const char *accessing_url_str = NULL; if (he) { accessing_url_str = he->address; } unsized_font = nffbc_LookupFont(fe_FontBroker, rc, fmi, accessing_url_str, NULL); if (!unsized_font) { nffbu_LookupFailed(fe_FontUtility, context, rc, fmi, NULL); } nffmi_release(fmi, NULL); if (unsized_font) { pointsize = attr->point_size; if (pointsize <= 0) pointsize = fe_ConvertHTMLSizeToPointSize(attr, charsetID); renderable_font = nff_GetRenderableFont(unsized_font, rc, pointsize, NULL); nff_release(unsized_font, NULL); } } nfrc_release(rc, NULL); return ((fe_Font) renderable_font); } int fe_WebfontsNeedReload(MWContext *context) { int ret = 0; if (fe_FontUtility) { ret = nffbu_WebfontsNeedReload(fe_FontUtility, context, NULL); } return (ret); } void fe_ShutdownWebfonts(void) { char *buf; /* Load Catalog */ /* Form "$HOME/.netscape/dynfonts/fonts.cat" into buf */ buf = fe_GetConfigDirFilename("dynfonts/fonts.cat"); if (buf) { nffbu_SaveCatalog(fe_FontUtility, buf, NULL); free(buf); } } static double fe_ConvertHTMLSizeToPointSize(LO_TextAttr *attr, int16 charset) { int j; int size3; double decipoints = 0.0; fe_FontFamily *family; fe_FontSize *size; int pitch; double pointsize; /* Translate HTML sizes 1-7 to pointsize */ /* Take the default size of the default family for * this charset to be the pointsize of HTML size 3, * if it is given; otherwise, use 12 points. */ size3 = 0; size = NULL; pitch = FE_FONT_MASK_TO_PITCH(attr->attrmask); family = FE_FONT_SELECTED_FAMILY(charset, pitch); if (family && family->name) { for (j = 0; j < family->numberOfPointSizes; j++) { size = &family->pointSizes[j]; if (size->selected) { break; } else { size = NULL; } } if (size) size3 = size->size; if (!size3) size3 = family->scaledSize; } if (!size3) size3 = 120; /* Sizing logic from fe_ComputeFontSizeTable */ if (attr->size < 3) { decipoints = ((1 - ((3 - attr->size) * fe_FontSizeIncrement)) * size3); if (decipoints < 10) decipoints = 10; } else if (attr->size == 3) { decipoints = size3; } else if (attr->size > 3) { decipoints = ((1 + ((attr->size - 3) * fe_FontSizeIncrement)) * size3); } pointsize = decipoints / 10; return pointsize; } #endif /* ifndef NO_WEB_FONTS */ XtPointer fe_GetFontOrFontSetFromFace(MWContext *context, LO_TextAttr *attr, char *net_font_face, int size, int fontmask, XmFontType *type) { XtPointer fontOrFontset = 0; char *local_net_font_face = NULL; char *familyname = NULL; if (attr) { fontOrFontset = (fe_Font) attr->FE_Data; if (fontOrFontset) return(fontOrFontset); } if (net_font_face && *net_font_face) { local_net_font_face = strdup(net_font_face); if (!local_net_font_face) return (0); familyname = NameFromList(local_net_font_face); while (familyname) { fontOrFontset = fe_GetFontOrFontSet(context, familyname, size, fontmask, type); if (!fontOrFontset) { /* Try the other pitch */ fontOrFontset = fe_GetFontOrFontSet(context, familyname, size, FE_FONT_MASK_TOGGLE_PITCH(fontmask), type); } if (fontOrFontset) break; familyname = NameFromList((char *) NULL); } XP_FREE(local_net_font_face); } if (!fontOrFontset) { fontOrFontset = fe_GetFontOrFontSet(context, NULL, size, fontmask, type); } if (fontOrFontset) { if (attr) { attr->FE_Data = (void *) fontOrFontset; } } return(fontOrFontset); } static void * fe_ReallocZap(void *p, int oldSize, int newSize) { char *end; char *q; p = realloc(p, newSize); if (p) { if (newSize > oldSize) { end = ((char *) p) + newSize; for (q = ((char *) p) + oldSize; q < end; q++) { *q = 0; } } } return p; } #define FE_REALLOC_ZAP(p, oldSize, newSize, type) \ ((type *) fe_ReallocZap((p), (oldSize) * sizeof(type), \ (newSize) * sizeof(type))) static char * fe_CapitalizeFontName(char *name) { char *p; char *ret; ret = strdup(name); if (!ret) { return NULL; } p = ret; while (1) { while ((*p) && XP_IS_SPACE(*p)) { p++; } if (!*p) { break; } *p = XP_TO_UPPER(*p); while ((*p) && (!XP_IS_SPACE(*p))) { p++; } if (!*p) { break; } } return ret; } static void fe_AddFontSize(fe_FontFamily *family, int faceNum, int pixelSizeNum, int pointSizeNum, char *pixelSizeFontSpec, char *pointSizeFontSpec) { int alloc; fe_FontFace *face; int i; fe_FontSize *newSizes; fe_FontSize *size; /* * first we do the pixel size */ size = NULL; if (family->pixelSizes) { for (i = 0; i < family->numberOfPixelSizes; i++) { size = &family->pixelSizes[i]; if (size->size == pixelSizeNum) { break; } else { size = NULL; } } } if (!size) { if (family->numberOfPixelSizes >= family->pixelAlloc) { alloc = (2 * (family->pixelAlloc + 1)); newSizes = FE_REALLOC_ZAP(family->pixelSizes, family->pixelAlloc, alloc, fe_FontSize); if (!newSizes) { return; } family->pixelSizes = newSizes; family->pixelAlloc = alloc; } size = &family->pixelSizes[family->numberOfPixelSizes++]; size->size = pixelSizeNum; } if (!size->faces[faceNum]) { face = FE_MALLOC_ZAP(fe_FontFace); if (!face) { return; } face->longXLFDFontName = strdup(pixelSizeFontSpec); if (!face->longXLFDFontName) { free(face); return; } face->next = fe_FontFaceList; fe_FontFaceList = face; size->faces[faceNum] = face; } else { /* @@@ fix this -- erik */ /* (void) fprintf(real_stderr, "dup %s\n", pixelSizeFontSpec); */ } /* * now we do the same for the point size */ size = NULL; if (family->pointSizes) { for (i = 0; i < family->numberOfPointSizes; i++) { size = &family->pointSizes[i]; if (size->size == pointSizeNum) { break; } else { size = NULL; } } } if (!size) { if (family->numberOfPointSizes >= family->pointAlloc) { alloc = (2 * (family->pointAlloc + 1)); newSizes = FE_REALLOC_ZAP(family->pointSizes, family->pointAlloc, alloc, fe_FontSize); if (!newSizes) { return; } family->pointSizes = newSizes; family->pointAlloc = alloc; } size = &family->pointSizes[family->numberOfPointSizes++]; size->size = pointSizeNum; } if (!size->faces[faceNum]) { face = FE_MALLOC_ZAP(fe_FontFace); if (!face) { return; } face->longXLFDFontName = strdup(pointSizeFontSpec); if (!face->longXLFDFontName) { free(face); return; } face->next = fe_FontFaceList; fe_FontFaceList = face; size->faces[faceNum] = face; } else { /* @@@ fix this -- erik */ /* (void) fprintf(real_stderr, "dup %s\n", pointSizeFontSpec); */ } } static void fe_AddFontFamily(fe_FontPitch *pitch, char *origFoundry, char *foundry, char *origFamily, char *familyName, int face, int pixelSize, int pointSize, char *pixelSizeFontSpec, char *pointSizeFontSpec, int charsetID, char *origCharset) { int alloc; fe_FontFamily *family; int i; char *name; fe_FontFamily *newFamilies; if (charsetID == CS_USRDEF2) { if (*foundry) { name = PR_smprintf("%s (%s, %s)", familyName, foundry, origCharset); } else { name = PR_smprintf("%s (%s)", familyName, origCharset); } } else { if (*foundry) { name = PR_smprintf("%s (%s)", familyName, foundry); } else { name = strdup(familyName); } } if (!name) { return; } family = NULL; if (pitch->families) { for (i = 0; i < pitch->numberOfFamilies; i++) { family = &pitch->families[i]; if (!strcmp(family->name, name)) { break; } else { family = NULL; } } } if (family) { free(name); } else { if (pitch->numberOfFamilies >= pitch->alloc) { alloc = (2 * (pitch->alloc + 1)); newFamilies = FE_REALLOC_ZAP(pitch->families, pitch->alloc, alloc, fe_FontFamily); if (!newFamilies) { free(name); return; } pitch->families = newFamilies; pitch->alloc = alloc; } family = &pitch->families[pitch->numberOfFamilies++]; family->name = name; family->family = strdup(origFamily); family->foundry = strdup(origFoundry); } fe_AddFontSize(family, face, pixelSize, pointSize, pixelSizeFontSpec, pointSizeFontSpec); } static void fe_AddFontCharSet(char *origFoundry, char *foundry, char *origFamily, char *family, int face, int pixelSize, int pointSize, int pitch, int charsetID, char *charset, char *charsetlang, char *pixelSizeFontSpec, char *pointSizeFontSpec, char *origCharset) { char mimeName[128]; char *name; if ((charsetID < 0) || (charsetID >= INTL_CHAR_SET_MAX)) { return; } if (!fe_FontCharSets[charsetID].name) { if (charsetID == CS_USRDEF2) { name = strdup(XP_GetString(XFE_USER_DEFINED)); } else { name = PR_smprintf("%s (%s)", charsetlang, charset); } if (!name) { return; } fe_FontCharSets[charsetID].name = name; INTL_CharSetIDToName(charsetID, mimeName); fe_FontCharSets[charsetID].mimeName = strdup(mimeName); if (!fe_FontCharSets[charsetID].mimeName) { return; } } if (pitch & fe_FONT_PITCH_PROPORTIONAL) { fe_AddFontFamily(&fe_FontCharSets[charsetID].pitches[0], origFoundry, foundry, origFamily, family, face, pixelSize, pointSize, pixelSizeFontSpec, pointSizeFontSpec, charsetID, origCharset); } if (pitch & fe_FONT_PITCH_MONO) { fe_AddFontFamily(&fe_FontCharSets[charsetID].pitches[1], origFoundry, foundry, origFamily, family, face, pixelSize, pointSize, pixelSizeFontSpec, pointSizeFontSpec, charsetID, origCharset); } } static char * fe_PropOrFixedFont(int i) { return i == 0 ? "prop" : "fixed"; } #define FE_INDEX_TO_FACE(face) (face == 0 ? "normal" : face == 1 ? "bold" : \ face == 2 ? "italic" : "boldItalic") #ifdef FE_PRINT_FONTS static void fe_PrintFamily(fe_FontFamily *family) { fe_FontFace *face; int i; int j; fe_FontSize *size; (void) fprintf(real_stderr, " %s\n", family->name); for (i = 0; i < family->numberOfPointSizes; i++) { size = &family->pointSizes[i]; (void) fprintf(real_stderr, " %d\n", size->size / 10); for (j = 0; j < 4; j++) { (void) fprintf(real_stderr, " %s\n", FE_INDEX_TO_FACE(j)); face = size->faces[j]; (void) fprintf(real_stderr, " %s\n", face->longXLFDFontName); } } } static void fe_PrintFonts(void) { fe_FontCharSet *charset; int i; int j; int k; fe_FontPitch *pitch; for (i = 0; i < INTL_CHAR_SET_MAX; i++) { charset = &fe_FontCharSets[i]; if (!charset->name) { continue; } (void) fprintf(real_stderr, "%s\n", charset->name); for (j = 0; j < 2; j++) { (void) fprintf(real_stderr, " %s\n", fe_PropOrFixedFont(j)); pitch = &charset->pitches[j]; for (k = 0; k < pitch->numberOfFamilies; k++) { fe_PrintFamily(&pitch->families[k]); } } } } #endif /* FE_PRINT_FONTS */ static int fe_CompareFontCharSets(unsigned char *charset1, unsigned char *charset2) { char *name1; char *name2; name1 = fe_FontCharSets[*charset1].name; name2 = fe_FontCharSets[*charset2].name; if (!name1) { if (!name2) { return 0; } return 1; } if (!name2) { return -1; } return strcmp(name1, name2); } static int fe_CompareFontFamilies(fe_FontFamily *family1, fe_FontFamily *family2) { return strcmp(family1->name, family2->name); } static int fe_CompareFontSizes(fe_FontSize *size1, fe_FontSize *size2) { return size1->size - size2->size; } typedef int (*fe_CompFunc)(const void *, const void *); static void fe_SortFonts(void) { fe_FontCharSet *charset; fe_FontFamily *family; int i; int j; int k; fe_FontPitch *pitch; for (i = 0; i < INTL_CHAR_SET_MAX; i++) { fe_SortedFontCharSets[i] = i; } XP_QSORT(fe_SortedFontCharSets, INTL_CHAR_SET_MAX, sizeof(*fe_SortedFontCharSets), (fe_CompFunc) fe_CompareFontCharSets); for (i = 0; i < INTL_CHAR_SET_MAX; i++) { charset = &fe_FontCharSets[i]; if (!charset->name) { continue; } for (j = 0; j < 2; j++) { pitch = &charset->pitches[j]; if (pitch->families) { XP_QSORT(pitch->families, pitch->numberOfFamilies, sizeof(fe_FontFamily), (fe_CompFunc) fe_CompareFontFamilies); } for (k = 0; k < pitch->numberOfFamilies; k++) { family = &pitch->families[k]; XP_QSORT(family->pixelSizes, family->numberOfPixelSizes, sizeof(fe_FontSize), (fe_CompFunc) fe_CompareFontSizes); XP_QSORT(family->pointSizes, family->numberOfPointSizes, sizeof(fe_FontSize), (fe_CompFunc) fe_CompareFontSizes); } } } } void fe_ReadFontCharSet(char *charsetname) { fe_FontCharSet *charset; int16 charsetID; int i; charsetID = (INTL_CharSetNameToID(charsetname) & 0xff); if ((charsetID < 0) || (charsetID >= INTL_CHAR_SET_MAX)) { charsetID = CS_LATIN1; } charsetID &= 0xff; for (i = 0; i < INTL_CHAR_SET_MAX; i++) { fe_FontCharSets[i].selected = 0; } charset = &fe_FontCharSets[charsetID]; if (charset->name) { charset->selected = 1; } else { charset = NULL; for (i = 0; i < INTL_CHAR_SET_MAX; i++) { charset = &fe_FontCharSets[i]; if (!charset->name) { charset = NULL; continue; } charset->selected = 1; break; } } if (!charset) { /* this should never happen */ (void) fprintf(real_stderr, "no recognized font charsets!\n"); exit(1); } } void fe_ReadFontSpec(char *spec) { fe_FontCharSet *charset; char *charSetName; fe_FontFamily *family; char *familyName; char *foundry; int i; int j; int k; int m; char *p; fe_FontPitch *pitch; char *pitchName; char *s; char *scaling; fe_FontSize *size; char *sizeName; int sizeNum; s = strdup(spec); if (!s) { return; } p = s; foundry = p; p = strchr(p, '-'); if (!p) { return; } *p++ = 0; familyName = p; p = strchr(p, '-'); if (!p) { return; } *p++ = 0; sizeName = p; p = strchr(p, '-'); if (!p) { return; } *p++ = 0; (void) sscanf(sizeName, "%d", &sizeNum); scaling = p; p = strchr(p, '-'); if (!p) { return; } *p++ = 0; pitchName = p; p = strchr(p, '-'); if (!p) { return; } *p++ = 0; charSetName = p; for (i = 0; i < INTL_CHAR_SET_MAX; i++) { charset = &fe_FontCharSets[i]; if ((!charset->name) || strcmp(charset->mimeName, charSetName)) { continue; } j = (*pitchName == 'p' ? 0 : 1); pitch = &charset->pitches[j]; family = NULL; for (k = 0; k < pitch->numberOfFamilies; k++) { family = &pitch->families[k]; if ((!strcmp(family->foundry, foundry)) && (!strcmp(family->family, familyName))) { break; } else { family = NULL; } } if (family) { for (k = 0; k < pitch->numberOfFamilies; k++) { pitch->families[k].selected = 0; } family->selected = 1; pitch->selectedFamily = family; family->allowScaling = (((*scaling) == 's') ? 1 : 0); /* * sanity check */ if (family->pointSizes->size) { family->allowScaling = 0; } else if (family->numberOfPointSizes == 1) { family->allowScaling = 1; } size = NULL; for (m = 0; m < family->numberOfPointSizes; m++) { size = &family->pointSizes[m]; if (size->size == sizeNum) { break; } else { size = NULL; } } if (size) { for (m = 0; m < family->numberOfPointSizes; m++) { family->pointSizes[m].selected = 0; } size->selected = 1; } else if (family->allowScaling) { for (m = 0; m < family->numberOfPointSizes; m++) { family->pointSizes[m].selected = 0; } family->pointSizes[0].selected = 1; family->scaledSize = sizeNum; } } break; } free(s); } static fe_FontSize * fe_GetScaledFontSize(fe_FontFamily *family, double idealSize, XP_Bool make_global) { fe_FontFace *face; int i; fe_FontSize *ret; ret = FE_MALLOC_ZAP(fe_FontSize); if (!ret) { return NULL; } if (make_global) { ret->next = fe_FontSizeList; fe_FontSizeList = ret; } ret->size = idealSize; for (i = 0; i < 4; i++) { ret->faces[i] = FE_MALLOC_ZAP(fe_FontFace); face = ret->faces[i]; if (!face) { return NULL; } if (make_global) { face->next = fe_FontFaceList; fe_FontFaceList = face; } face->longXLFDFontName = PR_smprintf( family->pointSizes->faces[i]->longXLFDFontName, ret->size); if (!face->longXLFDFontName) { return NULL; } } return ret; } static fe_FontSize * fe_FindFontPointSize(fe_FontFamily *family, double idealSize, XP_Bool search_for_fit, XP_Bool scale_to_fit) { int i; double minDist; fe_FontSize *minSize; fe_FontSize *maxSize; double newDist; fe_FontSize *ret; fe_FontSize *size; ret = NULL; if (! family->pointSizes) return NULL; if (family->pointSizes->size == 0) { minSize = &family->pointSizes[1]; } else { minSize = family->pointSizes; } maxSize = &family->pointSizes[family->numberOfPointSizes - 1]; if ((idealSize < minSize->size) || (idealSize > maxSize->size)) { if (idealSize > maxSize->size) { ret = maxSize; } if (idealSize < minSize->size) { ret = minSize; } } else { minDist = (1E+36); ret = family->pointSizes; for (i = 0; i < family->numberOfPointSizes; i++) { size = &family->pointSizes[i]; newDist = ((idealSize - size->size) * (idealSize - size->size)); if (newDist < minDist) { minDist = newDist; ret = size; } else { break; } } } if (search_for_fit) { minDist = (ret) ? ((idealSize - ret->size) * (idealSize - ret->size)) : (1E+36); for (size = family->pool; size; size = size->next) { newDist = ((idealSize - size->size) * (idealSize - size->size)); if (newDist < minDist) { minDist = newDist; ret = size; } } } if (scale_to_fit) { /* We have deliberately first searched through the array * of HTML point sizes for a match within 1/2 point of the * requested point size because we prefer hand-tuned bitmaps * to scaled outlines, all other things being equal. */ minDist = (ret) ? ((idealSize - ret->size) * (idealSize - ret->size)) : (1E+36); if (0 == family->pointSizes->size && minDist > 0.25) { size = fe_GetScaledFontSize(family, idealSize, False); if (size) { /* mark to be freed when the context expires */ size->in_pool = 1; /* hang off of the family */ size->next = family->pool; family->pool = size; ret = size; } } } return ret; } static fe_FontSize * fe_ComputeFontSize(fe_FontFamily *family, double idealSize) { if (family->allowScaling) return fe_GetScaledFontSize(family, idealSize, True); /* Pass False for scale_to_fit: fe_ComputeFontSize * is used only to compute the table of HTML sizes. * In integrating the range of sizes allowed by CSS-1, we want * no perturbation of font sizes as they are instantiated through * HTML size requests. Therefore, offer to scale outline fonts * in the construction of the HTML size table only when the * allowScaling flag is set for that particular family, as was * the case prior to CSS-1. */ return fe_FindFontPointSize(family, idealSize, False, False); } void fe_FreeFontGroups(void) { #if 0 fe_FontCharSet *charset; fe_FontFace *face; int i; int j; int k; int m; fe_FontPitch *pitch; fe_FontSize *size; for (i = 0; i < INTL_CHAR_SET_MAX; i++) { charset = &fe_FontCharSets[i]; if (fe_CharSetInfoArray[i].type == FE_FONT_TYPE_GROUP) { for (j = 0; j < 2; j++) { pitch = &charset->pitches[j]; if (!pitch->selectedFamily) { continue; } for (k = 0; k < 7; k++) { size = pitch->selectedFamily->htmlSizes[k]; if (size) { for (m = 0; m < 4; m++) { face = size->faces[m]; if (face) { free(face); } } free(size); } } free(pitch->selectedFamily); pitch->selectedFamily = NULL; } } } #endif } void fe_FreeUnicodeFonts(void) { fe_FontCharSet *charset; fe_FontFace *face; int i_pitch, i_htmlsize, i_face, i_encodings; fe_FontPitch *pitch; fe_FontSize *size; fe_UnicodePseudoFont *ufont; charset = &fe_FontCharSets[CS_UTF8&0xFF]; for (i_pitch = 0; i_pitch < 2; i_pitch++) { pitch = &charset->pitches[i_pitch]; if (!pitch->selectedFamily) continue; for (i_htmlsize = 0; i_htmlsize < 7; i_htmlsize++) { size = pitch->selectedFamily->htmlSizes[i_htmlsize]; if (!size) continue; for (i_face = 0; i_face < 4; i_face++) { face = size->faces[i_face]; if (!face) continue; if (!face->font) continue; ufont = (fe_UnicodePseudoFont *)face->font; if (ufont->tag != UNICODE_PSEUDO_FONT_TAG) { continue; } for (i_encodings=0; i_encodingsxfont_scaled[i_encodings]) { XFreeFont(ufont->dpy, ufont->xFonts[i_encodings]); XP_FREE(ufont->xfont_name[i_encodings]); } ufont->xfont_inited[i_encodings] = FALSE; ufont->xfont_scaled[i_encodings] = FALSE; ufont->xfont_name[i_encodings] = NULL; ufont->larger_fonts_avail[i_encodings] = FALSE; if (ufont->xmfontlist) XmFontListFree(ufont->xmfontlist); ufont->xmfontlist = NULL; if (ufont->xm_fontset) XmFontListFree(ufont->xm_fontset); ufont->xm_fontset = NULL; if (ufont->xfontset) XFreeFontSet(ufont->dpy, ufont->xfontset); ufont->xfontset = NULL; } } } } } void fe_FreeFontSizeTable(fe_FontFamily *family) { int k,m; fe_FontSize *size; fe_FontFace *face; if (!family->htmlSizesComputed) return; family->htmlSizesComputed = 0; /* * Only the scaled fonts were allocated new sizes. Hence we free * only them. */ if (!family->allowScaling) return; for (k = 0; k < 7; k++) { size = family->htmlSizes[k]; if (size) { for (m = 0; m < 4; m++) { face = size->faces[m]; if (face) { free(face); } } free(size); family->htmlSizes[k] = NULL; } } } void fe_ComputeFontSizeTable(fe_FontFamily *family) { int i; double idealSize; int j; fe_FontSize *size; int size3; size = NULL; /* * first, find the size selected within the family */ for (j = 0; j < family->numberOfPointSizes; j++) { size = &family->pointSizes[j]; if (size->selected) { break; } else { size = NULL; } } if ((!family) || (!size)) { /* this should not happen */ return; } fe_FreeFontGroups(); fe_FreeFontSizeTable(family); /* * set the default size (3) */ size3 = size->size; if (!size3) { size3 = family->scaledSize; } if (!size3) { size3 = 120; } i = 3; idealSize = size3; family->htmlSizes[i - 1] = fe_ComputeFontSize(family, idealSize); /* * set the higher sizes (4-7) */ for (i = 4; i <= 7; i++) { idealSize = ((1 + ((i - 3) * fe_FontSizeIncrement)) * size3); family->htmlSizes[i - 1] = fe_ComputeFontSize(family, idealSize); } /* * set the lower sizes (1-2) */ for (i = 1; i <= 2; i++) { idealSize = ((1 - ((3 - i) * fe_FontSizeIncrement)) * size3); if (idealSize < 10) { idealSize = 10; } family->htmlSizes[i - 1] = fe_ComputeFontSize(family, idealSize); } /* * mark family that htmlSizes has been computed. */ family->htmlSizesComputed = 1; /* @@@ need to implement this in case any of the scaled * sizes couldn't be malloc'ed -- erik * fe_CheckFonts(); */ } static int fe_CloneFamily(fe_FontFamily *cloneFamily, fe_FontFamily *origFamily) { int i; cloneFamily->name = strdup(origFamily->name); cloneFamily->foundry = strdup(origFamily->foundry); cloneFamily->family = strdup(origFamily->family); if ((!cloneFamily->name) || (!cloneFamily->foundry) || (!cloneFamily->family)) { return 0; } cloneFamily->selected = origFamily->selected; cloneFamily->allowScaling = origFamily->allowScaling; cloneFamily->pointAlloc = origFamily->pointAlloc; cloneFamily->numberOfPointSizes = origFamily->numberOfPointSizes; cloneFamily->pointSizes = XP_CALLOC(cloneFamily->pointAlloc, sizeof(fe_FontSize)); if (!cloneFamily->pointSizes) { return 0; } for (i = 0; i < cloneFamily->numberOfPointSizes; i++) { cloneFamily->pointSizes[i] = origFamily->pointSizes[i]; } if (origFamily->allowScaling) { /* * For scaled families, take care to copy the sizes and faces. * Setting this will make the sizes get recomputed. */ cloneFamily->htmlSizesComputed = 0; } else { cloneFamily->htmlSizesComputed = origFamily->htmlSizesComputed; for (i = 0; i < 7; i++) { cloneFamily->htmlSizes[i] = origFamily->htmlSizes[i]; } } return 1; } static int fe_ClonePitch(fe_FontPitch *clonePitch, fe_FontPitch *origPitch) { int i; clonePitch->alloc = origPitch->alloc; clonePitch->numberOfFamilies = origPitch->numberOfFamilies; clonePitch->families = XP_CALLOC(clonePitch->alloc, sizeof(fe_FontFamily)); if (!clonePitch->families) { return 0; } for (i = 0; i < clonePitch->numberOfFamilies; i++) { if (!fe_CloneFamily(&clonePitch->families[i], &origPitch->families[i])) { return 0; } } clonePitch->selectedFamily = NULL; return 1; } static void fe_SetDefaultFontSettings(Display *dpy) { fe_FontCharSet *charset; char *charsetname; char clas[512]; XrmDatabase db; fe_FontFace **faces; fe_FontFamily *family; int i; int j; int k; int m; char name[512]; fe_FontPitch *pitch; fe_FontSize *size; char *spec; char *type; XrmValue value; db = XtDatabase(dpy); /* * try to get the default charset from the resources */ (void) PR_snprintf(clas, sizeof(clas), "%s.DocumentFonts.DefaultCharSet", fe_progclass); (void) PR_snprintf(name, sizeof(name), "%s.documentFonts.defaultCharSet", fe_progclass); if (XrmGetResource(db, name, clas, &type, &value)) { charsetname = (char *) value.addr; } else { charsetname = "iso-8859-1"; } fe_ReadFontCharSet(charsetname); /* * try to get the default fonts from the resources */ for (i = 0; i < INTL_CHAR_SET_MAX; i++) { charset = &fe_FontCharSets[i]; if (!charset->name) { continue; } for (j = 0; j < 2; j++) { (void) PR_snprintf(clas, sizeof(clas), "%s.DocumentFonts.DefaultFont.CharSet.Pitch", fe_progclass); (void) PR_snprintf(name, sizeof(name), "%s.documentFonts.defaultFont.%s.%s", fe_progclass, charset->mimeName, fe_PropOrFixedFont(j)); if (XrmGetResource(db, name, clas, &type, &value)) { spec = PR_smprintf("%s-%s-%s", (char *) value.addr, fe_PropOrFixedFont(j), charset->mimeName); if (!spec) { continue; } fe_ReadFontSpec(spec); free(spec); } } } /* * make sure we have families set for each charset/pitch, * and sizes set for each family */ for (i = 0; i < INTL_CHAR_SET_MAX; i++) { charset = &fe_FontCharSets[i]; if (!charset->name) { continue; } for (j = 0; j < 2; j++) { pitch = &charset->pitches[j]; for (k = 0; k < pitch->numberOfFamilies; k++) { family = &pitch->families[k]; for (m = 0; m < family->numberOfPointSizes; m++) { faces = family->pointSizes[m].faces; if (!faces[0]) { if (faces[1]) { faces[0] = faces[1]; } else if (faces[2]) { faces[0] = faces[2]; } else { faces[0] = faces[3]; } } if (!faces[1]) { if (faces[3]) { faces[1] = faces[3]; } else if (faces[2]) { faces[1] = faces[2]; } else { faces[1] = faces[0]; } } if (!faces[2]) { if (faces[3]) { faces[2] = faces[3]; } else if (faces[1]) { faces[2] = faces[1]; } else { faces[2] = faces[0]; } } if (!faces[3]) { if (faces[1]) { faces[3] = faces[1]; } else if (faces[2]) { faces[3] = faces[2]; } else { faces[3] = faces[0]; } } } /* * make sure a size is selected for each family */ size = NULL; for (m = 0; m < family->numberOfPointSizes; m++) { size = &family->pointSizes[m]; if (size->selected) { break; } else { size = NULL; } } if ((!size) && family->numberOfPointSizes) { size = &family->pointSizes [(family->numberOfPointSizes+1)/2-1]; size->selected = 1; } /* * determine whether or not we allow scaling * from the available sizes */ if ((family->numberOfPointSizes == 1) && (family->pointSizes->size == 0)) { family->allowScaling = 1; } } /* * make sure a family is selected for each pitch */ family = NULL; for (k = 0; k < pitch->numberOfFamilies; k++) { family = &pitch->families[k]; if (family->selected) { break; } else { family = NULL; } } if ((!family) && pitch->numberOfFamilies) { family = &pitch->families[0]; family->selected = 1; } /* Force recomputation */ if (family) fe_FreeFontSizeTable(family); } /* * if some charset has fonts in one pitch, but not the * other, we clone the one that is available, so that * we always have a pitch available */ if (!charset->pitches[0].families) { if (!fe_ClonePitch(&charset->pitches[0], &charset->pitches[1])) { /* * if we can't clone the pitch, we * disable the whole charset */ free(charset->name); charset->name = NULL; } } else if (!charset->pitches[1].families) { if (!fe_ClonePitch(&charset->pitches[1], &charset->pitches[0])) { /* * if we can't clone the pitch, we * disable the whole charset */ free(charset->name); charset->name = NULL; } } } } static void fe_ReportFontCharSets(void) { fe_FontCharSet *charset; int16 *charsets; int i; int j; charsets = calloc(INTL_CHAR_SET_MAX, sizeof(*charsets)); if (!charsets) { return; } j = 0; for (i = 1; i < INTL_CHAR_SET_MAX; i++) { charset = &fe_FontCharSets[i]; if (!charset->name) { continue; } charsets[j++] = fe_CharSetInfoArray[i].charsetID; } INTL_ReportFontCharSets(charsets); } static fe_Font fe_LoadXFont(Display *dpy, char *name) { XFontStruct *f; f = XLoadQueryFont(dpy, name); if (f) { /* * The width check is from xemacs. * The ascent check is from Sun's AWT. */ if ((!f->max_bounds.width) || (f->ascent < 0)) { XFreeFont(dpy, f); f = NULL; } } return (fe_Font) f; } static float default_UnicodePseudoFontSizes[] = { 0.0, 8.0, 9.0, 10.0, 11.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0, 28.0, 32.0, 36.0, 48.0, 60.0, 72.0, }; static float* UnicodePseudoFontSizes = default_UnicodePseudoFontSizes; static int num_UnicodePseudoFontSizes = sizeof(default_UnicodePseudoFontSizes)/sizeof(float*); static char * fe_generatePixelSizeFontSpec( int pixelSizeNum, char *origFoundry, char *origFamily, char *origWeight, char *avgwidth, char *origCharset) { char *pixelSizeFontSpec; /* * Note: * origWeight has 2 values * origCharset has 2 values */ #ifdef SOLARIS if (pixelSizeNum) { pixelSizeFontSpec = PR_smprintf( "-%s-%s-%s-*-*-%d-*-*-*-*-%s-%s", origFoundry, origFamily, origWeight, pixelSizeNum, avgwidth, origCharset); } else { pixelSizeFontSpec = PR_smprintf( "-%s-%s-%s-*-*-%%d-*-*-*-*-%s-%s", origFoundry, origFamily, origWeight, avgwidth, origCharset); } #else /* SOLARIS */ if (pixelSizeNum) { pixelSizeFontSpec = PR_smprintf( "-%s-%s-%s-*-*-%d-*-*-*-*-*-%s", origFoundry, origFamily, origWeight, pixelSizeNum, origCharset); } else { pixelSizeFontSpec = PR_smprintf( "-%s-%s-%s-*-*-%%d-*-*-*-*-*-%s", origFoundry, origFamily, origWeight, origCharset); } #endif /* SOLARIS */ return pixelSizeFontSpec; } static char * fe_generatePointSizeFontSpec( int pointSizeNum, char *origFoundry, char *origFamily, char *origWeight, char *xResolution, char *yResolution, char *avgwidth, char *origCharset) { char *pointSizeFontSpec; /* * Note: * origWeight has 2 values * origCharset has 2 values */ #ifdef SOLARIS if (pointSizeNum) { pointSizeFontSpec = PR_smprintf( "-%s-%s-%s-*-*-*-%d-%s-%s-*-%s-%s", origFoundry, origFamily, origWeight, pointSizeNum, xResolution, yResolution, avgwidth, origCharset); } else { pointSizeFontSpec = PR_smprintf( "-%s-%s-%s-*-*-*-%%d-%s-%s-*-%s-%s", origFoundry, origFamily, origWeight, xResolution, yResolution, avgwidth, origCharset); } #else /* SOLARIS */ if (pointSizeNum) { pointSizeFontSpec = PR_smprintf( "-%s-%s-%s-*-*-*-%d-%s-%s-*-*-%s", origFoundry, origFamily, origWeight, pointSizeNum, xResolution, yResolution, origCharset); } else { pointSizeFontSpec = PR_smprintf( "-%s-%s-%s-*-*-*-%%d-%s-%s-*-*-%s", origFoundry, origFamily, origWeight, xResolution, yResolution, origCharset); } #endif /* SOLARIS */ return pointSizeFontSpec; } /* * fe_loadUnicodePseudoFonts * * At this time, Sept. 1996, Unicode fonts are not * available for Unix. To display (size) a Unicode string * we convert the Unicode string to a series substrings each * of which is converted in a locally displayable encoding. * We then display (size) each substring using a standard * X font from a this Unicode Pseudo font. * * A Unicode Pseudo font is therefore an array of X fonts * each of the given size/pitch/weight for this font with one * one X font per encoding. * * In loading these Unicode Pseudo fonts we pretend to * to have these Unicode fonts available and fill in the master * font table. Actually checking for a X font for each * for each size/pitch/weight/encoding would require loading * a huge number of fonts. * * 11 sizes * 2 pitches * 2 weights * 35 encodings = 1540 fonts * * Because of the large number of fonts and the fact that asian * fonts are large (1M per font) and the fact we might ask for * scaling this loading time could be in the order of * several minutes. During this font loading time the X server * appears to freeze and this is quite distressing to the user. * * HENCE BECAUSE OF THE UNACCEPTABLE LOADING DELAYS * WE JUST ASSUME THE UNICODE FONTS ARE AVAILABLE. * * Even when we begin using a Unicode Pseudo font we only * load the X fonts for the encodings that have actually been * seen. Just loading X fonts for all the encodings for a given * size/pitch/weight requires a large number of X fonts. * * 11 sizes * 2 pitches * 2 weights = 44 X fonts * */ static void fe_loadUnicodePseudoFonts(Display *dpy, char *my_origFamily, int my_pitch) { int i, j; char *my_origFoundry = "nsPseudoFont"; char *my_foundry = my_origFoundry; char *my_family = my_origFamily; int my_face; int my_pointSizeNum; int my_pixelSizeNum; int16 my_charsetID = CS_UTF8 & 0xFF; char *my_origCharset = "unicode-2-0"; char *my_charset = my_origCharset; char *my_charsetlang = "unicode-2-0"; char *my_pixelSizeFontSpec = NULL; char *my_pointSizeFontSpec = NULL; char *my_origWeight; char *my_avgwidth = "*"; char *my_xResolution = "*"; char *my_yResolution = "*"; char name[512], clas[512]; char *type; XrmValue value; XrmDatabase db = XtDatabase(dpy); /* Family name */ (void) PR_snprintf(name, sizeof(name), "%s.documentFonts.family.%s", fe_progclass, my_origFamily); (void) PR_snprintf(clas, sizeof(clas), "%s.DocumentFonts.Family.Name", fe_progclass); if (XrmGetResource(db, name, clas, &type, &value)) my_family = (char *) value.addr; /* Foundry name */ (void) PR_snprintf(name, sizeof(name), "%s.documentFonts.foundry.%s", fe_progclass, my_origFoundry); (void) PR_snprintf(clas, sizeof(clas), "%s.DocumentFonts.Foundry.Name", fe_progclass); if (XrmGetResource(db, name, clas, &type, &value)) my_foundry = (char *) value.addr; /* CharsetLang name */ (void) PR_snprintf(name, sizeof(name), "%s.documentFonts.charsetlang.%s", fe_progclass, my_charsetlang); (void) PR_snprintf(clas, sizeof(clas), "%s.DocumentFonts.CharSetLang.Name", fe_progclass); if (XrmGetResource(db, name, clas, &type, &value)) my_charsetlang = (char *) value.addr; /* * Create the Pseudo font sizes */ for (i=0; i/dynfonts * /usr/local/lib/netscape/dynfonts * * According to our webfont implementation, if a font displayer with * the same name exists in more than one directory, then the * first one takes priority. */ /* WF_FONT_DISPLAYER_PATH_1 */ pathname = fe_GetConfigDirFilename("dynfonts"); nffbp_ScanForFontDisplayers(fbp, pathname, NULL); free(pathname); /* WF_FONT_DISPLAYER_PATH_2 */ if (mozilla_home = getenv("MOZILLA_HOME")) { /* Form "$MOZILLA_HOME/dynfonts" into buf */ strncpy(buf, mozilla_home, sizeof(buf)-1); strncat(buf, dynfonts_str, sizeof(buf)-1 - strlen(buf)); buf[sizeof(buf)-1] = '\0'; nffbp_ScanForFontDisplayers(fbp, buf, NULL); } /* WF_FONT_DISPLAYER_PATH_3 */ /* Form "/dynfonts" into buf */ buf[0] = '\0'; fe_GetProgramDirectory(buf, sizeof(buf)-1); if (buf[0]) { strncat(buf, dynfonts_str_no_slash, sizeof(buf)-1 - strlen(buf)); buf[sizeof(buf)-1] = '\0'; nffbp_ScanForFontDisplayers(fbp, buf, NULL); } /* WF_FONT_DISPLAYER_PATH_4 */ nffbp_ScanForFontDisplayers(fbp, WF_FONT_DISPLAYER_PATH_4, NULL); } #endif void fe_InitFonts(Display *dpy) { char *avgwidth = NULL; #ifdef SOLARIS int avgWidthNum; #endif char *charset; int16 charsetID; char *charsetlang; char clas[512]; int count; XrmDatabase db; int face; char *family; char *font; char **fonts; char *foundry; int i; int j; char name[512]; char *origCharset; char *origFamily; char *origFoundry; char *origWeight; /* note: has weight and slant */ char *p; int pitch; char *pixelSize; char *pixelSizeFontSpec; int pixelSizeNum; char *pointSize; char *pointSizeFontSpec; int pointSizeNum; char *resx; char *setwidth; char *spacing; char *type; XrmValue value; char *weight; char *xResolution; char *yResolution; #ifdef SOLARIS avgwidth = NULL; #endif charset = NULL; charsetlang = NULL; family = NULL; font = NULL; fonts = NULL; foundry = NULL; origCharset = NULL; origFamily = NULL; origFoundry = NULL; origWeight = NULL; p = NULL; pixelSize = NULL; pixelSizeFontSpec = NULL; pointSize = NULL; pointSizeFontSpec = NULL; resx = NULL; setwidth = NULL; spacing = NULL; type = NULL; weight = NULL; xResolution = NULL; yResolution = NULL; #ifndef NO_WEB_FONTS /* Initialize font library */ fe_InitializeWebfonts(); #endif /* * do this first so that we are very likely to have this * font available if/when we fail to load any other font */ fe_FixedFont = fe_LoadXFont(dpy, "fixed"); fe_GetLocaleCharSets(dpy); #ifdef DEBUG if (sizeof(fe_CharSetInfoArray) / sizeof(*fe_CharSetInfoArray) != INTL_CHAR_SET_MAX) { (void) fprintf(real_stderr, "fe_CharSetInfoArray broken (size)\n"); #if 0 /* to fix 93446 */ fe_Exit(1); #endif } for (i = 0; i < INTL_CHAR_SET_MAX; i++) { if ((fe_CharSetInfoArray[i].charsetID & 0xff) != i) { (void) fprintf(real_stderr, "fe_CharSetInfoArray broken (%d)\n", i); #if 0 /* to fix 93446 */ fe_Exit(1); #endif } } #endif /* DEBUG */ fonts = XListFonts(dpy, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", INT_MAX, &count); if (!fonts) { return; } (void) memset(fe_FontCharSets, 0, sizeof(fe_FontCharSets)); db = XtDatabase(dpy); for (i = 0; i < count; i++) { FE_MAYBE_FREE(font); FE_MAYBE_FREE(origCharset); FE_MAYBE_FREE(origFamily); FE_MAYBE_FREE(origWeight); FE_MAYBE_FREE(pixelSizeFontSpec); FE_MAYBE_FREE(pointSizeFontSpec); /* ignore the non-XLFD short names */ if ((!fonts[i]) || (fonts[i][0] != '-')) { continue; } font = strdup(fonts[i]); if (!font) { continue; } p = font; j = 0; while (1) { p = strchr(p, '-'); if (!p) { break; } p++; switch (j) { case 0: foundry = p; break; case 1: family = p; break; case 2: weight = p; break; case 4: setwidth = p; break; case 6: pixelSize = p; break; case 7: pointSize = p; break; case 8: resx = p; break; case 10: spacing = p; break; #ifdef SOLARIS case 11: avgwidth = p; break; #endif case 12: charset = p; break; default: break; } j++; } if (j < 14) { /* skip non-XLFD names */ continue; } /* Skip Applix fonts -- if these are installed, there are hundreds of them, and they do not have proper XLFD names: the bold/italic/etc versions of the fonts have different *families* as well ("axhvr" for Helvetica-normal, "axhvb" for Helvetica-bold, etc) so all they do is bloat the menus and make the UI unusable. */ if (family && strncasecomp(family, "ax", 2) && XP_STRLEN(family) == 5) continue; (void) PR_snprintf(clas, sizeof(clas), "%s.DocumentFonts.Foundry.Name", fe_progclass); family[-1] = 0; (void) PR_snprintf(name, sizeof(name), "%s.documentFonts.foundry.%s", fe_progclass, foundry); origFoundry = strdup(foundry); if (!origFoundry) { continue; } if (XrmGetResource(db, name, clas, &type, &value)) { foundry = strdup((char *) value.addr); } else { foundry = fe_CapitalizeFontName(foundry); } if (!foundry) { continue; } (void) PR_snprintf(clas, sizeof(clas), "%s.DocumentFonts.Family.Name", fe_progclass); weight[-1] = 0; (void) PR_snprintf(name, sizeof(name), "%s.documentFonts.family.%s", fe_progclass, family); origFamily = strdup(family); if (!origFamily) { continue; } if (XrmGetResource(db, name, clas, &type, &value)) { family = strdup((char *) value.addr); } else { family = fe_CapitalizeFontName(family); } if (!family) { continue; } (void) PR_snprintf(clas, sizeof(clas), "%s.DocumentFonts.Face.Name", fe_progclass); setwidth[-1] = 0; (void) PR_snprintf(name, sizeof(name), "%s.documentFonts.face.%s", fe_progclass, weight); origWeight = strdup(weight); if (!origWeight) { continue; } if (XrmGetResource(db, name, clas, &type, &value)) { weight = (char *) value.addr; } else { #ifdef DEBUG_xxx (void) fprintf(real_stderr, "face %s\n", weight); #endif /* DEBUG_xxx */ weight = ""; } if (!strcmp(weight, "bold")) { face = 1; } else if (!strcmp(weight, "boldItalic")) { face = 3; } else if (!strcmp(weight, "italic")) { face = 2; } else { face = 0; } pointSize[-1] = 0; sscanf(pixelSize, "%d", &pixelSizeNum); if (pixelSizeNum < 0) { continue; } resx[-1] = 0; sscanf(pointSize, "%d", &pointSizeNum); if (pointSizeNum < 0) { continue; } switch (spacing[0]) { case 'm': pitch = fe_FONT_PITCH_MONO; break; case 'p': pitch = fe_FONT_PITCH_PROPORTIONAL; break; case 'c': /* fall through */ default: pitch = fe_FONT_PITCH_BOTH; break; } #ifdef SOLARIS charset[-1] = 0; sscanf(avgwidth, "%d", &avgWidthNum); if (avgWidthNum < 0) { continue; } #endif (void) PR_snprintf(clas, sizeof(clas), "%s.DocumentFonts.CharSet.Family.Name", fe_progclass); (void) PR_snprintf(name, sizeof(name), "%s.documentFonts.charset.%s.%s", fe_progclass, origFamily, charset); origCharset = strdup(charset); if (!origCharset) { continue; } charsetlang = charset; if (XrmGetResource(db, name, clas, &type, &value)) { charset = (char *) value.addr; } else { /* * if the user has messed with the app-defaults, we * might not be able to find our mapping, so check for * the following at least */ if (!strcmp(charset, "iso8859-1")) { charset = "iso-8859-1"; } #ifdef DEBUG else { (void) fprintf(real_stderr, "charset %s %s\n", origFamily, charsetlang); } #endif /* DEBUG */ } charsetID = (INTL_CharSetNameToID(charset) & 0xff); #ifdef SOLARIS if (charsetID == (CS_GB2312 & 0xff)) { /* * Simplified Chinese Solaris has broken fonts that * say GB2312 but are actually ASCII fonts. Skip 'em. */ if (avgWidthNum && (avgWidthNum == (pointSizeNum / 2))) { continue; } } else { avgwidth = "*"; } #endif /* SOLARIS */ #ifdef DEBUG if ((charsetID == CS_UNKNOWN) && strcmp(charset, "x-ignore")) { (void) fprintf(real_stderr, "internal %s %s %s\n", origFamily, charsetlang, charset); } #endif /* DEBUG */ if (!strcmp(charset, "x-ignore")) { charsetID = CS_USRDEF2; } if (charsetID >= INTL_CHAR_SET_MAX) { charsetID = CS_USRDEF2; } if (fe_CharSetInfoArray[charsetID].type == FE_FONT_TYPE_GROUP) { continue; } (void) PR_snprintf(clas, sizeof(clas), "%s.DocumentFonts.CharSetLang.Name", fe_progclass); (void) PR_snprintf(name, sizeof(name), "%s.documentFonts.charsetlang.%s", fe_progclass, charset); if (XrmGetResource(db, name, clas, &type, &value)) { charsetlang = (char *) value.addr; } else { #if 0 (void) fprintf(real_stderr, "charsetlang %s\n", charsetlang); #endif /* 0 */ charsetlang = XP_GetString(XFE_OTHER_LANGUAGE); } (void) PR_snprintf(clas, sizeof(clas), "%s.DocumentFonts.XResolution.CharSet", fe_progclass); (void) PR_snprintf(name, sizeof(name), "%s.documentFonts.xResolution.%s", fe_progclass, charset); if (XrmGetResource(db, name, clas, &type, &value)) { xResolution = (char *) value.addr; } else { xResolution = "*"; } (void) PR_snprintf(clas, sizeof(clas), "%s.DocumentFonts.YResolution.CharSet", fe_progclass); (void) PR_snprintf(name, sizeof(name), "%s.documentFonts.yResolution.%s", fe_progclass, charset); if (XrmGetResource(db, name, clas, &type, &value)) { yResolution = (char *) value.addr; } else { yResolution = "*"; } pixelSizeFontSpec = fe_generatePixelSizeFontSpec( pixelSizeNum, origFoundry, origFamily, origWeight, avgwidth, origCharset); if (!pixelSizeFontSpec) { continue; } pointSizeFontSpec = fe_generatePointSizeFontSpec( pointSizeNum, origFoundry, origFamily, origWeight, xResolution, yResolution, avgwidth, origCharset); if (!pointSizeFontSpec) { continue; } fe_AddFontCharSet(origFoundry, foundry, origFamily, family, face, pixelSizeNum, pointSizeNum, pitch, charsetID, charset, charsetlang, pixelSizeFontSpec, pointSizeFontSpec, origCharset); #if 0 (void) fprintf ( real_stderr, "\"%s\" \"%s\" \"%s\" %d \"%s%s\" %d \"%s\" \"%s\"\n\"%s\"\n", foundry, family, FE_INDEX_TO_FACE(face), pointSizeNum, ((pitch & fe_FONT_PITCH_MONO) ? "m" : ""), ((pitch & fe_FONT_PITCH_PROPORTIONAL) ? "p" : ""), charsetID, charset, charsetlang, pointSizeFontSpec ); #endif /* 0 */ free(origFoundry); free(foundry); free(family); } FE_MAYBE_FREE(font); FE_MAYBE_FREE(origCharset); FE_MAYBE_FREE(origFamily); FE_MAYBE_FREE(origWeight); FE_MAYBE_FREE(pixelSizeFontSpec); FE_MAYBE_FREE(pointSizeFontSpec); XFreeFontNames(fonts); (void) PR_snprintf(clas, sizeof(clas), "%s.DocumentFonts.SizeIncrement", fe_progclass); (void) PR_snprintf(name, sizeof(name), "%s.documentFonts.sizeIncrement", fe_progclass); if (XrmGetResource(db, name, clas, &type, &value)) { fe_FontSizeIncrement = (((double) atoi(value.addr)) / 100.0); if (fe_FontSizeIncrement <= 0) { fe_FontSizeIncrement = FE_DEFAULT_FONT_SIZE_INCREMENT; } } (void) PR_snprintf(clas, sizeof(clas), "%s.DocumentFonts.MaximumPoints", fe_progclass); (void) PR_snprintf(name, sizeof(name), "%s.documentFonts.maximumPoints", fe_progclass); if (XrmGetResource(db, name, clas, &type, &value)) { fe_FontMaximumPoints = atoi(value.addr); if (fe_FontMaximumPoints <= 0) fe_FontMaximumPoints = FE_DEFAULT_FONT_MAXIMUM_POINTS; } for (i=0; i < fe_GenericFamilyCount; i++) { (void) PR_snprintf(clas, sizeof(clas), "%s.DocumentFonts.Generic.%s", fe_progclass, fe_generics[i].class_name); (void) PR_snprintf(name, sizeof(name), "%s.documentFonts.generic.%s", fe_progclass, fe_generics[i].generic_name); if (XrmGetResource(db, name, clas, &type, &value)) fe_generics[i].family_name = strdup(value.addr); } fe_loadUnicodePseudoFonts(dpy, "helvetica", fe_FONT_PITCH_PROPORTIONAL); fe_loadUnicodePseudoFonts(dpy, "times", fe_FONT_PITCH_PROPORTIONAL); fe_loadUnicodePseudoFonts(dpy, "courier", fe_FONT_PITCH_MONO); fe_loadUnicodePseudoFonts(dpy, "fixed", fe_FONT_PITCH_MONO); fe_SortFonts(); fe_SetDefaultFontSettings(dpy); fe_ReportFontCharSets(); #ifdef FE_PRINT_FONTS fe_PrintFonts(); #endif } #ifdef DEBUG void fe_FreeFonts(void) { fe_FontCharSet *charset; fe_FontFace *face; fe_FontFamily *family; int i; int j; int k; fe_FontFace *nextFace; fe_FontPitch *pitch; for (i = 0; i < INTL_CHAR_SET_MAX; i++) { charset = &fe_FontCharSets[i]; if (!charset->name) { continue; } for (j = 0; j < 2; j++) { pitch = &charset->pitches[j]; for (k = 0; k < pitch->numberOfFamilies; k++) { family = &pitch->families[k]; free(family->name); free(family->foundry); free(family->family); free(family->pixelSizes); free(family->pointSizes); } free(pitch->families); } free(charset->name); free(charset->mimeName); } (void) memset(fe_FontCharSets, 0, sizeof(fe_FontCharSets)); face = fe_FontFaceList; while (face) { nextFace = face->next; if (face->longXLFDFontName) { free(face->longXLFDFontName); } if (face->font) { XFreeFont(fe_display, face->font); } face->loaded = FALSE; free(face); face = nextFace; } fe_FontFaceList = NULL; if (fe_FixedFont) { XFreeFont(fe_display, fe_FixedFont); fe_FixedFont = NULL; } } #endif /* DEBUG */ static void fe_AddFontSetting(fe_FontSettings **ret, fe_FontCharSet *charset, int i, fe_FontFamily *family, fe_FontSize *size) { fe_FontSettings *set; char *spec; spec = PR_smprintf ( "%s-%s-%d-%s-%s-%s\n", family->foundry, family->family, size->size, family->allowScaling ? "scale" : "noscale", fe_PropOrFixedFont(i), charset->mimeName ); set = FE_MALLOC_ZAP(fe_FontSettings); if ((!spec) || (!set)) { return; } set->spec = spec; set->next = *ret; *ret = set; } fe_FontSettings * fe_GetFontSettings(void) { fe_FontCharSet *charset; fe_FontFamily *family; int i; int j; int k; int m; fe_FontPitch *pitch; fe_FontSettings *ret; fe_FontSize *size; ret = NULL; for (i = 0; i < INTL_CHAR_SET_MAX; i++) { charset = &fe_FontCharSets[i]; if (!charset->name) { continue; } for (j = 0; j < 2; j++) { pitch = &charset->pitches[j]; for (k = 0; k < pitch->numberOfFamilies; k++) { family = &pitch->families[k]; if (family->selected) { for (m = 0; m < family->numberOfPointSizes; m++) { size = &family->pointSizes[m]; if (size->selected) { fe_AddFontSetting ( &ret, charset, j, family, size ); } } } } } } return ret; } void fe_SetFontSettings(fe_FontSettings *set) { } char * fe_GetFontCharSetSetting(void) { fe_FontCharSet *charset; int i; for (i = 0; i < INTL_CHAR_SET_MAX; i++) { charset = &fe_FontCharSets[i]; if (!charset->name) { continue; } if (charset->selected) { return charset->mimeName; } } return ""; } void fe_FreeFontSettings(fe_FontSettings *set) { fe_FontSettings *next; while (set) { next = set->next; free(set->spec); free(set); set = next; } } int fe_GetStrikePosition(int charset, fe_Font font) { int ascent; int descent; XCharStruct overall; /* * strike through the middle of lower case letters */ FE_TEXT_EXTENTS(charset, font, "a", 1, &ascent, &descent, &overall); return -((overall.ascent + 1) / 2); } int fe_GetUnderlinePosition(int charset) { /* * Underline position does not depend on font, otherwise you get * varying positions within a single line, and this looks bad. */ if ((fe_CharSetInfoArray[charset & 0xff].type == FE_FONT_TYPE_GROUP) || ((charset&0xFF) == (CS_UTF8&0xFF))) { /* * East Asian fonts have a lower baseline. * Underline looks better like this. */ return 3; } return 1; } static XP_Bool fe_AreNormalFontsAvail(int16 win_csid) { if (fe_FontCharSets[win_csid & 0xff].name != NULL) return TRUE; else return FALSE; } static fe_Font fe_LoadNormalFont(MWContext *context, char *familyName, int points, int sizeNum, int fontmask, int charset, int pitch, int faceNum, Display *dpy) { fe_FontFace *face; fe_Font font; fe_FontFamily *family = NULL; fe_FontSize *size; double decipoints; if (familyName && *familyName) { family = fe_FontFindFamily(charset, pitch, familyName); } if (!family) { family = fe_GetFontFamily(charset, pitch); if (!family) { return NULL; } } if (! points) size = family->htmlSizes[sizeNum-1]; else { decipoints = (double) (points * 10); size = fe_FindFontPointSize(family, decipoints, True, False); } if (!size) return NULL; face = size->faces[faceNum]; if (!face) return NULL; font = face->font; if (font) { return font; } else { font = fe_LoadXFont(dpy, face->longXLFDFontName); } if (font) { face->font = font; return font; } return NULL; } static XmFontList fe_GetFontListNormal(int16 charset, fe_Font font, int numOfFonts) { XmFontList fl; XmFontListEntry e; e = XmFontListEntryCreate("f0", XmFONT_IS_FONT, (XFontStruct*) font); XP_ASSERT(NULL != e); fl = XmFontListAppendEntry(NULL, e); XP_ASSERT(NULL != fl); XmFontListEntryFree(&e); return fl; } static XmString fe_ToXmStringNormal(int16 charset, fe_Font font, char * string, int len) { return XmStringCreate(string, "f0"); } void fe_GenericFontExtents(int charset, fe_Font font, int *fontAscent, int *fontDescent) { int ascent; int ascentExtra; int descent; int descentExtra; XFontStruct *f; fe_FontGroupFont *fonts; int i; int num; fe_CharSetInfo *info = &fe_CharSetInfoArray[(charset) & 0xff]; /* * Handle Unicode Pseudo Fonts */ if (info->info == FE_FONT_INFO_UNICODE) { fe_UnicodePseudoFont *ufont = (fe_UnicodePseudoFont *)font; if (ufont->tag != UNICODE_PSEUDO_FONT_TAG) { #ifdef DEBUG_bstell printf("bad ufont %s %d\n", __FILE__, __LINE__); #endif *(fontAscent) = 12; *(fontDescent) = 3; } (void)fe_UnicodeInitXfont(font, CS_LATIN1); *(fontAscent) = ufont->ascent; *(fontDescent) = ufont->descent; return; } /* * Handle EUC Fonts */ fonts = (fe_FontGroupFont *) font; ascent = 0; descent = 0; num = fe_CharSetFuncsArray[info->info].numberOfFonts; for (i = 0; i < num; i++) { if (i) { /* * East Asian text looks better with extra space for * underline. */ ascentExtra = 1; descentExtra = 2; } else { ascentExtra = 0; descentExtra = 0; } f = fonts[i].xFont; if (f) { if (f->ascent + ascentExtra > ascent) { ascent = f->ascent + ascentExtra; } if (f->descent + descentExtra > descent) { descent = f->descent + descentExtra; } } } *fontAscent = ascent; *fontDescent = descent; } #define FE_PROCESS_STRING_BUFFER_SIZE 1024 static void fe_ProcessEUCString(int charset, fe_StringProcessTable *table, fe_XDrawStringFunc draw1, fe_XDrawStringFunc draw2, Display *dpy, Drawable d, fe_Font fontGroup, GC gc, int x, int y, unsigned char *in, unsigned int inEnd, int *fontAscent, int *fontDescent, XCharStruct *overall, unsigned char numberOfFonts) { int ascent; int descent; int direction; fe_StringProcessTable *entry; fe_FontGroupFont *font; unsigned char fontIndex; fe_FontGroupFont *fonts; unsigned int inIndex; unsigned char len; unsigned char mask1; unsigned char mask2; XCharStruct metrics; unsigned char nextFontIndex; unsigned char out1[FE_PROCESS_STRING_BUFFER_SIZE]; XChar2b out2[FE_PROCESS_STRING_BUFFER_SIZE/2]; unsigned int out1Index; unsigned int out2Index; XChar2b *p; unsigned char skip; XFontStruct *xFont; if (inEnd > FE_PROCESS_STRING_BUFFER_SIZE) { inEnd = FE_PROCESS_STRING_BUFFER_SIZE; } fonts = (fe_FontGroupFont *) fontGroup; inIndex = 0; out1Index = 0; out2Index = 0; if (overall) { overall->lbearing = 0; overall->rbearing = 0; overall->width = 0; overall->ascent = 0; overall->descent = 0; } while (inIndex < inEnd) { entry = &table[in[inIndex]]; skip = entry->skip; len = entry->len; fontIndex = entry->fontIndex; font = &fonts[fontIndex]; xFont = font->xFont; if (gc && xFont) { XSetFont(dpy, gc, xFont->fid); } if (len == 1) { while (inIndex < inEnd) { inIndex += skip; if (inIndex >= inEnd) { break; } out1[out1Index++] = in[inIndex++]; if (inIndex >= inEnd) { break; } nextFontIndex = table[in[inIndex]].fontIndex; if (nextFontIndex != fontIndex) { break; } } if (out1Index && xFont) { XTextExtents(xFont, out1, out1Index, &direction, &ascent, &descent, &metrics); if (draw1) { (*draw1)(dpy, d, gc, x, y, out1, out1Index); } x += metrics.width; if (overall) { overall->width += metrics.width; if (metrics.ascent > overall->ascent) { overall->ascent = metrics.ascent; } if (metrics.descent > overall->descent) { overall->descent = metrics.descent; } } } out1Index = 0; } else { mask1 = font->mask1; mask2 = font->mask2; while (inIndex < inEnd) { inIndex += skip; if ((inIndex + 1) >= inEnd) { inIndex++; break; } p = &out2[out2Index++]; p->byte1 = (in[inIndex++] & mask1); p->byte2 = (in[inIndex++] & mask2); if (inIndex >= inEnd) { break; } nextFontIndex = table[in[inIndex]].fontIndex; if (nextFontIndex != fontIndex) { break; } } if (out2Index && xFont) { XTextExtents16(xFont, out2, out2Index, &direction, &ascent, &descent, &metrics); if (draw2) { (*draw2)(dpy, d, gc, x, y, (char *) out2, out2Index); } x += metrics.width; if (overall) { overall->width += metrics.width; if (metrics.ascent > overall->ascent) { overall->ascent = metrics.ascent; } if (metrics.descent > overall->descent) { overall->descent = metrics.descent; } } } out2Index = 0; } } if (overall) { /* @@@ fix */ overall->rbearing = overall->width; fe_GenericFontExtents(charset, fontGroup, fontAscent, fontDescent); } } static XmString fe_create_and_concatnate_XmString( XmString list, char* str, int len, char* flabel) { XmString ret; XmString seg = NULL; str[len++] = '\0'; if(NULL == list) return XmStringCreate(str, flabel); seg = XmStringCreate(str, flabel); XP_ASSERT(NULL != seg); ret = XmStringConcat(list, seg); XP_ASSERT(NULL != list); XmStringFree(list); XmStringFree(seg); return ret; } static XmString fe_EUCToXmString(int16 charset, fe_Font fontGroup, char * string, int len, fe_StringProcessTable *table) { int begin, cur, out; unsigned char curFI; char flabel[4]; XmString xms = NULL; unsigned char buf[FE_PROCESS_STRING_BUFFER_SIZE]; fe_StringProcessTable *entry = &table[(unsigned char)string[0]]; unsigned char lastFI = entry->fontIndex; unsigned char mask1 = 0xff; unsigned char mask2 = 0xff; fe_FontGroupFont *fonts; fonts = (fe_FontGroupFont *) fontGroup; if(FALSE == fe_AreFontsAvail(charset)) { /* The font is not available, it does not matter what we do, fall back to a simple string */ return XmStringCreateLocalized(string); } XP_STRCPY(flabel, "f0"); if(entry->len > 1) { mask1 = fonts[lastFI].mask1; mask2 = fonts[lastFI].mask2; } for(out=cur=begin=0; cur < len; ) { entry = &table[(unsigned char)string[cur]]; curFI = entry->fontIndex; /* Need to switch font, generate a new segment */ if((lastFI != curFI) || (out >= (FE_PROCESS_STRING_BUFFER_SIZE - 4))) { (void)PR_snprintf(flabel, sizeof(flabel), "f%d", lastFI); xms = fe_create_and_concatnate_XmString( xms, buf, out, flabel); /* Now we should save the state somewhere */ out = 0; begin = cur; lastFI = curFI; if(entry->len > 1) { mask1 = fonts[lastFI].mask1; mask2 = fonts[lastFI].mask2; } } cur += entry->skip; if(1 == entry->len) { if(cur < len) buf[out++] = string[cur++]; } else { if(cur < len) buf[out++] = (string[cur++] & mask1); if(cur < len) buf[out++] = (string[cur++] & mask2); } } if(begin != len) { (void)PR_snprintf(flabel, sizeof(flabel), "f%d", lastFI); xms = fe_create_and_concatnate_XmString( xms, buf, out, flabel); } return xms; } /* fontIndex skip len */ #define EUCCN_LATIN1 { 0, 0, 1 } #define EUCCN_GB2312 { 1, 0, 2 } static fe_StringProcessTable EUCCNTable[] = { /* 0x00 */ EUCCN_LATIN1, /* 0x01 */ EUCCN_LATIN1, /* 0x02 */ EUCCN_LATIN1, /* 0x03 */ EUCCN_LATIN1, /* 0x04 */ EUCCN_LATIN1, /* 0x05 */ EUCCN_LATIN1, /* 0x06 */ EUCCN_LATIN1, /* 0x07 */ EUCCN_LATIN1, /* 0x08 */ EUCCN_LATIN1, /* 0x09 */ EUCCN_LATIN1, /* 0x0a */ EUCCN_LATIN1, /* 0x0b */ EUCCN_LATIN1, /* 0x0c */ EUCCN_LATIN1, /* 0x0d */ EUCCN_LATIN1, /* 0x0e */ EUCCN_LATIN1, /* 0x0f */ EUCCN_LATIN1, /* 0x10 */ EUCCN_LATIN1, /* 0x11 */ EUCCN_LATIN1, /* 0x12 */ EUCCN_LATIN1, /* 0x13 */ EUCCN_LATIN1, /* 0x14 */ EUCCN_LATIN1, /* 0x15 */ EUCCN_LATIN1, /* 0x16 */ EUCCN_LATIN1, /* 0x17 */ EUCCN_LATIN1, /* 0x18 */ EUCCN_LATIN1, /* 0x19 */ EUCCN_LATIN1, /* 0x1a */ EUCCN_LATIN1, /* 0x1b */ EUCCN_LATIN1, /* 0x1c */ EUCCN_LATIN1, /* 0x1d */ EUCCN_LATIN1, /* 0x1e */ EUCCN_LATIN1, /* 0x1f */ EUCCN_LATIN1, /* 0x20 */ EUCCN_LATIN1, /* 0x21 */ EUCCN_LATIN1, /* 0x22 */ EUCCN_LATIN1, /* 0x23 */ EUCCN_LATIN1, /* 0x24 */ EUCCN_LATIN1, /* 0x25 */ EUCCN_LATIN1, /* 0x26 */ EUCCN_LATIN1, /* 0x27 */ EUCCN_LATIN1, /* 0x28 */ EUCCN_LATIN1, /* 0x29 */ EUCCN_LATIN1, /* 0x2a */ EUCCN_LATIN1, /* 0x2b */ EUCCN_LATIN1, /* 0x2c */ EUCCN_LATIN1, /* 0x2d */ EUCCN_LATIN1, /* 0x2e */ EUCCN_LATIN1, /* 0x2f */ EUCCN_LATIN1, /* 0x30 */ EUCCN_LATIN1, /* 0x31 */ EUCCN_LATIN1, /* 0x32 */ EUCCN_LATIN1, /* 0x33 */ EUCCN_LATIN1, /* 0x34 */ EUCCN_LATIN1, /* 0x35 */ EUCCN_LATIN1, /* 0x36 */ EUCCN_LATIN1, /* 0x37 */ EUCCN_LATIN1, /* 0x38 */ EUCCN_LATIN1, /* 0x39 */ EUCCN_LATIN1, /* 0x3a */ EUCCN_LATIN1, /* 0x3b */ EUCCN_LATIN1, /* 0x3c */ EUCCN_LATIN1, /* 0x3d */ EUCCN_LATIN1, /* 0x3e */ EUCCN_LATIN1, /* 0x3f */ EUCCN_LATIN1, /* 0x40 */ EUCCN_LATIN1, /* 0x41 */ EUCCN_LATIN1, /* 0x42 */ EUCCN_LATIN1, /* 0x43 */ EUCCN_LATIN1, /* 0x44 */ EUCCN_LATIN1, /* 0x45 */ EUCCN_LATIN1, /* 0x46 */ EUCCN_LATIN1, /* 0x47 */ EUCCN_LATIN1, /* 0x48 */ EUCCN_LATIN1, /* 0x49 */ EUCCN_LATIN1, /* 0x4a */ EUCCN_LATIN1, /* 0x4b */ EUCCN_LATIN1, /* 0x4c */ EUCCN_LATIN1, /* 0x4d */ EUCCN_LATIN1, /* 0x4e */ EUCCN_LATIN1, /* 0x4f */ EUCCN_LATIN1, /* 0x50 */ EUCCN_LATIN1, /* 0x51 */ EUCCN_LATIN1, /* 0x52 */ EUCCN_LATIN1, /* 0x53 */ EUCCN_LATIN1, /* 0x54 */ EUCCN_LATIN1, /* 0x55 */ EUCCN_LATIN1, /* 0x56 */ EUCCN_LATIN1, /* 0x57 */ EUCCN_LATIN1, /* 0x58 */ EUCCN_LATIN1, /* 0x59 */ EUCCN_LATIN1, /* 0x5a */ EUCCN_LATIN1, /* 0x5b */ EUCCN_LATIN1, /* 0x5c */ EUCCN_LATIN1, /* 0x5d */ EUCCN_LATIN1, /* 0x5e */ EUCCN_LATIN1, /* 0x5f */ EUCCN_LATIN1, /* 0x60 */ EUCCN_LATIN1, /* 0x61 */ EUCCN_LATIN1, /* 0x62 */ EUCCN_LATIN1, /* 0x63 */ EUCCN_LATIN1, /* 0x64 */ EUCCN_LATIN1, /* 0x65 */ EUCCN_LATIN1, /* 0x66 */ EUCCN_LATIN1, /* 0x67 */ EUCCN_LATIN1, /* 0x68 */ EUCCN_LATIN1, /* 0x69 */ EUCCN_LATIN1, /* 0x6a */ EUCCN_LATIN1, /* 0x6b */ EUCCN_LATIN1, /* 0x6c */ EUCCN_LATIN1, /* 0x6d */ EUCCN_LATIN1, /* 0x6e */ EUCCN_LATIN1, /* 0x6f */ EUCCN_LATIN1, /* 0x70 */ EUCCN_LATIN1, /* 0x71 */ EUCCN_LATIN1, /* 0x72 */ EUCCN_LATIN1, /* 0x73 */ EUCCN_LATIN1, /* 0x74 */ EUCCN_LATIN1, /* 0x75 */ EUCCN_LATIN1, /* 0x76 */ EUCCN_LATIN1, /* 0x77 */ EUCCN_LATIN1, /* 0x78 */ EUCCN_LATIN1, /* 0x79 */ EUCCN_LATIN1, /* 0x7a */ EUCCN_LATIN1, /* 0x7b */ EUCCN_LATIN1, /* 0x7c */ EUCCN_LATIN1, /* 0x7d */ EUCCN_LATIN1, /* 0x7e */ EUCCN_LATIN1, /* 0x7f */ EUCCN_LATIN1, /* 0x80 */ EUCCN_LATIN1, /* 0x81 */ EUCCN_LATIN1, /* 0x82 */ EUCCN_LATIN1, /* 0x83 */ EUCCN_LATIN1, /* 0x84 */ EUCCN_LATIN1, /* 0x85 */ EUCCN_LATIN1, /* 0x86 */ EUCCN_LATIN1, /* 0x87 */ EUCCN_LATIN1, /* 0x88 */ EUCCN_LATIN1, /* 0x89 */ EUCCN_LATIN1, /* 0x8a */ EUCCN_LATIN1, /* 0x8b */ EUCCN_LATIN1, /* 0x8c */ EUCCN_LATIN1, /* 0x8d */ EUCCN_LATIN1, /* 0x8e */ EUCCN_LATIN1, /* 0x8f */ EUCCN_LATIN1, /* 0x90 */ EUCCN_LATIN1, /* 0x91 */ EUCCN_LATIN1, /* 0x92 */ EUCCN_LATIN1, /* 0x93 */ EUCCN_LATIN1, /* 0x94 */ EUCCN_LATIN1, /* 0x95 */ EUCCN_LATIN1, /* 0x96 */ EUCCN_LATIN1, /* 0x97 */ EUCCN_LATIN1, /* 0x98 */ EUCCN_LATIN1, /* 0x99 */ EUCCN_LATIN1, /* 0x9a */ EUCCN_LATIN1, /* 0x9b */ EUCCN_LATIN1, /* 0x9c */ EUCCN_LATIN1, /* 0x9d */ EUCCN_LATIN1, /* 0x9e */ EUCCN_LATIN1, /* 0x9f */ EUCCN_LATIN1, /* 0xa0 */ EUCCN_LATIN1, /* 0xa1 */ EUCCN_GB2312, /* 0xa2 */ EUCCN_GB2312, /* 0xa3 */ EUCCN_GB2312, /* 0xa4 */ EUCCN_GB2312, /* 0xa5 */ EUCCN_GB2312, /* 0xa6 */ EUCCN_GB2312, /* 0xa7 */ EUCCN_GB2312, /* 0xa8 */ EUCCN_GB2312, /* 0xa9 */ EUCCN_GB2312, /* 0xaa */ EUCCN_GB2312, /* 0xab */ EUCCN_GB2312, /* 0xac */ EUCCN_GB2312, /* 0xad */ EUCCN_GB2312, /* 0xae */ EUCCN_GB2312, /* 0xaf */ EUCCN_GB2312, /* 0xb0 */ EUCCN_GB2312, /* 0xb1 */ EUCCN_GB2312, /* 0xb2 */ EUCCN_GB2312, /* 0xb3 */ EUCCN_GB2312, /* 0xb4 */ EUCCN_GB2312, /* 0xb5 */ EUCCN_GB2312, /* 0xb6 */ EUCCN_GB2312, /* 0xb7 */ EUCCN_GB2312, /* 0xb8 */ EUCCN_GB2312, /* 0xb9 */ EUCCN_GB2312, /* 0xba */ EUCCN_GB2312, /* 0xbb */ EUCCN_GB2312, /* 0xbc */ EUCCN_GB2312, /* 0xbd */ EUCCN_GB2312, /* 0xbe */ EUCCN_GB2312, /* 0xbf */ EUCCN_GB2312, /* 0xc0 */ EUCCN_GB2312, /* 0xc1 */ EUCCN_GB2312, /* 0xc2 */ EUCCN_GB2312, /* 0xc3 */ EUCCN_GB2312, /* 0xc4 */ EUCCN_GB2312, /* 0xc5 */ EUCCN_GB2312, /* 0xc6 */ EUCCN_GB2312, /* 0xc7 */ EUCCN_GB2312, /* 0xc8 */ EUCCN_GB2312, /* 0xc9 */ EUCCN_GB2312, /* 0xca */ EUCCN_GB2312, /* 0xcb */ EUCCN_GB2312, /* 0xcc */ EUCCN_GB2312, /* 0xcd */ EUCCN_GB2312, /* 0xce */ EUCCN_GB2312, /* 0xcf */ EUCCN_GB2312, /* 0xd0 */ EUCCN_GB2312, /* 0xd1 */ EUCCN_GB2312, /* 0xd2 */ EUCCN_GB2312, /* 0xd3 */ EUCCN_GB2312, /* 0xd4 */ EUCCN_GB2312, /* 0xd5 */ EUCCN_GB2312, /* 0xd6 */ EUCCN_GB2312, /* 0xd7 */ EUCCN_GB2312, /* 0xd8 */ EUCCN_GB2312, /* 0xd9 */ EUCCN_GB2312, /* 0xda */ EUCCN_GB2312, /* 0xdb */ EUCCN_GB2312, /* 0xdc */ EUCCN_GB2312, /* 0xdd */ EUCCN_GB2312, /* 0xde */ EUCCN_GB2312, /* 0xdf */ EUCCN_GB2312, /* 0xe0 */ EUCCN_GB2312, /* 0xe1 */ EUCCN_GB2312, /* 0xe2 */ EUCCN_GB2312, /* 0xe3 */ EUCCN_GB2312, /* 0xe4 */ EUCCN_GB2312, /* 0xe5 */ EUCCN_GB2312, /* 0xe6 */ EUCCN_GB2312, /* 0xe7 */ EUCCN_GB2312, /* 0xe8 */ EUCCN_GB2312, /* 0xe9 */ EUCCN_GB2312, /* 0xea */ EUCCN_GB2312, /* 0xeb */ EUCCN_GB2312, /* 0xec */ EUCCN_GB2312, /* 0xed */ EUCCN_GB2312, /* 0xee */ EUCCN_GB2312, /* 0xef */ EUCCN_GB2312, /* 0xf0 */ EUCCN_GB2312, /* 0xf1 */ EUCCN_GB2312, /* 0xf2 */ EUCCN_GB2312, /* 0xf3 */ EUCCN_GB2312, /* 0xf4 */ EUCCN_GB2312, /* 0xf5 */ EUCCN_GB2312, /* 0xf6 */ EUCCN_GB2312, /* 0xf7 */ EUCCN_GB2312, /* 0xf8 */ EUCCN_GB2312, /* 0xf9 */ EUCCN_GB2312, /* 0xfa */ EUCCN_GB2312, /* 0xfb */ EUCCN_GB2312, /* 0xfc */ EUCCN_GB2312, /* 0xfd */ EUCCN_GB2312, /* 0xfe */ EUCCN_GB2312, /* 0xff */ EUCCN_LATIN1, }; static XP_Bool fe_AreEUCCNFontsAvail(int16 win_csid) { /* this needs to match the code in fe_LoadEUCCNFont */ if ((fe_FontCharSets[CS_GB2312 & 0xff].name == NULL) && (fe_FontCharSets[CS_GB2312_11 & 0xff].name == NULL)) return FALSE; else return TRUE; } static fe_Font fe_LoadEUCCNFont(MWContext *context, char *familyName, int points, int sizeNum, int fontmask, int charset, int pitch, int faceNum, Display *dpy) { int16 cs; int len; fe_FontGroupFont *ret; len = (2 * sizeof(fe_FontGroupFont)); ret = calloc(1, len); if (!ret) { return NULL; } (void) memset(ret, 0, len); /* this needs to match the code in fe_AreEUCCNFontsAvail */ cs = CS_LATIN1; ret[0].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask); if (cs != CS_LATIN1) { XP_FREE(ret); return NULL; } cs = CS_GB2312; ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask); if (cs == CS_GB2312) { ret[1].mask1 = 0x7f; ret[1].mask2 = 0x7f; } else { cs = CS_GB2312_11; ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask); if (cs == CS_GB2312_11) { ret[1].mask1 = 0xff; ret[1].mask2 = 0xff; } else { XP_FREE(ret); return NULL; } } return (fe_Font) ret; } static XmFontList fe_FontGroupGetFontList(int16 charset, fe_Font fontGroup, int numOfFonts) { fe_FontGroupFont *fonts; int i; char flabel[4]; XmFontListEntry e; XmFontList fl; if(FALSE == fe_AreFontsAvail(charset)) return NULL; XP_STRCPY(flabel, "f0"); fonts = (fe_FontGroupFont *) fontGroup; e = XmFontListEntryCreate(flabel, XmFONT_IS_FONT, (XFontStruct*) fonts[0].xFont); flabel[1] = flabel[1] + 1; XP_ASSERT(NULL != e); fl = XmFontListAppendEntry(NULL, e); XP_ASSERT(NULL != fl); XmFontListEntryFree(&e); for(i=1; i < numOfFonts; i++, flabel[1] = flabel[1] + 1) { XFontStruct* f; XP_ASSERT(fonts[i].xFont); if(NULL != fonts[i].xFont) f = (XFontStruct*) fonts[i].xFont; else f = (XFontStruct*) fonts[0].xFont; /* somehow it will crash in Xt if we do not create it, fall back to latin1 */ e = XmFontListEntryCreate(flabel, XmFONT_IS_FONT, f); XP_ASSERT(NULL != e); fl = XmFontListAppendEntry(fl, e); XP_ASSERT(NULL != fl); XmFontListEntryFree(&e); } return fl; } static XmString fe_EUCCNToXmString(int16 charset, fe_Font fontGroup, char * string, int len) { return fe_EUCToXmString(charset, fontGroup, string, len, EUCCNTable); } static void fe_EUCCNTextExtents(fe_Font font, char *string, int len, int *direction, int *fontAscent, int *fontDescent, XCharStruct *overall) { fe_ProcessEUCString(CS_GB_8BIT, EUCCNTable, NULL, NULL, NULL, None, font, NULL, 0, 0, string, len, fontAscent, fontDescent, overall, fe_CharSetFuncsArray[FE_FONT_INFO_EUCCN].numberOfFonts); } static void fe_DrawEUCCNString(Display *dpy, Drawable d, fe_Font font, GC gc, int x, int y, char *string, int len) { fe_ProcessEUCString(CS_GB_8BIT, EUCCNTable, (fe_XDrawStringFunc) XDrawString, (fe_XDrawStringFunc) XDrawString16, dpy, d, font, gc, x, y, string, len, NULL, NULL, NULL, 0); } static void fe_DrawEUCCNImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2, int x, int y, char *string, int len) { fe_ProcessEUCString(CS_GB_8BIT, EUCCNTable, (fe_XDrawStringFunc) XDrawImageString, (fe_XDrawStringFunc) XDrawImageString16, dpy, d, font, gc, x, y, string, len, NULL, NULL, NULL, 0); } /* fontIndex skip len */ #define EUCJP_LATIN1 { 0, 0, 1 } #define EUCJP_JISX0208 { 1, 0, 2 } #define EUCJP_JISX0201 { 2, 1, 1 } #define EUCJP_JISX0212 { 3, 1, 2 } static fe_StringProcessTable EUCJPTable[] = { /* 0x00 */ EUCJP_LATIN1, /* 0x01 */ EUCJP_LATIN1, /* 0x02 */ EUCJP_LATIN1, /* 0x03 */ EUCJP_LATIN1, /* 0x04 */ EUCJP_LATIN1, /* 0x05 */ EUCJP_LATIN1, /* 0x06 */ EUCJP_LATIN1, /* 0x07 */ EUCJP_LATIN1, /* 0x08 */ EUCJP_LATIN1, /* 0x09 */ EUCJP_LATIN1, /* 0x0a */ EUCJP_LATIN1, /* 0x0b */ EUCJP_LATIN1, /* 0x0c */ EUCJP_LATIN1, /* 0x0d */ EUCJP_LATIN1, /* 0x0e */ EUCJP_LATIN1, /* 0x0f */ EUCJP_LATIN1, /* 0x10 */ EUCJP_LATIN1, /* 0x11 */ EUCJP_LATIN1, /* 0x12 */ EUCJP_LATIN1, /* 0x13 */ EUCJP_LATIN1, /* 0x14 */ EUCJP_LATIN1, /* 0x15 */ EUCJP_LATIN1, /* 0x16 */ EUCJP_LATIN1, /* 0x17 */ EUCJP_LATIN1, /* 0x18 */ EUCJP_LATIN1, /* 0x19 */ EUCJP_LATIN1, /* 0x1a */ EUCJP_LATIN1, /* 0x1b */ EUCJP_LATIN1, /* 0x1c */ EUCJP_LATIN1, /* 0x1d */ EUCJP_LATIN1, /* 0x1e */ EUCJP_LATIN1, /* 0x1f */ EUCJP_LATIN1, /* 0x20 */ EUCJP_LATIN1, /* 0x21 */ EUCJP_LATIN1, /* 0x22 */ EUCJP_LATIN1, /* 0x23 */ EUCJP_LATIN1, /* 0x24 */ EUCJP_LATIN1, /* 0x25 */ EUCJP_LATIN1, /* 0x26 */ EUCJP_LATIN1, /* 0x27 */ EUCJP_LATIN1, /* 0x28 */ EUCJP_LATIN1, /* 0x29 */ EUCJP_LATIN1, /* 0x2a */ EUCJP_LATIN1, /* 0x2b */ EUCJP_LATIN1, /* 0x2c */ EUCJP_LATIN1, /* 0x2d */ EUCJP_LATIN1, /* 0x2e */ EUCJP_LATIN1, /* 0x2f */ EUCJP_LATIN1, /* 0x30 */ EUCJP_LATIN1, /* 0x31 */ EUCJP_LATIN1, /* 0x32 */ EUCJP_LATIN1, /* 0x33 */ EUCJP_LATIN1, /* 0x34 */ EUCJP_LATIN1, /* 0x35 */ EUCJP_LATIN1, /* 0x36 */ EUCJP_LATIN1, /* 0x37 */ EUCJP_LATIN1, /* 0x38 */ EUCJP_LATIN1, /* 0x39 */ EUCJP_LATIN1, /* 0x3a */ EUCJP_LATIN1, /* 0x3b */ EUCJP_LATIN1, /* 0x3c */ EUCJP_LATIN1, /* 0x3d */ EUCJP_LATIN1, /* 0x3e */ EUCJP_LATIN1, /* 0x3f */ EUCJP_LATIN1, /* 0x40 */ EUCJP_LATIN1, /* 0x41 */ EUCJP_LATIN1, /* 0x42 */ EUCJP_LATIN1, /* 0x43 */ EUCJP_LATIN1, /* 0x44 */ EUCJP_LATIN1, /* 0x45 */ EUCJP_LATIN1, /* 0x46 */ EUCJP_LATIN1, /* 0x47 */ EUCJP_LATIN1, /* 0x48 */ EUCJP_LATIN1, /* 0x49 */ EUCJP_LATIN1, /* 0x4a */ EUCJP_LATIN1, /* 0x4b */ EUCJP_LATIN1, /* 0x4c */ EUCJP_LATIN1, /* 0x4d */ EUCJP_LATIN1, /* 0x4e */ EUCJP_LATIN1, /* 0x4f */ EUCJP_LATIN1, /* 0x50 */ EUCJP_LATIN1, /* 0x51 */ EUCJP_LATIN1, /* 0x52 */ EUCJP_LATIN1, /* 0x53 */ EUCJP_LATIN1, /* 0x54 */ EUCJP_LATIN1, /* 0x55 */ EUCJP_LATIN1, /* 0x56 */ EUCJP_LATIN1, /* 0x57 */ EUCJP_LATIN1, /* 0x58 */ EUCJP_LATIN1, /* 0x59 */ EUCJP_LATIN1, /* 0x5a */ EUCJP_LATIN1, /* 0x5b */ EUCJP_LATIN1, /* 0x5c */ EUCJP_LATIN1, /* 0x5d */ EUCJP_LATIN1, /* 0x5e */ EUCJP_LATIN1, /* 0x5f */ EUCJP_LATIN1, /* 0x60 */ EUCJP_LATIN1, /* 0x61 */ EUCJP_LATIN1, /* 0x62 */ EUCJP_LATIN1, /* 0x63 */ EUCJP_LATIN1, /* 0x64 */ EUCJP_LATIN1, /* 0x65 */ EUCJP_LATIN1, /* 0x66 */ EUCJP_LATIN1, /* 0x67 */ EUCJP_LATIN1, /* 0x68 */ EUCJP_LATIN1, /* 0x69 */ EUCJP_LATIN1, /* 0x6a */ EUCJP_LATIN1, /* 0x6b */ EUCJP_LATIN1, /* 0x6c */ EUCJP_LATIN1, /* 0x6d */ EUCJP_LATIN1, /* 0x6e */ EUCJP_LATIN1, /* 0x6f */ EUCJP_LATIN1, /* 0x70 */ EUCJP_LATIN1, /* 0x71 */ EUCJP_LATIN1, /* 0x72 */ EUCJP_LATIN1, /* 0x73 */ EUCJP_LATIN1, /* 0x74 */ EUCJP_LATIN1, /* 0x75 */ EUCJP_LATIN1, /* 0x76 */ EUCJP_LATIN1, /* 0x77 */ EUCJP_LATIN1, /* 0x78 */ EUCJP_LATIN1, /* 0x79 */ EUCJP_LATIN1, /* 0x7a */ EUCJP_LATIN1, /* 0x7b */ EUCJP_LATIN1, /* 0x7c */ EUCJP_LATIN1, /* 0x7d */ EUCJP_LATIN1, /* 0x7e */ EUCJP_LATIN1, /* 0x7f */ EUCJP_LATIN1, /* 0x80 */ EUCJP_LATIN1, /* 0x81 */ EUCJP_LATIN1, /* 0x82 */ EUCJP_LATIN1, /* 0x83 */ EUCJP_LATIN1, /* 0x84 */ EUCJP_LATIN1, /* 0x85 */ EUCJP_LATIN1, /* 0x86 */ EUCJP_LATIN1, /* 0x87 */ EUCJP_LATIN1, /* 0x88 */ EUCJP_LATIN1, /* 0x89 */ EUCJP_LATIN1, /* 0x8a */ EUCJP_LATIN1, /* 0x8b */ EUCJP_LATIN1, /* 0x8c */ EUCJP_LATIN1, /* 0x8d */ EUCJP_LATIN1, /* 0x8e */ EUCJP_JISX0201, /* 0x8f */ EUCJP_JISX0212, /* 0x90 */ EUCJP_LATIN1, /* 0x91 */ EUCJP_LATIN1, /* 0x92 */ EUCJP_LATIN1, /* 0x93 */ EUCJP_LATIN1, /* 0x94 */ EUCJP_LATIN1, /* 0x95 */ EUCJP_LATIN1, /* 0x96 */ EUCJP_LATIN1, /* 0x97 */ EUCJP_LATIN1, /* 0x98 */ EUCJP_LATIN1, /* 0x99 */ EUCJP_LATIN1, /* 0x9a */ EUCJP_LATIN1, /* 0x9b */ EUCJP_LATIN1, /* 0x9c */ EUCJP_LATIN1, /* 0x9d */ EUCJP_LATIN1, /* 0x9e */ EUCJP_LATIN1, /* 0x9f */ EUCJP_LATIN1, /* 0xa0 */ EUCJP_LATIN1, /* 0xa1 */ EUCJP_JISX0208, /* 0xa2 */ EUCJP_JISX0208, /* 0xa3 */ EUCJP_JISX0208, /* 0xa4 */ EUCJP_JISX0208, /* 0xa5 */ EUCJP_JISX0208, /* 0xa6 */ EUCJP_JISX0208, /* 0xa7 */ EUCJP_JISX0208, /* 0xa8 */ EUCJP_JISX0208, /* 0xa9 */ EUCJP_JISX0208, /* 0xaa */ EUCJP_JISX0208, /* 0xab */ EUCJP_JISX0208, /* 0xac */ EUCJP_JISX0208, /* 0xad */ EUCJP_JISX0208, /* 0xae */ EUCJP_JISX0208, /* 0xaf */ EUCJP_JISX0208, /* 0xb0 */ EUCJP_JISX0208, /* 0xb1 */ EUCJP_JISX0208, /* 0xb2 */ EUCJP_JISX0208, /* 0xb3 */ EUCJP_JISX0208, /* 0xb4 */ EUCJP_JISX0208, /* 0xb5 */ EUCJP_JISX0208, /* 0xb6 */ EUCJP_JISX0208, /* 0xb7 */ EUCJP_JISX0208, /* 0xb8 */ EUCJP_JISX0208, /* 0xb9 */ EUCJP_JISX0208, /* 0xba */ EUCJP_JISX0208, /* 0xbb */ EUCJP_JISX0208, /* 0xbc */ EUCJP_JISX0208, /* 0xbd */ EUCJP_JISX0208, /* 0xbe */ EUCJP_JISX0208, /* 0xbf */ EUCJP_JISX0208, /* 0xc0 */ EUCJP_JISX0208, /* 0xc1 */ EUCJP_JISX0208, /* 0xc2 */ EUCJP_JISX0208, /* 0xc3 */ EUCJP_JISX0208, /* 0xc4 */ EUCJP_JISX0208, /* 0xc5 */ EUCJP_JISX0208, /* 0xc6 */ EUCJP_JISX0208, /* 0xc7 */ EUCJP_JISX0208, /* 0xc8 */ EUCJP_JISX0208, /* 0xc9 */ EUCJP_JISX0208, /* 0xca */ EUCJP_JISX0208, /* 0xcb */ EUCJP_JISX0208, /* 0xcc */ EUCJP_JISX0208, /* 0xcd */ EUCJP_JISX0208, /* 0xce */ EUCJP_JISX0208, /* 0xcf */ EUCJP_JISX0208, /* 0xd0 */ EUCJP_JISX0208, /* 0xd1 */ EUCJP_JISX0208, /* 0xd2 */ EUCJP_JISX0208, /* 0xd3 */ EUCJP_JISX0208, /* 0xd4 */ EUCJP_JISX0208, /* 0xd5 */ EUCJP_JISX0208, /* 0xd6 */ EUCJP_JISX0208, /* 0xd7 */ EUCJP_JISX0208, /* 0xd8 */ EUCJP_JISX0208, /* 0xd9 */ EUCJP_JISX0208, /* 0xda */ EUCJP_JISX0208, /* 0xdb */ EUCJP_JISX0208, /* 0xdc */ EUCJP_JISX0208, /* 0xdd */ EUCJP_JISX0208, /* 0xde */ EUCJP_JISX0208, /* 0xdf */ EUCJP_JISX0208, /* 0xe0 */ EUCJP_JISX0208, /* 0xe1 */ EUCJP_JISX0208, /* 0xe2 */ EUCJP_JISX0208, /* 0xe3 */ EUCJP_JISX0208, /* 0xe4 */ EUCJP_JISX0208, /* 0xe5 */ EUCJP_JISX0208, /* 0xe6 */ EUCJP_JISX0208, /* 0xe7 */ EUCJP_JISX0208, /* 0xe8 */ EUCJP_JISX0208, /* 0xe9 */ EUCJP_JISX0208, /* 0xea */ EUCJP_JISX0208, /* 0xeb */ EUCJP_JISX0208, /* 0xec */ EUCJP_JISX0208, /* 0xed */ EUCJP_JISX0208, /* 0xee */ EUCJP_JISX0208, /* 0xef */ EUCJP_JISX0208, /* 0xf0 */ EUCJP_JISX0208, /* 0xf1 */ EUCJP_JISX0208, /* 0xf2 */ EUCJP_JISX0208, /* 0xf3 */ EUCJP_JISX0208, /* 0xf4 */ EUCJP_JISX0208, /* 0xf5 */ EUCJP_JISX0208, /* 0xf6 */ EUCJP_JISX0208, /* 0xf7 */ EUCJP_JISX0208, /* 0xf8 */ EUCJP_JISX0208, /* 0xf9 */ EUCJP_JISX0208, /* 0xfa */ EUCJP_JISX0208, /* 0xfb */ EUCJP_JISX0208, /* 0xfc */ EUCJP_JISX0208, /* 0xfd */ EUCJP_JISX0208, /* 0xfe */ EUCJP_JISX0208, /* 0xff */ EUCJP_LATIN1, }; static XP_Bool fe_AreEUCJPFontsAvail(int16 win_csid) { /* this needs to match the code in fe_LoadEUCJPFont */ if ((fe_FontCharSets[CS_JISX0208 & 0xff].name == NULL) && (fe_FontCharSets[CS_JISX0208_11 & 0xff].name == NULL)) return FALSE; else return TRUE; } static fe_Font fe_LoadEUCJPFont(MWContext *context, char *familyName, int points, int sizeNum, int fontmask, int charset, int pitch, int faceNum, Display *dpy) { int16 cs; int len; fe_FontGroupFont *ret; len = (4 * sizeof(fe_FontGroupFont)); ret = calloc(1, len); if (!ret) { return NULL; } (void) memset(ret, 0, len); /* this needs to match the code in fe_AreEUCJPFontsAvail */ cs = CS_LATIN1; ret[0].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask); if (cs != CS_LATIN1) { XP_FREE(ret); return NULL; } cs = CS_JISX0208; ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask); if (cs == CS_JISX0208) { ret[1].mask1 = 0x7f; ret[1].mask2 = 0x7f; } else { cs = CS_JISX0208_11; ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask); if (cs == CS_JISX0208_11) { ret[1].mask1 = 0xff; ret[1].mask2 = 0xff; } else { XP_FREE(ret); return NULL; } } cs = CS_JISX0201; ret[2].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask); if (cs != CS_JISX0201) { ret[2].xFont = NULL; } cs = CS_JISX0212; ret[3].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask); if (cs == CS_JISX0212) { ret[3].mask1 = 0x7f; ret[3].mask2 = 0x7f; } else { ret[3].xFont = NULL; } return (fe_Font) ret; } static XmString fe_EUCJPToXmString(int16 charset, fe_Font fontGroup, char * string, int len) { return fe_EUCToXmString(charset, fontGroup, string, len, EUCJPTable); } static void fe_EUCJPTextExtents(fe_Font font, char *string, int len, int *direction, int *fontAscent, int *fontDescent, XCharStruct *overall) { fe_ProcessEUCString(CS_EUCJP, EUCJPTable, NULL, NULL, NULL, None, font, NULL, 0, 0, string, len, fontAscent, fontDescent, overall, fe_CharSetFuncsArray[FE_FONT_INFO_EUCJP].numberOfFonts); } static void fe_DrawEUCJPString(Display *dpy, Drawable d, fe_Font font, GC gc, int x, int y, char *string, int len) { fe_ProcessEUCString(CS_EUCJP, EUCJPTable, (fe_XDrawStringFunc) XDrawString, (fe_XDrawStringFunc) XDrawString16, dpy, d, font, gc, x, y, string, len, NULL, NULL, NULL, 0); } static void fe_DrawEUCJPImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2, int x, int y, char *string, int len) { fe_ProcessEUCString(CS_EUCJP, EUCJPTable, (fe_XDrawStringFunc) XDrawImageString, (fe_XDrawStringFunc) XDrawImageString16, dpy, d, font, gc, x, y, string, len, NULL, NULL, NULL, 0); } /* fontIndex skip len */ #define EUCKR_LATIN1 { 0, 0, 1 } #define EUCKR_KSC5601 { 1, 0, 2 } static fe_StringProcessTable EUCKRTable[] = { /* 0x00 */ EUCKR_LATIN1, /* 0x01 */ EUCKR_LATIN1, /* 0x02 */ EUCKR_LATIN1, /* 0x03 */ EUCKR_LATIN1, /* 0x04 */ EUCKR_LATIN1, /* 0x05 */ EUCKR_LATIN1, /* 0x06 */ EUCKR_LATIN1, /* 0x07 */ EUCKR_LATIN1, /* 0x08 */ EUCKR_LATIN1, /* 0x09 */ EUCKR_LATIN1, /* 0x0a */ EUCKR_LATIN1, /* 0x0b */ EUCKR_LATIN1, /* 0x0c */ EUCKR_LATIN1, /* 0x0d */ EUCKR_LATIN1, /* 0x0e */ EUCKR_LATIN1, /* 0x0f */ EUCKR_LATIN1, /* 0x10 */ EUCKR_LATIN1, /* 0x11 */ EUCKR_LATIN1, /* 0x12 */ EUCKR_LATIN1, /* 0x13 */ EUCKR_LATIN1, /* 0x14 */ EUCKR_LATIN1, /* 0x15 */ EUCKR_LATIN1, /* 0x16 */ EUCKR_LATIN1, /* 0x17 */ EUCKR_LATIN1, /* 0x18 */ EUCKR_LATIN1, /* 0x19 */ EUCKR_LATIN1, /* 0x1a */ EUCKR_LATIN1, /* 0x1b */ EUCKR_LATIN1, /* 0x1c */ EUCKR_LATIN1, /* 0x1d */ EUCKR_LATIN1, /* 0x1e */ EUCKR_LATIN1, /* 0x1f */ EUCKR_LATIN1, /* 0x20 */ EUCKR_LATIN1, /* 0x21 */ EUCKR_LATIN1, /* 0x22 */ EUCKR_LATIN1, /* 0x23 */ EUCKR_LATIN1, /* 0x24 */ EUCKR_LATIN1, /* 0x25 */ EUCKR_LATIN1, /* 0x26 */ EUCKR_LATIN1, /* 0x27 */ EUCKR_LATIN1, /* 0x28 */ EUCKR_LATIN1, /* 0x29 */ EUCKR_LATIN1, /* 0x2a */ EUCKR_LATIN1, /* 0x2b */ EUCKR_LATIN1, /* 0x2c */ EUCKR_LATIN1, /* 0x2d */ EUCKR_LATIN1, /* 0x2e */ EUCKR_LATIN1, /* 0x2f */ EUCKR_LATIN1, /* 0x30 */ EUCKR_LATIN1, /* 0x31 */ EUCKR_LATIN1, /* 0x32 */ EUCKR_LATIN1, /* 0x33 */ EUCKR_LATIN1, /* 0x34 */ EUCKR_LATIN1, /* 0x35 */ EUCKR_LATIN1, /* 0x36 */ EUCKR_LATIN1, /* 0x37 */ EUCKR_LATIN1, /* 0x38 */ EUCKR_LATIN1, /* 0x39 */ EUCKR_LATIN1, /* 0x3a */ EUCKR_LATIN1, /* 0x3b */ EUCKR_LATIN1, /* 0x3c */ EUCKR_LATIN1, /* 0x3d */ EUCKR_LATIN1, /* 0x3e */ EUCKR_LATIN1, /* 0x3f */ EUCKR_LATIN1, /* 0x40 */ EUCKR_LATIN1, /* 0x41 */ EUCKR_LATIN1, /* 0x42 */ EUCKR_LATIN1, /* 0x43 */ EUCKR_LATIN1, /* 0x44 */ EUCKR_LATIN1, /* 0x45 */ EUCKR_LATIN1, /* 0x46 */ EUCKR_LATIN1, /* 0x47 */ EUCKR_LATIN1, /* 0x48 */ EUCKR_LATIN1, /* 0x49 */ EUCKR_LATIN1, /* 0x4a */ EUCKR_LATIN1, /* 0x4b */ EUCKR_LATIN1, /* 0x4c */ EUCKR_LATIN1, /* 0x4d */ EUCKR_LATIN1, /* 0x4e */ EUCKR_LATIN1, /* 0x4f */ EUCKR_LATIN1, /* 0x50 */ EUCKR_LATIN1, /* 0x51 */ EUCKR_LATIN1, /* 0x52 */ EUCKR_LATIN1, /* 0x53 */ EUCKR_LATIN1, /* 0x54 */ EUCKR_LATIN1, /* 0x55 */ EUCKR_LATIN1, /* 0x56 */ EUCKR_LATIN1, /* 0x57 */ EUCKR_LATIN1, /* 0x58 */ EUCKR_LATIN1, /* 0x59 */ EUCKR_LATIN1, /* 0x5a */ EUCKR_LATIN1, /* 0x5b */ EUCKR_LATIN1, /* 0x5c */ EUCKR_LATIN1, /* 0x5d */ EUCKR_LATIN1, /* 0x5e */ EUCKR_LATIN1, /* 0x5f */ EUCKR_LATIN1, /* 0x60 */ EUCKR_LATIN1, /* 0x61 */ EUCKR_LATIN1, /* 0x62 */ EUCKR_LATIN1, /* 0x63 */ EUCKR_LATIN1, /* 0x64 */ EUCKR_LATIN1, /* 0x65 */ EUCKR_LATIN1, /* 0x66 */ EUCKR_LATIN1, /* 0x67 */ EUCKR_LATIN1, /* 0x68 */ EUCKR_LATIN1, /* 0x69 */ EUCKR_LATIN1, /* 0x6a */ EUCKR_LATIN1, /* 0x6b */ EUCKR_LATIN1, /* 0x6c */ EUCKR_LATIN1, /* 0x6d */ EUCKR_LATIN1, /* 0x6e */ EUCKR_LATIN1, /* 0x6f */ EUCKR_LATIN1, /* 0x70 */ EUCKR_LATIN1, /* 0x71 */ EUCKR_LATIN1, /* 0x72 */ EUCKR_LATIN1, /* 0x73 */ EUCKR_LATIN1, /* 0x74 */ EUCKR_LATIN1, /* 0x75 */ EUCKR_LATIN1, /* 0x76 */ EUCKR_LATIN1, /* 0x77 */ EUCKR_LATIN1, /* 0x78 */ EUCKR_LATIN1, /* 0x79 */ EUCKR_LATIN1, /* 0x7a */ EUCKR_LATIN1, /* 0x7b */ EUCKR_LATIN1, /* 0x7c */ EUCKR_LATIN1, /* 0x7d */ EUCKR_LATIN1, /* 0x7e */ EUCKR_LATIN1, /* 0x7f */ EUCKR_LATIN1, /* 0x80 */ EUCKR_LATIN1, /* 0x81 */ EUCKR_LATIN1, /* 0x82 */ EUCKR_LATIN1, /* 0x83 */ EUCKR_LATIN1, /* 0x84 */ EUCKR_LATIN1, /* 0x85 */ EUCKR_LATIN1, /* 0x86 */ EUCKR_LATIN1, /* 0x87 */ EUCKR_LATIN1, /* 0x88 */ EUCKR_LATIN1, /* 0x89 */ EUCKR_LATIN1, /* 0x8a */ EUCKR_LATIN1, /* 0x8b */ EUCKR_LATIN1, /* 0x8c */ EUCKR_LATIN1, /* 0x8d */ EUCKR_LATIN1, /* 0x8e */ EUCKR_LATIN1, /* 0x8f */ EUCKR_LATIN1, /* 0x90 */ EUCKR_LATIN1, /* 0x91 */ EUCKR_LATIN1, /* 0x92 */ EUCKR_LATIN1, /* 0x93 */ EUCKR_LATIN1, /* 0x94 */ EUCKR_LATIN1, /* 0x95 */ EUCKR_LATIN1, /* 0x96 */ EUCKR_LATIN1, /* 0x97 */ EUCKR_LATIN1, /* 0x98 */ EUCKR_LATIN1, /* 0x99 */ EUCKR_LATIN1, /* 0x9a */ EUCKR_LATIN1, /* 0x9b */ EUCKR_LATIN1, /* 0x9c */ EUCKR_LATIN1, /* 0x9d */ EUCKR_LATIN1, /* 0x9e */ EUCKR_LATIN1, /* 0x9f */ EUCKR_LATIN1, /* 0xa0 */ EUCKR_LATIN1, /* 0xa1 */ EUCKR_KSC5601, /* 0xa2 */ EUCKR_KSC5601, /* 0xa3 */ EUCKR_KSC5601, /* 0xa4 */ EUCKR_KSC5601, /* 0xa5 */ EUCKR_KSC5601, /* 0xa6 */ EUCKR_KSC5601, /* 0xa7 */ EUCKR_KSC5601, /* 0xa8 */ EUCKR_KSC5601, /* 0xa9 */ EUCKR_KSC5601, /* 0xaa */ EUCKR_KSC5601, /* 0xab */ EUCKR_KSC5601, /* 0xac */ EUCKR_KSC5601, /* 0xad */ EUCKR_KSC5601, /* 0xae */ EUCKR_KSC5601, /* 0xaf */ EUCKR_KSC5601, /* 0xb0 */ EUCKR_KSC5601, /* 0xb1 */ EUCKR_KSC5601, /* 0xb2 */ EUCKR_KSC5601, /* 0xb3 */ EUCKR_KSC5601, /* 0xb4 */ EUCKR_KSC5601, /* 0xb5 */ EUCKR_KSC5601, /* 0xb6 */ EUCKR_KSC5601, /* 0xb7 */ EUCKR_KSC5601, /* 0xb8 */ EUCKR_KSC5601, /* 0xb9 */ EUCKR_KSC5601, /* 0xba */ EUCKR_KSC5601, /* 0xbb */ EUCKR_KSC5601, /* 0xbc */ EUCKR_KSC5601, /* 0xbd */ EUCKR_KSC5601, /* 0xbe */ EUCKR_KSC5601, /* 0xbf */ EUCKR_KSC5601, /* 0xc0 */ EUCKR_KSC5601, /* 0xc1 */ EUCKR_KSC5601, /* 0xc2 */ EUCKR_KSC5601, /* 0xc3 */ EUCKR_KSC5601, /* 0xc4 */ EUCKR_KSC5601, /* 0xc5 */ EUCKR_KSC5601, /* 0xc6 */ EUCKR_KSC5601, /* 0xc7 */ EUCKR_KSC5601, /* 0xc8 */ EUCKR_KSC5601, /* 0xc9 */ EUCKR_KSC5601, /* 0xca */ EUCKR_KSC5601, /* 0xcb */ EUCKR_KSC5601, /* 0xcc */ EUCKR_KSC5601, /* 0xcd */ EUCKR_KSC5601, /* 0xce */ EUCKR_KSC5601, /* 0xcf */ EUCKR_KSC5601, /* 0xd0 */ EUCKR_KSC5601, /* 0xd1 */ EUCKR_KSC5601, /* 0xd2 */ EUCKR_KSC5601, /* 0xd3 */ EUCKR_KSC5601, /* 0xd4 */ EUCKR_KSC5601, /* 0xd5 */ EUCKR_KSC5601, /* 0xd6 */ EUCKR_KSC5601, /* 0xd7 */ EUCKR_KSC5601, /* 0xd8 */ EUCKR_KSC5601, /* 0xd9 */ EUCKR_KSC5601, /* 0xda */ EUCKR_KSC5601, /* 0xdb */ EUCKR_KSC5601, /* 0xdc */ EUCKR_KSC5601, /* 0xdd */ EUCKR_KSC5601, /* 0xde */ EUCKR_KSC5601, /* 0xdf */ EUCKR_KSC5601, /* 0xe0 */ EUCKR_KSC5601, /* 0xe1 */ EUCKR_KSC5601, /* 0xe2 */ EUCKR_KSC5601, /* 0xe3 */ EUCKR_KSC5601, /* 0xe4 */ EUCKR_KSC5601, /* 0xe5 */ EUCKR_KSC5601, /* 0xe6 */ EUCKR_KSC5601, /* 0xe7 */ EUCKR_KSC5601, /* 0xe8 */ EUCKR_KSC5601, /* 0xe9 */ EUCKR_KSC5601, /* 0xea */ EUCKR_KSC5601, /* 0xeb */ EUCKR_KSC5601, /* 0xec */ EUCKR_KSC5601, /* 0xed */ EUCKR_KSC5601, /* 0xee */ EUCKR_KSC5601, /* 0xef */ EUCKR_KSC5601, /* 0xf0 */ EUCKR_KSC5601, /* 0xf1 */ EUCKR_KSC5601, /* 0xf2 */ EUCKR_KSC5601, /* 0xf3 */ EUCKR_KSC5601, /* 0xf4 */ EUCKR_KSC5601, /* 0xf5 */ EUCKR_KSC5601, /* 0xf6 */ EUCKR_KSC5601, /* 0xf7 */ EUCKR_KSC5601, /* 0xf8 */ EUCKR_KSC5601, /* 0xf9 */ EUCKR_KSC5601, /* 0xfa */ EUCKR_KSC5601, /* 0xfb */ EUCKR_KSC5601, /* 0xfc */ EUCKR_KSC5601, /* 0xfd */ EUCKR_KSC5601, /* 0xfe */ EUCKR_KSC5601, /* 0xff */ EUCKR_LATIN1, }; static XP_Bool fe_AreEUCKRFontsAvail(int16 win_csid) { /* this needs to match the code in fe_LoadEUCKRFont */ if ((fe_FontCharSets[CS_KSC5601 & 0xff].name == NULL) && (fe_FontCharSets[CS_KSC5601_11 & 0xff].name == NULL)) return FALSE; else return TRUE; } static fe_Font fe_LoadEUCKRFont(MWContext *context, char *familyName, int points, int sizeNum, int fontmask, int charset, int pitch, int faceNum, Display *dpy) { int16 cs; int len; fe_FontGroupFont *ret; len = (2 * sizeof(fe_FontGroupFont)); ret = calloc(1, len); if (!ret) { return NULL; } (void) memset(ret, 0, len); cs = CS_LATIN1; ret[0].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask); if (cs != CS_LATIN1) { XP_FREE(ret); return NULL; } /* this needs to match the code in fe_AreEUCKRFontsAvail */ cs = CS_KSC5601; ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask); if (cs == CS_KSC5601) { ret[1].mask1 = 0x7f; ret[1].mask2 = 0x7f; } else { cs = CS_KSC5601_11; ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask); if (cs == CS_KSC5601_11) { ret[1].mask1 = 0xff; ret[1].mask2 = 0xff; } else { XP_FREE(ret); return NULL; } } return (fe_Font) ret; } static XmString fe_EUCKRToXmString(int16 charset, fe_Font fontGroup, char * string, int len) { return fe_EUCToXmString(charset, fontGroup, string, len, EUCKRTable); } static void fe_EUCKRTextExtents(fe_Font font, char *string, int len, int *direction, int *fontAscent, int *fontDescent, XCharStruct *overall) { fe_ProcessEUCString(CS_KSC_8BIT, EUCKRTable, NULL, NULL, NULL, None, font, NULL, 0, 0, string, len, fontAscent, fontDescent, overall, fe_CharSetFuncsArray[FE_FONT_INFO_EUCKR].numberOfFonts); } static void fe_DrawEUCKRString(Display *dpy, Drawable d, fe_Font font, GC gc, int x, int y, char *string, int len) { fe_ProcessEUCString(CS_KSC_8BIT, EUCKRTable, (fe_XDrawStringFunc) XDrawString, (fe_XDrawStringFunc) XDrawString16, dpy, d, font, gc, x, y, string, len, NULL, NULL, NULL, 0); } static void fe_DrawEUCKRImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2, int x, int y, char *string, int len) { fe_ProcessEUCString(CS_KSC_8BIT, EUCKRTable, (fe_XDrawStringFunc) XDrawImageString, (fe_XDrawStringFunc) XDrawImageString16, dpy, d, font, gc, x, y, string, len, NULL, NULL, NULL, 0); } /* fontIndex skip len */ #define EUCTW_LATIN1 { 0, 0, 1 } #define EUCTW_CNS11643_1 { 1, 0, 2 } #define EUCTW_CNS11643_2 { 2, 2, 2 } static fe_StringProcessTable EUCTWTable[] = { /* 0x00 */ EUCTW_LATIN1, /* 0x01 */ EUCTW_LATIN1, /* 0x02 */ EUCTW_LATIN1, /* 0x03 */ EUCTW_LATIN1, /* 0x04 */ EUCTW_LATIN1, /* 0x05 */ EUCTW_LATIN1, /* 0x06 */ EUCTW_LATIN1, /* 0x07 */ EUCTW_LATIN1, /* 0x08 */ EUCTW_LATIN1, /* 0x09 */ EUCTW_LATIN1, /* 0x0a */ EUCTW_LATIN1, /* 0x0b */ EUCTW_LATIN1, /* 0x0c */ EUCTW_LATIN1, /* 0x0d */ EUCTW_LATIN1, /* 0x0e */ EUCTW_LATIN1, /* 0x0f */ EUCTW_LATIN1, /* 0x10 */ EUCTW_LATIN1, /* 0x11 */ EUCTW_LATIN1, /* 0x12 */ EUCTW_LATIN1, /* 0x13 */ EUCTW_LATIN1, /* 0x14 */ EUCTW_LATIN1, /* 0x15 */ EUCTW_LATIN1, /* 0x16 */ EUCTW_LATIN1, /* 0x17 */ EUCTW_LATIN1, /* 0x18 */ EUCTW_LATIN1, /* 0x19 */ EUCTW_LATIN1, /* 0x1a */ EUCTW_LATIN1, /* 0x1b */ EUCTW_LATIN1, /* 0x1c */ EUCTW_LATIN1, /* 0x1d */ EUCTW_LATIN1, /* 0x1e */ EUCTW_LATIN1, /* 0x1f */ EUCTW_LATIN1, /* 0x20 */ EUCTW_LATIN1, /* 0x21 */ EUCTW_LATIN1, /* 0x22 */ EUCTW_LATIN1, /* 0x23 */ EUCTW_LATIN1, /* 0x24 */ EUCTW_LATIN1, /* 0x25 */ EUCTW_LATIN1, /* 0x26 */ EUCTW_LATIN1, /* 0x27 */ EUCTW_LATIN1, /* 0x28 */ EUCTW_LATIN1, /* 0x29 */ EUCTW_LATIN1, /* 0x2a */ EUCTW_LATIN1, /* 0x2b */ EUCTW_LATIN1, /* 0x2c */ EUCTW_LATIN1, /* 0x2d */ EUCTW_LATIN1, /* 0x2e */ EUCTW_LATIN1, /* 0x2f */ EUCTW_LATIN1, /* 0x30 */ EUCTW_LATIN1, /* 0x31 */ EUCTW_LATIN1, /* 0x32 */ EUCTW_LATIN1, /* 0x33 */ EUCTW_LATIN1, /* 0x34 */ EUCTW_LATIN1, /* 0x35 */ EUCTW_LATIN1, /* 0x36 */ EUCTW_LATIN1, /* 0x37 */ EUCTW_LATIN1, /* 0x38 */ EUCTW_LATIN1, /* 0x39 */ EUCTW_LATIN1, /* 0x3a */ EUCTW_LATIN1, /* 0x3b */ EUCTW_LATIN1, /* 0x3c */ EUCTW_LATIN1, /* 0x3d */ EUCTW_LATIN1, /* 0x3e */ EUCTW_LATIN1, /* 0x3f */ EUCTW_LATIN1, /* 0x40 */ EUCTW_LATIN1, /* 0x41 */ EUCTW_LATIN1, /* 0x42 */ EUCTW_LATIN1, /* 0x43 */ EUCTW_LATIN1, /* 0x44 */ EUCTW_LATIN1, /* 0x45 */ EUCTW_LATIN1, /* 0x46 */ EUCTW_LATIN1, /* 0x47 */ EUCTW_LATIN1, /* 0x48 */ EUCTW_LATIN1, /* 0x49 */ EUCTW_LATIN1, /* 0x4a */ EUCTW_LATIN1, /* 0x4b */ EUCTW_LATIN1, /* 0x4c */ EUCTW_LATIN1, /* 0x4d */ EUCTW_LATIN1, /* 0x4e */ EUCTW_LATIN1, /* 0x4f */ EUCTW_LATIN1, /* 0x50 */ EUCTW_LATIN1, /* 0x51 */ EUCTW_LATIN1, /* 0x52 */ EUCTW_LATIN1, /* 0x53 */ EUCTW_LATIN1, /* 0x54 */ EUCTW_LATIN1, /* 0x55 */ EUCTW_LATIN1, /* 0x56 */ EUCTW_LATIN1, /* 0x57 */ EUCTW_LATIN1, /* 0x58 */ EUCTW_LATIN1, /* 0x59 */ EUCTW_LATIN1, /* 0x5a */ EUCTW_LATIN1, /* 0x5b */ EUCTW_LATIN1, /* 0x5c */ EUCTW_LATIN1, /* 0x5d */ EUCTW_LATIN1, /* 0x5e */ EUCTW_LATIN1, /* 0x5f */ EUCTW_LATIN1, /* 0x60 */ EUCTW_LATIN1, /* 0x61 */ EUCTW_LATIN1, /* 0x62 */ EUCTW_LATIN1, /* 0x63 */ EUCTW_LATIN1, /* 0x64 */ EUCTW_LATIN1, /* 0x65 */ EUCTW_LATIN1, /* 0x66 */ EUCTW_LATIN1, /* 0x67 */ EUCTW_LATIN1, /* 0x68 */ EUCTW_LATIN1, /* 0x69 */ EUCTW_LATIN1, /* 0x6a */ EUCTW_LATIN1, /* 0x6b */ EUCTW_LATIN1, /* 0x6c */ EUCTW_LATIN1, /* 0x6d */ EUCTW_LATIN1, /* 0x6e */ EUCTW_LATIN1, /* 0x6f */ EUCTW_LATIN1, /* 0x70 */ EUCTW_LATIN1, /* 0x71 */ EUCTW_LATIN1, /* 0x72 */ EUCTW_LATIN1, /* 0x73 */ EUCTW_LATIN1, /* 0x74 */ EUCTW_LATIN1, /* 0x75 */ EUCTW_LATIN1, /* 0x76 */ EUCTW_LATIN1, /* 0x77 */ EUCTW_LATIN1, /* 0x78 */ EUCTW_LATIN1, /* 0x79 */ EUCTW_LATIN1, /* 0x7a */ EUCTW_LATIN1, /* 0x7b */ EUCTW_LATIN1, /* 0x7c */ EUCTW_LATIN1, /* 0x7d */ EUCTW_LATIN1, /* 0x7e */ EUCTW_LATIN1, /* 0x7f */ EUCTW_LATIN1, /* 0x80 */ EUCTW_LATIN1, /* 0x81 */ EUCTW_LATIN1, /* 0x82 */ EUCTW_LATIN1, /* 0x83 */ EUCTW_LATIN1, /* 0x84 */ EUCTW_LATIN1, /* 0x85 */ EUCTW_LATIN1, /* 0x86 */ EUCTW_LATIN1, /* 0x87 */ EUCTW_LATIN1, /* 0x88 */ EUCTW_LATIN1, /* 0x89 */ EUCTW_LATIN1, /* 0x8a */ EUCTW_LATIN1, /* 0x8b */ EUCTW_LATIN1, /* 0x8c */ EUCTW_LATIN1, /* 0x8d */ EUCTW_LATIN1, /* 0x8e */ EUCTW_CNS11643_2, /* 0x8f */ EUCTW_LATIN1, /* 0x90 */ EUCTW_LATIN1, /* 0x91 */ EUCTW_LATIN1, /* 0x92 */ EUCTW_LATIN1, /* 0x93 */ EUCTW_LATIN1, /* 0x94 */ EUCTW_LATIN1, /* 0x95 */ EUCTW_LATIN1, /* 0x96 */ EUCTW_LATIN1, /* 0x97 */ EUCTW_LATIN1, /* 0x98 */ EUCTW_LATIN1, /* 0x99 */ EUCTW_LATIN1, /* 0x9a */ EUCTW_LATIN1, /* 0x9b */ EUCTW_LATIN1, /* 0x9c */ EUCTW_LATIN1, /* 0x9d */ EUCTW_LATIN1, /* 0x9e */ EUCTW_LATIN1, /* 0x9f */ EUCTW_LATIN1, /* 0xa0 */ EUCTW_LATIN1, /* 0xa1 */ EUCTW_CNS11643_1, /* 0xa2 */ EUCTW_CNS11643_1, /* 0xa3 */ EUCTW_CNS11643_1, /* 0xa4 */ EUCTW_CNS11643_1, /* 0xa5 */ EUCTW_CNS11643_1, /* 0xa6 */ EUCTW_CNS11643_1, /* 0xa7 */ EUCTW_CNS11643_1, /* 0xa8 */ EUCTW_CNS11643_1, /* 0xa9 */ EUCTW_CNS11643_1, /* 0xaa */ EUCTW_CNS11643_1, /* 0xab */ EUCTW_CNS11643_1, /* 0xac */ EUCTW_CNS11643_1, /* 0xad */ EUCTW_CNS11643_1, /* 0xae */ EUCTW_CNS11643_1, /* 0xaf */ EUCTW_CNS11643_1, /* 0xb0 */ EUCTW_CNS11643_1, /* 0xb1 */ EUCTW_CNS11643_1, /* 0xb2 */ EUCTW_CNS11643_1, /* 0xb3 */ EUCTW_CNS11643_1, /* 0xb4 */ EUCTW_CNS11643_1, /* 0xb5 */ EUCTW_CNS11643_1, /* 0xb6 */ EUCTW_CNS11643_1, /* 0xb7 */ EUCTW_CNS11643_1, /* 0xb8 */ EUCTW_CNS11643_1, /* 0xb9 */ EUCTW_CNS11643_1, /* 0xba */ EUCTW_CNS11643_1, /* 0xbb */ EUCTW_CNS11643_1, /* 0xbc */ EUCTW_CNS11643_1, /* 0xbd */ EUCTW_CNS11643_1, /* 0xbe */ EUCTW_CNS11643_1, /* 0xbf */ EUCTW_CNS11643_1, /* 0xc0 */ EUCTW_CNS11643_1, /* 0xc1 */ EUCTW_CNS11643_1, /* 0xc2 */ EUCTW_CNS11643_1, /* 0xc3 */ EUCTW_CNS11643_1, /* 0xc4 */ EUCTW_CNS11643_1, /* 0xc5 */ EUCTW_CNS11643_1, /* 0xc6 */ EUCTW_CNS11643_1, /* 0xc7 */ EUCTW_CNS11643_1, /* 0xc8 */ EUCTW_CNS11643_1, /* 0xc9 */ EUCTW_CNS11643_1, /* 0xca */ EUCTW_CNS11643_1, /* 0xcb */ EUCTW_CNS11643_1, /* 0xcc */ EUCTW_CNS11643_1, /* 0xcd */ EUCTW_CNS11643_1, /* 0xce */ EUCTW_CNS11643_1, /* 0xcf */ EUCTW_CNS11643_1, /* 0xd0 */ EUCTW_CNS11643_1, /* 0xd1 */ EUCTW_CNS11643_1, /* 0xd2 */ EUCTW_CNS11643_1, /* 0xd3 */ EUCTW_CNS11643_1, /* 0xd4 */ EUCTW_CNS11643_1, /* 0xd5 */ EUCTW_CNS11643_1, /* 0xd6 */ EUCTW_CNS11643_1, /* 0xd7 */ EUCTW_CNS11643_1, /* 0xd8 */ EUCTW_CNS11643_1, /* 0xd9 */ EUCTW_CNS11643_1, /* 0xda */ EUCTW_CNS11643_1, /* 0xdb */ EUCTW_CNS11643_1, /* 0xdc */ EUCTW_CNS11643_1, /* 0xdd */ EUCTW_CNS11643_1, /* 0xde */ EUCTW_CNS11643_1, /* 0xdf */ EUCTW_CNS11643_1, /* 0xe0 */ EUCTW_CNS11643_1, /* 0xe1 */ EUCTW_CNS11643_1, /* 0xe2 */ EUCTW_CNS11643_1, /* 0xe3 */ EUCTW_CNS11643_1, /* 0xe4 */ EUCTW_CNS11643_1, /* 0xe5 */ EUCTW_CNS11643_1, /* 0xe6 */ EUCTW_CNS11643_1, /* 0xe7 */ EUCTW_CNS11643_1, /* 0xe8 */ EUCTW_CNS11643_1, /* 0xe9 */ EUCTW_CNS11643_1, /* 0xea */ EUCTW_CNS11643_1, /* 0xeb */ EUCTW_CNS11643_1, /* 0xec */ EUCTW_CNS11643_1, /* 0xed */ EUCTW_CNS11643_1, /* 0xee */ EUCTW_CNS11643_1, /* 0xef */ EUCTW_CNS11643_1, /* 0xf0 */ EUCTW_CNS11643_1, /* 0xf1 */ EUCTW_CNS11643_1, /* 0xf2 */ EUCTW_CNS11643_1, /* 0xf3 */ EUCTW_CNS11643_1, /* 0xf4 */ EUCTW_CNS11643_1, /* 0xf5 */ EUCTW_CNS11643_1, /* 0xf6 */ EUCTW_CNS11643_1, /* 0xf7 */ EUCTW_CNS11643_1, /* 0xf8 */ EUCTW_CNS11643_1, /* 0xf9 */ EUCTW_CNS11643_1, /* 0xfa */ EUCTW_CNS11643_1, /* 0xfb */ EUCTW_CNS11643_1, /* 0xfc */ EUCTW_CNS11643_1, /* 0xfd */ EUCTW_CNS11643_1, /* 0xfe */ EUCTW_CNS11643_1, /* 0xff */ EUCTW_LATIN1, }; static XP_Bool fe_AreEUCTWFontsAvail(int16 win_csid) { /* this needs to match the code in fe_LoadEUCTWFont */ if (((fe_FontCharSets[CS_CNS11643_1 & 0xff].name == NULL) || (fe_FontCharSets[CS_CNS11643_2 & 0xff].name == NULL)) && (fe_FontCharSets[CS_CNS11643_1110 & 0xff].name == NULL)) return FALSE; else return TRUE; } static fe_Font fe_LoadEUCTWFont(MWContext *context, char *familyName, int points, int sizeNum, int fontmask, int charset, int pitch, int faceNum, Display *dpy) { int16 cs; int len; fe_FontGroupFont *ret; len = (3 * sizeof(fe_FontGroupFont)); ret = calloc(1, len); if (!ret) { return NULL; } (void) memset(ret, 0, len); cs = CS_LATIN1; ret[0].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask); if (cs != CS_LATIN1) { XP_FREE(ret); return NULL; } /* this needs to match the code in fe_AreEUCTWFontsAvail */ cs = CS_CNS11643_1; ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask); if (cs == CS_CNS11643_1) { ret[1].mask1 = 0x7f; ret[1].mask2 = 0x7f; } else { ret[1].xFont = NULL; } cs = CS_CNS11643_2; ret[2].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask); if (cs == CS_CNS11643_2) { ret[2].mask1 = 0x7f; ret[2].mask2 = 0x7f; } else { ret[2].xFont = NULL; } if ((!ret[1].xFont) || (!ret[2].xFont)) { cs = CS_CNS11643_1110; ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask); if (cs == CS_CNS11643_1110) { ret[1].mask1 = 0xff; ret[1].mask2 = 0xff; ret[2].xFont = ret[1].xFont; ret[2].mask1 = 0xff; ret[2].mask2 = 0x7f; } else { XP_FREE(ret); return NULL; } } return (fe_Font) ret; } static XmString fe_EUCTWToXmString(int16 charset, fe_Font fontGroup, char * string, int len) { return fe_EUCToXmString(charset, fontGroup, string, len, EUCTWTable); } static void fe_EUCTWTextExtents(fe_Font font, char *string, int len, int *direction, int *fontAscent, int *fontDescent, XCharStruct *overall) { fe_ProcessEUCString(CS_CNS_8BIT, EUCTWTable, NULL, NULL, NULL, None, font, NULL, 0, 0, string, len, fontAscent, fontDescent, overall, fe_CharSetFuncsArray[FE_FONT_INFO_EUCTW].numberOfFonts); } static void fe_DrawEUCTWString(Display *dpy, Drawable d, fe_Font font, GC gc, int x, int y, char *string, int len) { fe_ProcessEUCString(CS_CNS_8BIT, EUCTWTable, (fe_XDrawStringFunc) XDrawString, (fe_XDrawStringFunc) XDrawString16, dpy, d, font, gc, x, y, string, len, NULL, NULL, NULL, 0); } static void fe_DrawEUCTWImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2, int x, int y, char *string, int len) { fe_ProcessEUCString(CS_CNS_8BIT, EUCTWTable, (fe_XDrawStringFunc) XDrawImageString, (fe_XDrawStringFunc) XDrawImageString16, dpy, d, font, gc, x, y, string, len, NULL, NULL, NULL, 0); } /* fontIndex skip len */ #define BIG5_LATIN1 { 0, 0, 1 } #define BIG5_BIG5 { 1, 0, 2 } static fe_StringProcessTable BIG5Table[] = { /* 0x00 */ BIG5_LATIN1, /* 0x01 */ BIG5_LATIN1, /* 0x02 */ BIG5_LATIN1, /* 0x03 */ BIG5_LATIN1, /* 0x04 */ BIG5_LATIN1, /* 0x05 */ BIG5_LATIN1, /* 0x06 */ BIG5_LATIN1, /* 0x07 */ BIG5_LATIN1, /* 0x08 */ BIG5_LATIN1, /* 0x09 */ BIG5_LATIN1, /* 0x0a */ BIG5_LATIN1, /* 0x0b */ BIG5_LATIN1, /* 0x0c */ BIG5_LATIN1, /* 0x0d */ BIG5_LATIN1, /* 0x0e */ BIG5_LATIN1, /* 0x0f */ BIG5_LATIN1, /* 0x10 */ BIG5_LATIN1, /* 0x11 */ BIG5_LATIN1, /* 0x12 */ BIG5_LATIN1, /* 0x13 */ BIG5_LATIN1, /* 0x14 */ BIG5_LATIN1, /* 0x15 */ BIG5_LATIN1, /* 0x16 */ BIG5_LATIN1, /* 0x17 */ BIG5_LATIN1, /* 0x18 */ BIG5_LATIN1, /* 0x19 */ BIG5_LATIN1, /* 0x1a */ BIG5_LATIN1, /* 0x1b */ BIG5_LATIN1, /* 0x1c */ BIG5_LATIN1, /* 0x1d */ BIG5_LATIN1, /* 0x1e */ BIG5_LATIN1, /* 0x1f */ BIG5_LATIN1, /* 0x20 */ BIG5_LATIN1, /* 0x21 */ BIG5_LATIN1, /* 0x22 */ BIG5_LATIN1, /* 0x23 */ BIG5_LATIN1, /* 0x24 */ BIG5_LATIN1, /* 0x25 */ BIG5_LATIN1, /* 0x26 */ BIG5_LATIN1, /* 0x27 */ BIG5_LATIN1, /* 0x28 */ BIG5_LATIN1, /* 0x29 */ BIG5_LATIN1, /* 0x2a */ BIG5_LATIN1, /* 0x2b */ BIG5_LATIN1, /* 0x2c */ BIG5_LATIN1, /* 0x2d */ BIG5_LATIN1, /* 0x2e */ BIG5_LATIN1, /* 0x2f */ BIG5_LATIN1, /* 0x30 */ BIG5_LATIN1, /* 0x31 */ BIG5_LATIN1, /* 0x32 */ BIG5_LATIN1, /* 0x33 */ BIG5_LATIN1, /* 0x34 */ BIG5_LATIN1, /* 0x35 */ BIG5_LATIN1, /* 0x36 */ BIG5_LATIN1, /* 0x37 */ BIG5_LATIN1, /* 0x38 */ BIG5_LATIN1, /* 0x39 */ BIG5_LATIN1, /* 0x3a */ BIG5_LATIN1, /* 0x3b */ BIG5_LATIN1, /* 0x3c */ BIG5_LATIN1, /* 0x3d */ BIG5_LATIN1, /* 0x3e */ BIG5_LATIN1, /* 0x3f */ BIG5_LATIN1, /* 0x40 */ BIG5_LATIN1, /* 0x41 */ BIG5_LATIN1, /* 0x42 */ BIG5_LATIN1, /* 0x43 */ BIG5_LATIN1, /* 0x44 */ BIG5_LATIN1, /* 0x45 */ BIG5_LATIN1, /* 0x46 */ BIG5_LATIN1, /* 0x47 */ BIG5_LATIN1, /* 0x48 */ BIG5_LATIN1, /* 0x49 */ BIG5_LATIN1, /* 0x4a */ BIG5_LATIN1, /* 0x4b */ BIG5_LATIN1, /* 0x4c */ BIG5_LATIN1, /* 0x4d */ BIG5_LATIN1, /* 0x4e */ BIG5_LATIN1, /* 0x4f */ BIG5_LATIN1, /* 0x50 */ BIG5_LATIN1, /* 0x51 */ BIG5_LATIN1, /* 0x52 */ BIG5_LATIN1, /* 0x53 */ BIG5_LATIN1, /* 0x54 */ BIG5_LATIN1, /* 0x55 */ BIG5_LATIN1, /* 0x56 */ BIG5_LATIN1, /* 0x57 */ BIG5_LATIN1, /* 0x58 */ BIG5_LATIN1, /* 0x59 */ BIG5_LATIN1, /* 0x5a */ BIG5_LATIN1, /* 0x5b */ BIG5_LATIN1, /* 0x5c */ BIG5_LATIN1, /* 0x5d */ BIG5_LATIN1, /* 0x5e */ BIG5_LATIN1, /* 0x5f */ BIG5_LATIN1, /* 0x60 */ BIG5_LATIN1, /* 0x61 */ BIG5_LATIN1, /* 0x62 */ BIG5_LATIN1, /* 0x63 */ BIG5_LATIN1, /* 0x64 */ BIG5_LATIN1, /* 0x65 */ BIG5_LATIN1, /* 0x66 */ BIG5_LATIN1, /* 0x67 */ BIG5_LATIN1, /* 0x68 */ BIG5_LATIN1, /* 0x69 */ BIG5_LATIN1, /* 0x6a */ BIG5_LATIN1, /* 0x6b */ BIG5_LATIN1, /* 0x6c */ BIG5_LATIN1, /* 0x6d */ BIG5_LATIN1, /* 0x6e */ BIG5_LATIN1, /* 0x6f */ BIG5_LATIN1, /* 0x70 */ BIG5_LATIN1, /* 0x71 */ BIG5_LATIN1, /* 0x72 */ BIG5_LATIN1, /* 0x73 */ BIG5_LATIN1, /* 0x74 */ BIG5_LATIN1, /* 0x75 */ BIG5_LATIN1, /* 0x76 */ BIG5_LATIN1, /* 0x77 */ BIG5_LATIN1, /* 0x78 */ BIG5_LATIN1, /* 0x79 */ BIG5_LATIN1, /* 0x7a */ BIG5_LATIN1, /* 0x7b */ BIG5_LATIN1, /* 0x7c */ BIG5_LATIN1, /* 0x7d */ BIG5_LATIN1, /* 0x7e */ BIG5_LATIN1, /* 0x7f */ BIG5_LATIN1, /* 0x80 */ BIG5_LATIN1, /* 0x81 */ BIG5_LATIN1, /* 0x82 */ BIG5_LATIN1, /* 0x83 */ BIG5_LATIN1, /* 0x84 */ BIG5_LATIN1, /* 0x85 */ BIG5_LATIN1, /* 0x86 */ BIG5_LATIN1, /* 0x87 */ BIG5_LATIN1, /* 0x88 */ BIG5_LATIN1, /* 0x89 */ BIG5_LATIN1, /* 0x8a */ BIG5_LATIN1, /* 0x8b */ BIG5_LATIN1, /* 0x8c */ BIG5_LATIN1, /* 0x8d */ BIG5_LATIN1, /* 0x8e */ BIG5_LATIN1, /* 0x8f */ BIG5_LATIN1, /* 0x90 */ BIG5_LATIN1, /* 0x91 */ BIG5_LATIN1, /* 0x92 */ BIG5_LATIN1, /* 0x93 */ BIG5_LATIN1, /* 0x94 */ BIG5_LATIN1, /* 0x95 */ BIG5_LATIN1, /* 0x96 */ BIG5_LATIN1, /* 0x97 */ BIG5_LATIN1, /* 0x98 */ BIG5_LATIN1, /* 0x99 */ BIG5_LATIN1, /* 0x9a */ BIG5_LATIN1, /* 0x9b */ BIG5_LATIN1, /* 0x9c */ BIG5_LATIN1, /* 0x9d */ BIG5_LATIN1, /* 0x9e */ BIG5_LATIN1, /* 0x9f */ BIG5_LATIN1, /* 0xa0 */ BIG5_LATIN1, /* 0xa1 */ BIG5_BIG5, /* 0xa2 */ BIG5_BIG5, /* 0xa3 */ BIG5_BIG5, /* 0xa4 */ BIG5_BIG5, /* 0xa5 */ BIG5_BIG5, /* 0xa6 */ BIG5_BIG5, /* 0xa7 */ BIG5_BIG5, /* 0xa8 */ BIG5_BIG5, /* 0xa9 */ BIG5_BIG5, /* 0xaa */ BIG5_BIG5, /* 0xab */ BIG5_BIG5, /* 0xac */ BIG5_BIG5, /* 0xad */ BIG5_BIG5, /* 0xae */ BIG5_BIG5, /* 0xaf */ BIG5_BIG5, /* 0xb0 */ BIG5_BIG5, /* 0xb1 */ BIG5_BIG5, /* 0xb2 */ BIG5_BIG5, /* 0xb3 */ BIG5_BIG5, /* 0xb4 */ BIG5_BIG5, /* 0xb5 */ BIG5_BIG5, /* 0xb6 */ BIG5_BIG5, /* 0xb7 */ BIG5_BIG5, /* 0xb8 */ BIG5_BIG5, /* 0xb9 */ BIG5_BIG5, /* 0xba */ BIG5_BIG5, /* 0xbb */ BIG5_BIG5, /* 0xbc */ BIG5_BIG5, /* 0xbd */ BIG5_BIG5, /* 0xbe */ BIG5_BIG5, /* 0xbf */ BIG5_BIG5, /* 0xc0 */ BIG5_BIG5, /* 0xc1 */ BIG5_BIG5, /* 0xc2 */ BIG5_BIG5, /* 0xc3 */ BIG5_BIG5, /* 0xc4 */ BIG5_BIG5, /* 0xc5 */ BIG5_BIG5, /* 0xc6 */ BIG5_BIG5, /* 0xc7 */ BIG5_BIG5, /* 0xc8 */ BIG5_BIG5, /* 0xc9 */ BIG5_BIG5, /* 0xca */ BIG5_BIG5, /* 0xcb */ BIG5_BIG5, /* 0xcc */ BIG5_BIG5, /* 0xcd */ BIG5_BIG5, /* 0xce */ BIG5_BIG5, /* 0xcf */ BIG5_BIG5, /* 0xd0 */ BIG5_BIG5, /* 0xd1 */ BIG5_BIG5, /* 0xd2 */ BIG5_BIG5, /* 0xd3 */ BIG5_BIG5, /* 0xd4 */ BIG5_BIG5, /* 0xd5 */ BIG5_BIG5, /* 0xd6 */ BIG5_BIG5, /* 0xd7 */ BIG5_BIG5, /* 0xd8 */ BIG5_BIG5, /* 0xd9 */ BIG5_BIG5, /* 0xda */ BIG5_BIG5, /* 0xdb */ BIG5_BIG5, /* 0xdc */ BIG5_BIG5, /* 0xdd */ BIG5_BIG5, /* 0xde */ BIG5_BIG5, /* 0xdf */ BIG5_BIG5, /* 0xe0 */ BIG5_BIG5, /* 0xe1 */ BIG5_BIG5, /* 0xe2 */ BIG5_BIG5, /* 0xe3 */ BIG5_BIG5, /* 0xe4 */ BIG5_BIG5, /* 0xe5 */ BIG5_BIG5, /* 0xe6 */ BIG5_BIG5, /* 0xe7 */ BIG5_BIG5, /* 0xe8 */ BIG5_BIG5, /* 0xe9 */ BIG5_BIG5, /* 0xea */ BIG5_BIG5, /* 0xeb */ BIG5_BIG5, /* 0xec */ BIG5_BIG5, /* 0xed */ BIG5_BIG5, /* 0xee */ BIG5_BIG5, /* 0xef */ BIG5_BIG5, /* 0xf0 */ BIG5_BIG5, /* 0xf1 */ BIG5_BIG5, /* 0xf2 */ BIG5_BIG5, /* 0xf3 */ BIG5_BIG5, /* 0xf4 */ BIG5_BIG5, /* 0xf5 */ BIG5_BIG5, /* 0xf6 */ BIG5_BIG5, /* 0xf7 */ BIG5_BIG5, /* 0xf8 */ BIG5_BIG5, /* 0xf9 */ BIG5_BIG5, /* 0xfa */ BIG5_BIG5, /* 0xfb */ BIG5_BIG5, /* 0xfc */ BIG5_BIG5, /* 0xfd */ BIG5_BIG5, /* 0xfe */ BIG5_BIG5, /* 0xff */ BIG5_LATIN1, }; static XP_Bool fe_AreBIG5FontsAvail(int16 win_csid) { /* this needs to match the code in fe_LoadBIG5Font */ if (fe_FontCharSets[CS_X_BIG5 & 0xff].name == NULL) return FALSE; else return TRUE; } static fe_Font fe_LoadBIG5Font(MWContext *context, char *familyName, int points, int sizeNum, int fontmask, int charset, int pitch, int faceNum, Display *dpy) { int16 cs; int len; fe_FontGroupFont *ret; len = (2 * sizeof(fe_FontGroupFont)); ret = calloc(1, len); if (!ret) { return NULL; } (void) memset(ret, 0, len); cs = CS_LATIN1; ret[0].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask); if (cs != CS_LATIN1) { XP_FREE(ret); return NULL; } /* this needs to match the code in fe_AreBIG5FontsAvail */ cs = CS_X_BIG5; ret[1].xFont = (XFontStruct *) fe_LoadFont(context, &cs, familyName, points, sizeNum, fontmask); if (cs == CS_X_BIG5) { ret[1].mask1 = 0xff; ret[1].mask2 = 0xff; } else { XP_FREE(ret); return NULL; } return (fe_Font) ret; } static XmString fe_BIG5ToXmString(int16 charset, fe_Font fontGroup, char * string, int len) { return fe_EUCToXmString(charset, fontGroup, string, len, BIG5Table); } static void fe_BIG5TextExtents(fe_Font font, char *string, int len, int *direction, int *fontAscent, int *fontDescent, XCharStruct *overall) { fe_ProcessEUCString(CS_BIG5, BIG5Table, NULL, NULL, NULL, None, font, NULL, 0, 0, string, len, fontAscent, fontDescent, overall, fe_CharSetFuncsArray[FE_FONT_INFO_BIG5].numberOfFonts); } static void fe_DrawBIG5String(Display *dpy, Drawable d, fe_Font font, GC gc, int x, int y, char *string, int len) { fe_ProcessEUCString(CS_BIG5, BIG5Table, (fe_XDrawStringFunc) XDrawString, (fe_XDrawStringFunc) XDrawString16, dpy, d, font, gc, x, y, string, len, NULL, NULL, NULL, 0); } static void fe_DrawBIG5ImageString(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2, int x, int y, char *string, int len) { fe_ProcessEUCString(CS_BIG5, BIG5Table, (fe_XDrawStringFunc) XDrawImageString, (fe_XDrawStringFunc) XDrawImageString16, dpy, d, font, gc, x, y, string, len, NULL, NULL, NULL, 0); } int fe_UnicodePointToPixelSize(Display *dpy, int pointSize) { int pixelSize; static double pointToPixelFactor; static XP_Bool inited = FALSE; char name[512], class[512]; char *type; XrmValue value; if (!inited) { inited = TRUE; pointToPixelFactor = ((WidthOfScreen(DefaultScreenOfDisplay(dpy)) / (WidthMMOfScreen(DefaultScreenOfDisplay(dpy)) / 25.4)) / 72.27) / 10; /* * Get the users resource setting */ (void) PR_snprintf(name, sizeof(name), "%s.unicodeFont.screenDpi", fe_progclass); (void) PR_snprintf(class, sizeof(class),"%s.UnicodeFont.ScreenDpi", fe_progclass); if (XrmGetResource(XtDatabase(dpy), name, class, &type, &value)){ float userScreenDpi; if (sscanf((char *)value.addr, "%e", &userScreenDpi)) { pointToPixelFactor = (userScreenDpi/72.27) / 10; } } } pointSize += 4; /* round up */ pixelSize = (int)(pointSize * pointToPixelFactor); return pixelSize; } static XP_Bool fe_AreUnicodeFontsAvail(int16 win_csid) { /* * since we build unicode fonts from other fonts * there is not a good way to tell what will be * avail so just assume we can do it */ return TRUE; } /* * fe_LoadUnicodeFont - load (create) a Unicode Pseudo Font * * see fe_loadUnicodePseudoFonts() for information on Unicode Pseudo Fonts * */ fe_Font fe_LoadUnicodeFont(void *not_used, char *familyName, int points, int sizeNum, int fontmask, int charset, int pitch, int faceNum, Display *dpy) { fe_UnicodePseudoFont *ufont; fe_FontFamily *unicodeFamily = NULL; fe_FontSize *unicodeSize; int pixelSize; /* * If the familyName is specified then find it * else use the selected family */ if (familyName) { unicodeFamily = fe_FontFindFamily(CS_UTF8, pitch, familyName); } /* * If the familyName is not specified or that family not found * then use the selected family */ if (!unicodeFamily) { unicodeFamily = fe_GetFontFamily(CS_UTF8, pitch); familyName = unicodeFamily->family; } unicodeSize = unicodeFamily->htmlSizes[sizeNum-1]; pixelSize = fe_UnicodePointToPixelSize(dpy, unicodeSize->size); ufont = fe_LoadUnicodeFontByPixelSize(not_used, familyName, pixelSize, fontmask, charset, pitch, faceNum, dpy); return ufont; } /* * fe_LoadUnicodeFontByPixelSize - load (create) a Unicode Pseudo Font * * see fe_loadUnicodePseudoFonts() for information on Unicode Pseudo Fonts * */ fe_Font fe_LoadUnicodeFontByPixelSize(void *not_used, char *familyName, int pixelSize, int fontmask, int charset, int pitch, int faceNum, Display *dpy) { fe_UnicodePseudoFont *ufont; ufont = (fe_UnicodePseudoFont*)calloc(1, sizeof(fe_UnicodePseudoFont)); if (!ufont) { return NULL; } ufont->tag = UNICODE_PSEUDO_FONT_TAG; ufont->family = strdup(familyName); ufont->dpy = dpy; ufont->pixelSize = pixelSize; ufont->fontmask = fontmask; ufont->pitch = pitch; ufont->faceNum = faceNum; ufont->ascent = 0; ufont->descent = 0; return ufont; } static XmFontList fe_UTF8GetFontList(int16 charset, fe_Font font, int numOfFonts) { fe_UnicodePseudoFont *ufont = (fe_UnicodePseudoFont *)font; XP_ASSERT( NULL != ufont); XP_ASSERT( NULL != ufont->xmfontlist); return XmFontListCopy(ufont->xmfontlist); } static XmString fe_UTF8ToXmString(int16 charset, fe_Font fontGroup, char * string, int len) { XP_ASSERT(0); return NULL; /* to make compiler happen */ } void fe_freeUnicodePseudoFont(fe_Font font) { fe_UnicodePseudoFont *ufont = (fe_UnicodePseudoFont *)font; int i_encodings; if (ufont->tag != UNICODE_PSEUDO_FONT_TAG) { #ifdef DEBUG_bstell printf("bad ufont %s %d\n", __FILE__, __LINE__); #endif return; } if (ufont->family) free(ufont->family); /* * Free any scaled fonts */ for (i_encodings=0; i_encodingsxfont_scaled[i_encodings]) { XFreeFont(ufont->dpy, ufont->xFonts[i_encodings]); XP_FREE(ufont->xfont_name[i_encodings]); } } if (ufont->xmfontlist) XmFontListFree(ufont->xmfontlist); if (ufont->xm_fontset) XmFontListFree(ufont->xm_fontset); if (ufont->xfontset) XFreeFontSet(ufont->dpy, ufont->xfontset); free(ufont); } static char * fe_UnicodeEquivFontName(fe_UnicodePseudoFont *ufont, uint16 charsetID) { XrmDatabase db; char name[512], class[512]; char *csid_name, *type; XrmValue value; charsetID &= 0xFF; if (ufont->fontFamily[charsetID&0xFF]) return (ufont->fontFamily[charsetID]); db = XtDatabase(ufont->dpy); csid_name = INTL_CsidToCharsetNamePt(charsetID); (void) PR_snprintf(name, sizeof(name), "%s.unicodeFont.%s.%s", fe_progclass, ufont->family, csid_name); (void) PR_snprintf(class, sizeof(class), "%s.UnicodeFont.%s.%s", fe_progclass, ufont->family, "Name"); if (XrmGetResource(db, name, class, &type, &value)) ufont->fontFamily[charsetID] = strdup(value.addr); else ufont->fontFamily[charsetID] = strdup(ufont->family); return (ufont->fontFamily[charsetID]); } /* * Rate the Quality of the font match * * a return range 0.0 to 1.0 * 1.0 means perfect match * lower numbers mean poorer match */ static int fe_UnicodeFontQ(fe_UnicodePseudoFont *ufont, int32 target_height, int32 actual_height, XP_Bool family_match, XP_Bool weight_match, XP_Bool slant_match, int target_pitch, XP_Bool pitch_match ) { float q = 1.0; /* * Look at size match */ if (actual_height <= target_height) q *= (float)actual_height / (float)target_height; else q *= (float)target_height / (float)actual_height; /* * Look at family match (correct font family) */ if (!family_match) q *= 0.8; #ifdef DEBUG_bstell else q *= 1.0; #endif /* * Look at weight match (regular vs bold) */ if (!weight_match) q *= 0.75; /* * Look at slant match (regular vs italic) */ if (!slant_match) q *= 0.5; /* * Look at pitch match (monospaced vs proportional) * * Pitch doesn't mean much to most users but: * many (older) applications assume a monospaced font * and won't work correctly with a proportional font * Hence if the target font is monospaced * we strongly want the pitch to be right */ if (!pitch_match) { if (target_pitch == 0) /* proportional */ q *= 0.8; else /* MONO */ q *= 0.0; } return (int)(q * 100); } #define IS_ORIG_PITCH(pitch) ((pitch)==0) #define IS_ORIG_WEIGHT_FACE(face) (((face)&1)==0) #define IS_ORIG_SLANT_FACE(face) (((face)&2)==0) /* * fe_UnicodeFindFontInRange * * find the font for this encoding with the UnicodePseudoFont's * specified font name / slant / weight * no scaling * size range = minPixelSize to maxPixelSize * either pitch */ static XFontStruct * fe_UnicodeFindFontInRange(fe_UnicodePseudoFont *ufont, uint16 charsetID, int32 maxPixelSize, int32 minPixelSize, XP_Bool any_weight, char **name) { int pitch, i_pitch, i_pnt; fe_FontSize *size; fe_FontFamily *fontFamily; char *family; int bestFoundQ = 0; int thisFontQ; int bestFoundFaceNum; fe_FontSize *bestFoundSize = NULL; /* * Get the equivalent font name for this encoding */ family = fe_UnicodeEquivFontName(ufont, charsetID); /* * Find the font */ for (i_pitch=0; i_pitch<2; i_pitch++) { if (IS_ORIG_PITCH(i_pitch)) pitch = ufont->pitch; else pitch = FE_OPPOSITE_PITCH(ufont->pitch); fontFamily = fe_FontFindFamily(charsetID, pitch, family); if (fontFamily == NULL) continue; /* scan pixel sizes for largest size that is not too big */ for (i_pnt=fontFamily->numberOfPixelSizes-1; i_pnt>=0; i_pnt--) { size = &fontFamily->pixelSizes[i_pnt]; /* stop when sizes are too small */ if (size->sizesize>=maxPixelSize) ufont->larger_fonts_avail[charsetID] = TRUE; if ((size->size>=minPixelSize) && (size->size<=maxPixelSize)) { int i_face, faceNum; for (i_face=0; i_face<2; i_face++) { if (IS_ORIG_WEIGHT_FACE(i_face)) faceNum = ufont->faceNum; else { if (!any_weight) continue; faceNum = FE_OPPOSITE_WEIGHT_FACE(ufont->faceNum); } /* load font if necessary */ if (!size->faces[faceNum]) continue; thisFontQ = fe_UnicodeFontQ(ufont, maxPixelSize, size->size, /* family_match */ TRUE, IS_ORIG_WEIGHT_FACE(i_face), TRUE, ufont->pitch, IS_ORIG_PITCH(i_pitch)); if (thisFontQ > bestFoundQ) { bestFoundQ = thisFontQ; bestFoundSize = size; bestFoundFaceNum = faceNum; } } } } } if (bestFoundSize != NULL) { if (!bestFoundSize->faces[bestFoundFaceNum]->loaded) { bestFoundSize->faces[bestFoundFaceNum]->loaded = TRUE; bestFoundSize->faces[bestFoundFaceNum]->font = fe_LoadXFont(ufont->dpy, bestFoundSize->faces[bestFoundFaceNum]->longXLFDFontName); } if (bestFoundSize->faces[bestFoundFaceNum]->font) { *name = bestFoundSize->faces[bestFoundFaceNum]->longXLFDFontName; return bestFoundSize->faces[bestFoundFaceNum]->font; } } *name = ""; return NULL; } /* * fe_UnicodeFindFontSloppy * * find the font for this encoding with the UnicodePseudoFont's * ANY FAMILY */ static XFontStruct * fe_UnicodeFindFontSloppy(fe_UnicodePseudoFont *ufont, uint16 charsetID, int32 maxPixelSize, int32 minPixelSize, XP_Bool allow_scaling, XP_Bool any_weight, XP_Bool any_slant, char **name) { int i_family, i_pitch, i_pnt, i_face; fe_FontPitch *fontPitch; fe_FontSize *size = NULL; fe_FontFamily *fontFamily = NULL; fe_FontCharSet *fontCharset; XFontStruct *scaled_font; fe_FontSize *bestFoundSize = NULL; fe_FontFamily *bestFontFamily = NULL; int bestFoundQ = 0; int thisFontQ; int bestFoundFaceNum = 0; fe_FontFamily *targetFontFamily; char *targetFamily; if (minPixelSize < 1) minPixelSize = 1; fontCharset = &fe_FontCharSets[charsetID]; /* * Get the equivalent font name for this encoding */ targetFamily = fe_UnicodeEquivFontName(ufont, charsetID); /* * Find the font */ for (i_pitch=0; i_pitch<2; i_pitch++) { if IS_ORIG_PITCH(i_pitch) { fontPitch = &fontCharset->pitches[ufont->pitch]; targetFontFamily = fe_FontFindFamily(charsetID, ufont->pitch, targetFamily); } else { fontPitch = &fontCharset->pitches[FE_OPPOSITE_PITCH(ufont->pitch)]; targetFontFamily = fe_FontFindFamily(charsetID, FE_OPPOSITE_PITCH(ufont->pitch), targetFamily); } for (i_family = 0; i_family < fontPitch->numberOfFamilies; i_family++) { fontFamily = &fontPitch->families[i_family]; for (i_pnt=fontFamily->numberOfPixelSizes-1; i_pnt>=0; i_pnt--) { size = &fontFamily->pixelSizes[i_pnt]; if ((charsetID==CS_LATIN1) && (size->size) && (size->size < smallestFontFoundSize)) smallestFontFoundSize = size->size; /* skip sizes that are too small */ if ((size->size) && (size->sizesize>=maxPixelSize) ufont->larger_fonts_avail[charsetID] = TRUE; if (((size->size>=minPixelSize) && (size->size<=maxPixelSize)) || (allow_scaling && (size->size == 0))) { int32 target_size; for (i_face=0; i_face<4; i_face++) { int faceNum = ufont->faceNum; if (!IS_ORIG_WEIGHT_FACE(i_face)) { if (!any_weight) continue; faceNum = FE_OPPOSITE_WEIGHT_FACE(faceNum); } if (!IS_ORIG_SLANT_FACE(i_face)) { if (!any_slant) continue; faceNum = FE_OPPOSITE_SLANT_FACE(faceNum); } if (!size->faces[faceNum]) continue; if (size->size) /* not scaled */ target_size = size->size; else target_size = maxPixelSize; thisFontQ = fe_UnicodeFontQ(ufont, maxPixelSize, target_size, /* family_match */ (targetFontFamily==fontFamily), IS_ORIG_WEIGHT_FACE(i_face), IS_ORIG_SLANT_FACE(i_face), ufont->pitch, IS_ORIG_PITCH(i_pitch)); if (thisFontQ > bestFoundQ) { bestFoundQ = thisFontQ; bestFoundSize = size; bestFoundFaceNum = faceNum; bestFontFamily = fontFamily; } } } } } } if (bestFoundSize != NULL) { /* load font if necessary */ if (bestFoundSize->size) { if (!bestFoundSize->faces[bestFoundFaceNum]->loaded) { bestFoundSize->faces[bestFoundFaceNum]->loaded = TRUE; bestFoundSize->faces[bestFoundFaceNum]->font = fe_LoadXFont(ufont->dpy, bestFoundSize->faces[bestFoundFaceNum]->longXLFDFontName); } if (bestFoundSize->faces[bestFoundFaceNum]->font) *name = bestFoundSize->faces[bestFoundFaceNum]->longXLFDFontName; return bestFoundSize->faces[bestFoundFaceNum]->font; } else if (allow_scaling) { *name = PR_smprintf(bestFontFamily->pixelSizes->faces[ bestFoundFaceNum]->longXLFDFontName, maxPixelSize); scaled_font = fe_LoadXFont(ufont->dpy, *name); if (scaled_font) return scaled_font; else XP_FREE(*name); } } *name = ""; return NULL; } /* * fe_UnicodeFindFontScaled * * find the font for this encoding with the UnicodePseudoFont's * specified font name / slant / weight * scaled font * either pitch */ static XFontStruct * fe_UnicodeFindFontScaled(fe_UnicodePseudoFont *ufont, uint16 charsetID, int32 maxPixelSize, char **name) { int pitch, i_pitch, i_face; char *family; fe_FontFamily *fontFamily; XFontStruct *scaled_font; fe_FontFamily *bestFontFamily = NULL; int bestFoundQ = 0; int thisFontQ; int bestFoundFaceNum = 0; /* * Get the equivalent font name for this encoding */ family = fe_UnicodeEquivFontName(ufont, charsetID); for (i_pitch=0; i_pitch<2; i_pitch++) { if (IS_ORIG_PITCH(i_pitch)) pitch = ufont->pitch; else pitch = FE_OPPOSITE_PITCH(ufont->pitch); fontFamily = fe_FontFindFamily(charsetID, pitch, family); if (fontFamily == NULL) continue; if (fontFamily->pixelSizes->size == 0) { int faceNum; for (i_face=0; i_face<2; i_face++) { if (IS_ORIG_WEIGHT_FACE(i_face)) faceNum = ufont->faceNum; else faceNum = FE_OPPOSITE_WEIGHT_FACE(ufont->faceNum); if (!fontFamily->pixelSizes->faces[faceNum]) continue; thisFontQ = fe_UnicodeFontQ(ufont, maxPixelSize, maxPixelSize, TRUE, /* family_match */ IS_ORIG_WEIGHT_FACE(i_face), TRUE, /* slant_match */ ufont->pitch, IS_ORIG_PITCH(i_pitch)); if (thisFontQ > bestFoundQ) { bestFoundQ = thisFontQ; bestFoundFaceNum = faceNum; bestFontFamily = fontFamily; } } } } if (bestFontFamily != NULL) { *name = PR_smprintf(bestFontFamily->pixelSizes->faces[ bestFoundFaceNum]->longXLFDFontName, maxPixelSize); scaled_font = fe_LoadXFont(ufont->dpy, *name); if (scaled_font) return scaled_font; else XP_FREE(*name); } *name = ""; return NULL; } static XP_Bool fe_UnicodeCheckAllowScaling(fe_UnicodePseudoFont *ufont) { XP_Bool allow_scaling; fe_FontFamily *unicodeFamily; char *server_vendor; static XP_Bool inited_server_info = FALSE; static XP_Bool is_hp_server = FALSE; static XP_Bool allow_hp_scaling = FALSE; char name[512], class[512]; char *type; XrmValue value; /* * When displaying on a HP system do not scale. * * HP scaling causes the X server to "freeze" * which makes the system unusable. * Mouse delays of 20+ seconds make it very * difficult to even exit the application. */ if (!inited_server_info) { inited_server_info = TRUE; server_vendor = ServerVendor(ufont->dpy); if (strstr(server_vendor, "Hewlett-Packard")) { is_hp_server = TRUE; } /* * Get the users resource setting */ (void) PR_snprintf(name, sizeof(name), "%s.unicodeFont.allowHPScaling", fe_progclass); (void) PR_snprintf(class, sizeof(class),"%s.UnicodeFont.AllowHPScaling", fe_progclass); if (XrmGetResource(XtDatabase(ufont->dpy), name, class, &type, &value)){ char *string = (char *)value.addr; if ((string[0]=='y') || (string[0]=='Y') || (string[0]=='t') || (string[0]=='T') || (string[0]=='1')) allow_hp_scaling = TRUE; else allow_hp_scaling = FALSE; } } if ((is_hp_server) && (!allow_hp_scaling)) return FALSE; unicodeFamily = fe_GetFontFamily(CS_UTF8, ufont->pitch); allow_scaling = unicodeFamily->allowScaling; return allow_scaling; } static XFontStruct * fe_UnicodeFindFont(fe_UnicodePseudoFont *ufont, uint16 encoding, XP_Bool *is_scaled, char **name) { uint16 charsetID; fe_FontCharSet *fontCharset; int loop_timeout; int32 maxPixelSize; XFontStruct *ret_font, *scaled_font = NULL; XP_Bool allow_scaling; /* printf("encoding = %d (%d), pixelSize = %d, pitch = %d, faceNum = %d\n", encoding, encoding&0xFF, ufont->pixelSize, ufont->pitch, ufont->faceNum); */ /* * Init return value */ *is_scaled = FALSE; /* * Check the encoding */ charsetID = encoding & 0xFF; fontCharset = &fe_FontCharSets[charsetID]; if (!fontCharset->name) { return NULL; } maxPixelSize = ufont->pixelSize; allow_scaling = fe_UnicodeCheckAllowScaling(ufont); /* * Get the best font for this size and encoding * * We loop looking for a font that will fit * The reason for the loop is that after we load the font it is * possible that the ascent or descent is too large. * If this happens we reduce the size by that amount and try again. * * The loop count is large because: * If we can only find a bestfit that is small * and this bestfit is still larger than the desired size * then we end up running thru the loop while maxPixelSize is reduced * to the pixel that bestfit is small enough. * This tends to not be efficient since the bestfit font * is only loaded once. */ #define LOOP_TIMEOUT 100 scaled_font = NULL; for (loop_timeout=0; loop_timeoutdpy, scaled_font); XP_FREE(*name); *name = ""; scaled_font = NULL; } /* * Exact Fit (non scaled) * try to find: * the family with this size range: 100% - 95% * no scaling * correct pitch/weight/slant * then try the other pitch */ ret_font = fe_UnicodeFindFontInRange(ufont, charsetID, maxPixelSize, 0.95*maxPixelSize, FALSE, name); if (ret_font) { loop_timeout += LOOP_TIMEOUT/10 - 1; goto UnicodeFindFont_foundOne; } /* * Exact Fit (scaled) * try to find: * the family with the SCALED SIZE * (X bitmap scaled fonts typically look bad) * correct slant * ANY PITCH / ANY WEIGHT */ if (allow_scaling) { scaled_font = fe_UnicodeFindFontScaled(ufont, charsetID, maxPixelSize, name); if (scaled_font) { loop_timeout += LOOP_TIMEOUT/5 - 1; ret_font = scaled_font; goto UnicodeFindFont_foundOne; } } /* * Close Fit (non scaled) * try to find: * the family with this size range: 100% - 75% * no scaling * correct slant * ANY_WEIGHT / ANY PITCH */ ret_font = fe_UnicodeFindFontInRange(ufont, charsetID, maxPixelSize, 0.75*maxPixelSize, TRUE, name); if (ret_font) { loop_timeout += LOOP_TIMEOUT/10 - 1; goto UnicodeFindFont_foundOne; } /* * Okay Fit (any family) * try to find: * size range: 100% - 75% * correct slant * ANY FAMILY / ANY WEIGHT / ANY PITCH */ ret_font = fe_UnicodeFindFontSloppy(ufont, charsetID, maxPixelSize, 0.75*maxPixelSize, allow_scaling, TRUE, FALSE, name); if (ret_font) { loop_timeout += LOOP_TIMEOUT/10 - 1; goto UnicodeFindFont_foundOne; } /* * Loose Fit (non scaled) * try to find: * size range: 100% - 50% * ANY FAMILY / ANY WEIGHT / ANY PITCH / ANY SLANT */ ret_font = fe_UnicodeFindFontSloppy(ufont, charsetID, maxPixelSize, 0.50*maxPixelSize, allow_scaling, TRUE, TRUE, name); if (ret_font) { loop_timeout += LOOP_TIMEOUT/10 - 1; goto UnicodeFindFont_foundOne; } /* * Any fit * try to find: * ANY SIZE / ANY FAMILY / ANY WEIGHT / ANY PITCH / ANY SLANT */ ret_font = fe_UnicodeFindFontSloppy(ufont, charsetID, maxPixelSize, 0.0*maxPixelSize, allow_scaling, TRUE, TRUE, name); if (ret_font) { loop_timeout += LOOP_TIMEOUT/10 - 1; goto UnicodeFindFont_foundOne; } /* * HUM ..., * must not be a font small enough * in desperation we give them a real small font. */ ret_font = fe_UnicodeFindFontSloppy(ufont, CS_LATIN1, smallestFontFoundSize, 0.0*maxPixelSize, allow_scaling, TRUE, TRUE, name); if (ret_font) { loop_timeout += LOOP_TIMEOUT/10 - 1; goto UnicodeFindFont_foundOne; } /* * Gave up trying to find a font that will fit */ goto UnicodeFindFont_failed; UnicodeFindFont_foundOne: /* * if encoding is CS_LATIN1 use the font * else check that the font will fit */ if ((encoding==CS_LATIN1) && (ufont->ascent==0) && (ufont->descent==0)){ if ((ufont->pixelSize/10) > (ret_font->ascent+ret_font->descent)) ret_font->ascent = (ufont->pixelSize/10) - ret_font->descent; ufont->ascent = ret_font->ascent; ufont->descent = ret_font->descent; } else { if (ret_font->ascent > ufont->ascent) { /* printf("ascent too big (%d), reduce by %d\n", ufont->pixelSize, ret_font->ascent - ufont->ascent); */ maxPixelSize -= (ret_font->ascent - ufont->ascent) * 10; if (maxPixelSize > 20) /* continue unless something wrong */ continue; } if (ret_font->descent > ufont->descent) { /* printf("descent too big (%d), reduce by %d\n", ret_font->descent - ufont->descent); */ maxPixelSize -= (ret_font->descent - ufont->descent) * 10; if (maxPixelSize > 20) /* continue unless something wrong */ continue; } } if (scaled_font != NULL) *is_scaled = TRUE; return ret_font; } UnicodeFindFont_failed: /* * did not find any fit */ if (encoding == CS_LATIN1) { /* if we got here something is wrong with fonts */ XFontStruct *xfont = (XFontStruct *)fe_FixedFont; ufont->ascent = xfont->ascent; ufont->descent = xfont->descent; return fe_FixedFont; } return NULL; } static XFontStruct * fe_UnicodeInitXfont(fe_UnicodePseudoFont *ufont, uint16 encoding) { XmFontListEntry flentry; uint16 charset = encoding&0xFF; if (ufont->tag != UNICODE_PSEUDO_FONT_TAG) { #ifdef DEBUG_bstell printf("bad ufont %s %d\n", __FILE__, __LINE__); #endif return fe_FixedFont; /* fallback */ } /* * Time to load the font */ ufont->xfont_inited[charset] = TRUE; ufont->xFonts[charset] = fe_UnicodeFindFont(ufont, encoding, &ufont->xfont_scaled[charset], &ufont->xfont_name[charset]); /* * Add this font to the XmFontList */ if (ufont->xFonts[charset]) { flentry = XmFontListEntryCreate(INTL_CsidToCharsetNamePt(encoding), XmFONT_IS_FONT, ufont->xFonts[charset]); ufont->xmfontlist = XmFontListAppendEntry(ufont->xmfontlist, flentry); XmFontListEntryFree(&flentry); } return ufont->xFonts[charset]; } XFontStruct * fe_UnicodeGetXfont(fe_UnicodePseudoFont *ufont, uint16 encoding) { uint16 charset = encoding&0xFF; if (ufont->tag != UNICODE_PSEUDO_FONT_TAG) { #ifdef DEBUG_bstell printf("bad ufont %s %d\n", __FILE__, __LINE__); #endif return fe_FixedFont; /* fallback */ } /* * If the xfont is already there return it */ if (ufont->xfont_inited[charset]) return ufont->xFonts[charset]; /* * Make sure CS_LATIN1 loaded so the * ascender/descender info is set */ if (encoding != CS_LATIN1) { if (ufont->xfont_inited[CS_LATIN1] == FALSE) fe_UnicodeInitXfont(ufont, CS_LATIN1); } /* * Load the font */ fe_UnicodeInitXfont(ufont, encoding); return ufont->xFonts[charset]; } XmFontList XUPF_GetXmFontList(fe_Font font) { fe_UnicodePseudoFont *ufont = (fe_UnicodePseudoFont *)font; if ((ufont==NULL) || (ufont->tag != UNICODE_PSEUDO_FONT_TAG)) { return NULL; } return ufont->xmfontlist; } /* * create a XmFontList with one XFontSet for XmText widgets * since they can only handle a single locale. */ XmFontList XUPF_GetXmFontSet(fe_Font font) { fe_UnicodePseudoFont *ufont = (fe_UnicodePseudoFont *)font; int16 *csidList; int i; char *fontNameList = NULL; char **missingCharSets; int missingCharSetCount; char *missingCharString; XmFontListEntry flentry; /* check for bad inputs */ if ((ufont==NULL) || (ufont->tag != UNICODE_PSEUDO_FONT_TAG)) { return NULL; } /* if it has already been created just use it */ if (ufont->xm_fontset) return ufont->xm_fontset; /* * get the list of charset we need */ csidList = INTL_GetXCharSetIDs(ufont->dpy); if (csidList == NULL) return NULL; /* * build the list of fontSet names */ for( i=0; csidList[i] != 0; i++ ) { char *fontName; char *newFontNameList; (void)fe_UnicodeGetXfont(ufont, csidList[i]); fontName = ufont->xfont_name[csidList[i]&0xff]; if ((fontName==NULL) || (strlen(fontName)==0)) { continue; } if (fontNameList == NULL) newFontNameList = strdup(fontName); else newFontNameList = PR_smprintf("%s,\n%s", fontNameList, fontName); if (!newFontNameList) { continue; } if (fontNameList != NULL) free(fontNameList); fontNameList = newFontNameList; } free(csidList); /* * create the XFontSet */ ufont->xfontset = XCreateFontSet(ufont->dpy, fontNameList, &missingCharSets, &missingCharSetCount, &missingCharString); flentry = XmFontListEntryCreate(XmFONTLIST_DEFAULT_TAG, XmFONT_IS_FONTSET, ufont->xfontset); ufont->xm_fontset = XmFontListAppendEntry(NULL, flentry); XmFontListEntryFree(&flentry); return ufont->xm_fontset; } int XUPF_JavaPointToPixelSize(Display *dpy, int pointSize) { static XP_Bool inited = FALSE; static XP_Bool use_point_sizing; static double pointToPixelFactor = (72.27/72.27)/10; char name[512], class[512]; char *type; XrmValue value; if (!inited) { inited = TRUE; /* * Get the users resource setting */ (void) PR_snprintf(name, sizeof(name), "%s.javaFont.usePointSizing", fe_progclass); (void) PR_snprintf(class, sizeof(class),"%s.JavaFont.UsePointSizing", fe_progclass); if (XrmGetResource(XtDatabase(dpy), name, class, &type, &value)){ char *string = (char *)value.addr; if ((string[0]=='y') || (string[0]=='Y') || (string[0]=='t') || (string[0]=='T') || (string[0]=='1')) use_point_sizing = TRUE; else use_point_sizing = FALSE; } (void) PR_snprintf(name, sizeof(name), "%s.javaFont.screenDpi", fe_progclass); (void) PR_snprintf(class, sizeof(class),"%s.JavaFont.ScreenDpi", fe_progclass); if (XrmGetResource(XtDatabase(dpy), name, class, &type, &value)){ float userScreenDpi; if (sscanf((char *)value.addr, "%e", &userScreenDpi)) { pointToPixelFactor = (userScreenDpi/72.27)/10; } } } if (use_point_sizing) return (fe_UnicodePointToPixelSize(dpy, pointSize)); else { pointSize += 4; /* round up */ return (int)(pointSize * pointToPixelFactor); } } void fe_UnicodeConvertToPlaceHolder(fe_UnicodePseudoFont *ufont, int16 *encoding, XFontStruct **xfont, unsigned char *segment, int seg_data_len) { /* unsigned char c; */ int i; /* * Handle errors */ #if 0 if (*encoding == -1) /* not utf8 */ c = '?'; else if (!*xfont) /* only bigger fonts available */ c = '?'; else /* no font at all for this encoding */ c = '?'; #endif /* 0 */ for (i=0; i< seg_data_len; i++) { segment[i] = ((unsigned char) '?') /* c */; } *encoding = CS_LATIN1; *xfont = fe_UnicodeGetXfont(ufont, CS_LATIN1); } /* * fe_UTF8TextExtents - Get the Text Extents for a UTF8 Unicode string * * Parse the string into locally displayable encoded segments * and sum up the extents for the segments * * If there are errors dummy up some space for those characters * so we can display something. * hopefully the user will see the garbage and try a different encoding */ void fe_UTF8TextExtents(fe_Font font, char *string, int len, int *direction, int *fontAscent, int *fontDescent, XCharStruct *overall) { fe_UnicodePseudoFont *ufont = (fe_UnicodePseudoFont *)font; unsigned char segment[X11STRING_LIMIT*6]; int16 encoding; int parsed_cnt = 0; int this_parsed_cnt, seg_data_len; int ascent, descent, this_direction; Dimension width; XFontStruct *xfont; XCharStruct this_overall; if ((ufont==NULL) || (ufont->tag != UNICODE_PSEUDO_FONT_TAG)) { /* something is wrong. I will just return a guess */ overall->ascent = *fontAscent = 14; overall->descent = *fontDescent = 3; overall->lbearing = 0; overall->rbearing = 0; overall->width = len*9; return; } /* * initialize the values */ *fontAscent = 0; *fontDescent = 0; overall->lbearing = 0; overall->rbearing = 0; overall->width = 0; overall->ascent = 0; overall->descent = 0; /* * Break up the unicode string into locally sizeable encoded segments */ ascent = 0; descent = 0; width = 0; while (1) { /* get a single encoding string */ this_parsed_cnt = utf8_to_local_encoding(string+parsed_cnt, len-parsed_cnt, segment, sizeof(segment), &seg_data_len, &encoding); if (this_parsed_cnt < 1) /* no more input data */ break; /* * Get the font for this segment */ if (encoding >= 0) xfont = fe_UnicodeGetXfont(ufont, encoding); else xfont = NULL; /* * Handle errors */ if ((encoding < 0) || (!xfont)) { fe_UnicodeConvertToPlaceHolder(ufont, &encoding, &xfont, segment, seg_data_len); } /* * Get the size metrics for this segment */ if (IS_16BIT_ENCODING(encoding)) { XTextExtents16(xfont, (XChar2b*)segment, seg_data_len/2, &this_direction, &ascent, &descent, &this_overall); } else { XTextExtents(xfont, segment, seg_data_len, &this_direction, &ascent, &descent, &this_overall); } /* * sum up the width so far * height (ascent/descent) comes from the theoritical size */ parsed_cnt += this_parsed_cnt; *direction = this_direction; /* which segment should I use ? */ if ((this_overall.lbearing+overall->width) < overall->lbearing) overall->lbearing = this_overall.lbearing + overall->width; overall->width += this_overall.width; overall->rbearing += this_overall.rbearing; } /* * Set the height from the theoritical size */ *fontAscent = ufont->ascent; *fontDescent = ufont->descent + 1; overall->ascent = ufont->ascent; overall->descent = ufont->descent + 1; } static void fe_DisplayUTF8String(XP_Bool imageString, Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2, int x, int y, char *string, int len) { fe_UnicodePseudoFont *ufont = (fe_UnicodePseudoFont *)font; unsigned char segment[X11STRING_LIMIT*6]; int parsed_cnt = 0; int16 encoding, charset; int this_parsed_cnt, seg_data_len; int ascent, descent, this_direction; XCharStruct this_overall; XFontStruct *xfont; if ((ufont==NULL) || (ufont->tag != UNICODE_PSEUDO_FONT_TAG)) { return; } if (!gc) { return; } while (1) { /* * get a single encoding string */ this_parsed_cnt = utf8_to_local_encoding(string+parsed_cnt, len-parsed_cnt, segment, sizeof(segment), &seg_data_len, &encoding); if (this_parsed_cnt < 1) break; parsed_cnt += this_parsed_cnt; /* * Set the font for this encoding */ if (encoding>0) xfont = fe_UnicodeGetXfont(ufont, encoding); else xfont = NULL; /* * Handle errors */ if ((encoding < 0) || (!xfont)) { fe_UnicodeConvertToPlaceHolder(ufont, &encoding, &xfont, segment, seg_data_len); } if (IS_16BIT_ENCODING(encoding)) seg_data_len /= 2; XSetFont(dpy, gc, xfont->fid); charset = encoding &0xFF; if (IS_16BIT_ENCODING(encoding)) { /* get the real base line / descent */ XTextExtents16(ufont->xFonts[charset], (XChar2b*)segment, seg_data_len, &this_direction, &ascent, &descent, &this_overall); if (imageString) XFillRectangle(dpy, d, gc2, x, y-ufont->ascent, this_overall.width, ufont->ascent+ufont->descent); XDrawString16(dpy, d, gc, x, y, (XChar2b*)segment,seg_data_len); } else { XTextExtents(ufont->xFonts[charset], segment, seg_data_len, &this_direction, &ascent, &descent, &this_overall); if (imageString) XFillRectangle(dpy, d, gc2, x, y-ufont->ascent, this_overall.width, ufont->ascent+ufont->descent); XDrawString(dpy, d, gc, x, y, segment, seg_data_len); } x += this_overall.width; } } void fe_DrawUTF8String(Display *dpy, Drawable d, fe_Font font, GC gc, int x, int y, char *string, int len) { fe_DisplayUTF8String(FALSE, dpy, d, font, gc, NULL, x, y, string, len); } static void fe_DrawUTF8StringImage(Display *dpy, Drawable d, fe_Font font, GC gc, GC gc2, int x, int y, char *string, int len) { fe_DisplayUTF8String(TRUE, dpy, d, font, gc, gc2, x, y, string, len); } int fe_DrawUCS2String(Display *dpy, Drawable d, fe_Font font, GC gc, int x, int y, uint16 *string, int len) { unsigned char *utf8p; int fontAscent, fontDescent, direction; XCharStruct overall; /* * Convert from UCS2 to UTF8 */ utf8p = INTL_UCS2ToUTF8(string, len); if (utf8p == NULL) { return -1; } fe_DisplayUTF8String(FALSE, dpy, d, font, gc, NULL, x, y, utf8p, strlen(utf8p)); fe_UTF8TextExtents(font, utf8p, strlen(utf8p), &direction, &fontAscent, &fontDescent, &overall); free(utf8p); return overall.width; } void fe_UCS2TextExtents(fe_Font font, uint16 *string, int len, int *direction, int *fontAscent, int *fontDescent, XCharStruct *overall) { unsigned char *utf8p; /* * Convert from UCS2 to UTF8 */ utf8p = INTL_UCS2ToUTF8(string, len); if (utf8p == NULL) { *direction = 0; *fontAscent = 0; *fontDescent = 0; overall->width = 0; return; } fe_UTF8TextExtents(font, utf8p, strlen(utf8p), direction, fontAscent, fontDescent, overall); free(utf8p); } XmString XUPF_UCS2ToXmString(uint16 *uniChars, int32 length, fe_Font font, XmFontList *fontList) { fe_UnicodePseudoFont *ufont = (fe_UnicodePseudoFont *)font; unsigned char *utf8p; XmString xmstring; if ((ufont==NULL) || (ufont->tag != UNICODE_PSEUDO_FONT_TAG)) { /* something is wrong. */ return NULL; } /* * Convert from UCS2 to UTF8 */ if (length) { utf8p = INTL_UCS2ToUTF8(uniChars, length); if (utf8p == NULL) { return NULL; } } else utf8p = XP_STRDUP(""); xmstring = fe_utf8_to_XmString(ufont, utf8p, strlen(utf8p), fontList); free(utf8p); return xmstring; } fe_Font XUPF_LoadDefaultFont(Display *dpy) { fe_UnicodePseudoFont *ufont; ufont = fe_LoadUnicodeFont(NULL, "helvetica", 0, 4, 0, CS_LATIN1, 0, 0, dpy); return ufont; } /* * fe_utf8_to_XmString - Convert a utf8 string to a XmString * * Parse the utf8 string into locally displayable encoded segments * and add each segment onto a XmString * * If there are errors display something. * hopefully the user will see the garbage and try a different encoding */ XmString fe_utf8_to_XmString(fe_Font font, char *string, int len, XmFontList *fontList) { fe_UnicodePseudoFont *ufont = (fe_UnicodePseudoFont *)font; unsigned char segment[X11STRING_LIMIT*6]; int16 encoding; char *encoding_name; int parsed_cnt = 0; int this_parsed_cnt, seg_data_len; XmString xm_string = NULL; XmString this_xm_seg, old_xm_string; XFontStruct *xfont; if ((ufont==NULL) || (ufont->tag != UNICODE_PSEUDO_FONT_TAG)) { /* something is wrong. I will just return a guess */ return NULL; } /* * Break up the unicode string into locally sizeable encoded segments */ while (1) { /* get a single encoding string */ this_parsed_cnt = utf8_to_local_encoding(string+parsed_cnt, len-parsed_cnt, segment, sizeof(segment), &seg_data_len, &encoding); if (this_parsed_cnt < 1) /* no more input data */ break; parsed_cnt += this_parsed_cnt; /* * Get update the XmFontList */ if (encoding >= 0) xfont = fe_UnicodeGetXfont(ufont, encoding); else xfont = NULL; /* * Handle errors */ if ((encoding < 0) || (!xfont)) { fe_UnicodeConvertToPlaceHolder(ufont, &encoding, &xfont, segment, seg_data_len); } /* * Add this component to the XmString */ encoding_name = INTL_CsidToCharsetNamePt(encoding); this_xm_seg = XmStringCreateLtoR(segment, encoding_name); if (xm_string) { old_xm_string = xm_string; xm_string = XmStringConcat(old_xm_string, this_xm_seg); XmStringFree(old_xm_string); XmStringFree(this_xm_seg); } else xm_string = this_xm_seg; } /* * handle empty string */ if (xm_string==NULL) { (void)fe_UnicodeGetXfont(ufont, CS_LATIN1); xm_string = XmStringCreateSimple(""); } *fontList = ufont->xmfontlist; return xm_string; } /******************************************************************** New Code ********************************************************************/ /* * these values can be changed to whatever is convenient for Java */ enum { INTL_FontStyleNormal, INTL_FontStyleBold, INTL_FontStyleItalic, INTL_FontStyleBoldItalic }; static XFontStruct * intl_GetFontFace(Display *display, int sizeNum, fe_FontSize *size, int faceNum, char **fontName) { fe_FontFace *face; int i; char *name; XFontStruct *ret; for (i = 0; i < 2; i++, faceNum = 0) { face = size->faces[faceNum]; if (!face) { continue; } if (face->font) { if (fontName) { if (size->size) { *fontName = strdup(face->longXLFDFontName); } else { *fontName = PR_smprintf( face->longXLFDFontName, sizeNum); } } return face->font; } else { if (size->size) { name = strdup(face->longXLFDFontName); } else { name = PR_smprintf(face->longXLFDFontName, sizeNum); } if (!name) { return NULL; } ret = fe_LoadXFont(display, name); if (ret) { face->font = ret; if (fontName) { *fontName = name; } return ret; } } } return NULL; } static XFontStruct * intl_GetFontSize(Display *display, fe_FontFamily *family, int sizeNum, int faceNum, char **fontName) { int closestSize = 0; int firstSize; int i; double minDist; double newDist; XFontStruct *ret; fe_FontSize *size; if (!family->pixelSizes) { return NULL; } if (family->pixelSizes->size) { firstSize = 0; } else { if (family->numberOfPixelSizes == 1) { return intl_GetFontFace(display, sizeNum, family->pixelSizes, faceNum, fontName); } firstSize = 1; } minDist = (1E+36); for (i = firstSize; i < family->numberOfPixelSizes; i++) { size = &family->pixelSizes[i]; newDist = ((sizeNum - size->size) * (sizeNum - size->size)); if (newDist < minDist) { minDist = newDist; closestSize = i; } else { break; } } for (i = 0; i < family->numberOfPixelSizes; i++) { if (closestSize - i >= firstSize) { size = &family->pixelSizes[closestSize - i]; ret = intl_GetFontFace(display, size->size, size, faceNum, fontName); if (ret) { return ret; } } if (closestSize + i < family->numberOfPixelSizes) { size = &family->pixelSizes[closestSize + i]; ret = intl_GetFontFace(display, size->size, size, faceNum, fontName); if (ret) { return ret; } } } if (!family->pixelSizes->size) { return intl_GetFontFace(display, sizeNum, family->pixelSizes, faceNum, fontName); } return NULL; } XFontStruct * intl_GetFont(Display *display, int16 characterSet, char *familyName, char *foundry, int sizeNum, int style, char **fontName) { fe_FontCharSet *charset; int faceNum; fe_FontFamily *family = NULL; int i; int j; fe_FontPitch *pitch; XFontStruct *ret; /* * check the charset */ characterSet &= 0x00ff; if ((0 > characterSet) || (characterSet >= INTL_CHAR_SET_MAX)) { return NULL; } if (fe_CharSetInfoArray[characterSet].type == FE_FONT_TYPE_GROUP) { return NULL; } if (!fe_FontCharSets[characterSet].name) { return NULL; } /* * check the family */ if (!familyName) { familyName = ""; } /* * check the foundry */ if (!foundry) { foundry = ""; } /* * check the size */ if (sizeNum <= 0) { return NULL; } /* * check the style */ switch (style) { case INTL_FontStyleNormal: faceNum = 0; break; case INTL_FontStyleBold: faceNum = 1; break; case INTL_FontStyleItalic: faceNum = 2; break; case INTL_FontStyleBoldItalic: faceNum = 3; break; default: return NULL; } charset = &fe_FontCharSets[characterSet]; /* * iterate over the pitches (proportional and fixed) * and for each pitch, look for the requested family and foundry */ for (i = 0; i < 2; i++) { pitch = &charset->pitches[i]; for (j = 0; j < pitch->numberOfFamilies; j++) { family = &pitch->families[j]; if ((!strcmp(family->family, familyName)) && (!strcmp(family->foundry, foundry))) { ret = intl_GetFontSize(display, family, sizeNum, faceNum, fontName); if (ret) { return ret; } } } } /* * couldn't find the requested family/foundry pair * so try matching just the family */ for (i = 0; i < 2; i++) { pitch = &charset->pitches[i]; for (j = 0; j < pitch->numberOfFamilies; j++) { family = &pitch->families[j]; if (!strcmp(family->family, familyName)) { ret = intl_GetFontSize(display, family, sizeNum, faceNum, fontName); if (ret) { return ret; } } } } /* * couldn't find the requested family * so let's try the one selected in the UI */ for (i = 0; i < 2; i++) { pitch = &charset->pitches[i]; for (j = 0; j < pitch->numberOfFamilies; j++) { family = &pitch->families[j]; if (family->selected) { break; } else { family = NULL; } } if (family) { ret = intl_GetFontSize(display, family, sizeNum, faceNum, fontName); if (ret) { return ret; } } } /* * if we couldn't load the selected family * we try all of the families in turn */ for (i = 0; i < 2; i++) { pitch = &charset->pitches[i]; for (j = 0; j < pitch->numberOfFamilies; j++) { family = &pitch->families[j]; ret = intl_GetFontSize(display, family, sizeNum, faceNum, fontName); if (ret) { return ret; } } } return NULL; } XFontStruct * INTL_GetFont(Display *display, int16 characterSet, char *familyName, char *foundry, int sizeNum, int style) { return intl_GetFont(display, characterSet, familyName, foundry, sizeNum, style, NULL); } static int16 * INTL_GetXCharSetIDs(Display *dpy) { unsigned char *charset; int len; int16 *p; int16 *ret; ret = NULL; if (!fe_LocaleCharSets) { fe_GetLocaleCharSets(dpy); if (!fe_LocaleCharSets) { ret = (int16 *) malloc(2 * sizeof(int16)); if (!ret) { return NULL; } ret[0] = CS_LATIN1; ret[1] = 0; return ret; } } len = 0; charset = fe_LocaleCharSets; while (*charset) { len++; charset++; } ret = (int16 *) malloc((len + 1) * sizeof(int16)); if (!ret) { return NULL; } p = ret; charset = fe_LocaleCharSets; while (*charset) { *p++ = fe_CharSetInfoArray[*charset++].charsetID; } *p = 0; return ret; } char * INTL_GetXFontName(Display *display, int16 characterSet, char *familyName, char *foundry, int sizeNum, int style) { char *fontName; fontName = NULL; (void) intl_GetFont(display, characterSet, familyName, foundry, sizeNum, style, &fontName); return fontName; }